a. elements may not use the \"javascript\" protocol in their \"href\" attributes.",
+ "nl": "Anchor(a.-elementen mogen geen \"javascript\"protocol in hun \"href\"-attributen hebben staan.",
+ "pt-br": "Os elementos de âncora ( a ) não podem usar o protocolo \"javascript\" em seus atributos \"href\"."
+ },
+ "guidelines": [],
+ "tags": [
+ "link",
+ "content"
+ ],
+ "options": {
+ "selector": "a[href^='javascript:']"
+ }
+ },
+ "aSuspiciousLinkText": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Verknüpfungstexte sollten sinnvoll sein",
+ "en": "Link text should be useful",
+ "nl": "Linkteksten moeten bruikbaar en betekenisvol zijn",
+ "pt-br": "Texto do link deve ser útil"
+ },
+ "description": {
+ "de": "Da viele Benutzer von Bildschirmvorleseprogrammen Verknüpfungen verwenden, um in der Seite zu navigieren, erlauben Verknüpfungen mit einfachen Texten (bspw. \"Hier klicken\") keinen Rückschluss auf ihren Zweck.",
+ "en": "Because many users of screen-readers use links to navigate the page, providing links with text that simply read \"click here\" gives no hint of the function of the link.",
+ "nl": "Veel gebruikers van schermlezers gebruiken links om op de pagina te navigeren. Links met de tekst \"klik hier\" zijn voor deze gebruikers niet betekenisvol en niet bruikbaar.",
+ "pt-br": "Como muitos usuários de tela-leitores usam links para navegar na página, fornecendo links com texto que simplesmente ler \"clique aqui\" não dá nenhuma dica da função do link."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H30"
+ ]
+ },
+ "2.4.4": {
+ "techniques": [
+ "H30"
+ ]
+ },
+ "2.4.9": {
+ "techniques": [
+ "H30"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "link",
+ "content"
+ ],
+ "strings": [
+ "suspiciousLinks"
+ ],
+ "callback": "aSuspiciousLinkText"
+ },
+ "aTitleDescribesDestination": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Das Title-Attribut von Verknüpfungen beschreibt das Verknüpfungs-Ziel.",
+ "en": "The title attribute of all source a (anchor) elements describes the link destination.",
+ "nl": "Het titel-attribuut van alle source a (anchor)-elementen beschrijven de bestemming van de link",
+ "pt-br": "O atributo título de todos os elementos (âncora) descrevem o destino do link."
+ },
+ "description": {
+ "de": "Jede Verknüpfung muss ein \"title\"-Attribut haben, welches den Zweck oder das Ziel der Verknüpfung beschreibt.",
+ "en": "Every link must have a \"title\" attribute which describes the purpose or destination of the link.",
+ "nl": "Elke link moet een \"title\"-attribuut hebben waarin het doel of de bestemming van de link wordt beschreven.",
+ "pt-br": "Cada link deve ter um atributo \"title\" que descreve a finalidade ou destino do link."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.9": {
+ "techniques": [
+ "H33",
+ "H25"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "link",
+ "content"
+ ],
+ "options": {
+ "selector": "a[title]"
+ }
+ },
+ "addressForAuthor": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Das Dokument sollte eine korrekte Kontaktadresse zum Autor beinhalten",
+ "en": "The document should contain an address for the author",
+ "nl": "Het document moet een adres voor de auteur bevatten",
+ "pt-br": "O documento deve conter o endereço eletrônico do autor"
+ },
+ "description": {
+ "de": "Dokumente sollten eine korrekte E-Mail-Addresse in einem address-Element enthalten.",
+ "en": "Documents should provide a valid email address within an address element.",
+ "nl": "Documenten moeten een e-mailadres bevatten binnen het address-element.",
+ "pt-br": "Os documentos devem fornecer um endereço de e-mail válido dentro de um elemento address ."
+ },
+ "guidelines": [],
+ "tags": [
+ "document"
+ ],
+ "options": {
+ "selector": "body:not(body:has(address))"
+ }
+ },
+ "addressForAuthorMustBeValid": {
+ "type": "selector",
+ "testability": 0.5,
+ "title": {
+ "de": "Das Dokument sollte eine korrekte E-Mail-Adresse zum Autor beinhalten",
+ "en": "The document should contain a valid email address for the author",
+ "nl": "Het document moet een geldig e-mailadres bevatten voor de auteur",
+ "pt-br": "O documento deve conter um email válido do autor"
+ },
+ "description": {
+ "de": "Dokumente sollten eine korrekte E-Mail-Addresse in einem address-Element enthalten.",
+ "en": "Documents should provide a valid email address within an address element.",
+ "nl": "Documenten moeten een geldig e-mailadres bevatten binnen het address element.",
+ "pt-br": "Os documentos devem fornecer um endereço de e-mail válido dentro de um elemento address."
+ },
+ "guidelines": [],
+ "tags": [
+ "document"
+ ],
+ "options": {
+ "selector": "address"
+ }
+ },
+ "appletContainsTextEquivalent": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Alle Applets sollten den Inhalt im Element des Applets selbst enthalten",
+ "en": "All applets should contain the same content within the body of the applet",
+ "nl": "Alle applets moeten dezelfde content bevatten in de body van de applet",
+ "pt-br": "Todos os applets devem conter o mesmo conteúdo dentro do corpo do applet"
+ },
+ "description": {
+ "de": "Applets sollten ihre Text-Äquivalente oder eine Beschreibung innerhalb des applet code>-Tag selbst enthalten.",
+ "en": "Applets should contain their text equivalents or description within the applet tag itself.",
+ "nl": "Applets moeten hun tekstuele equivalent of beschrijving bevatten in de applet tag.",
+ "pt-br": "As applets devem conter seus equivalentes de texto ou descrição dentro da própria tag applet."
+ },
+ "guidelines": {
+ "508": [
+ "m"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "G74",
+ "H35"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "objects",
+ "applet",
+ "content"
+ ],
+ "callback": "appletContainsTextEquivalent"
+ },
+ "appletContainsTextEquivalentInAlt": {
+ "type": "placeholder",
+ "testability": 0.5,
+ "title": {
+ "de": "Alle Applets sollten ein Text-Äquivalent im \"alt\"-Attribut enthalten",
+ "en": "All applets should contain a text equivalent in the \"alt\" attribute",
+ "nl": "Alle applets moeten een tekstuele equivalent bevatten in het \"alt\"-attribuut",
+ "pt-br": "Todos os applets devem conter um equivalente de texto no atributo \"alt\""
+ },
+ "description": {
+ "de": "Applets sollten ihr Text-Äquivalent oder eine Beschreibung im \"alt\"-Attribut enthalten.",
+ "en": "Applets should contain their text equivalents or description in an \"alt\" attribute.",
+ "nl": "Applets moeten hun tekstuele equivalent of beschrijving bevatten in een \"alt\"-attribuut.",
+ "pt-br": "Os applets devem conter seus equivalentes de texto ou descrição em um atributo \"alt\"."
+ },
+ "guidelines": {
+ "508": [
+ "m"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "G74",
+ "H35"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "objects",
+ "applet",
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "attribute": "alt",
+ "empty": true,
+ "selector": "applet"
+ }
+ },
+ "appletProvidesMechanismToReturnToParent": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Alle Applets sollten einen Weg für Tastatur-Benutzer bieten, um das Applet zu verlassen.",
+ "en": "All applets should provide a way for keyboard users to escape",
+ "nl": "Alle applets moeten door toetsenbordgebruikers kunnen worden verlaten",
+ "pt-br": "Todos os applets devem fornecer uma maneira de escape para os usuários de teclado"
+ },
+ "description": {
+ "de": "Stellen Sie sicher, dass ein Benutzer, der nur eine Tastatur als Eingabegerät besitzt, ein applet code>-Element per Tastaturbefehl verlassen kann. Dies muss manuell getestet werden.",
+ "en": "Ensure that a user who has only a keyboard as an input device can escape an applet element. This requires manual confirmation.",
+ "nl": "Zorg ervoor dat gebruikers die alleen het toetsenbord gebruiken als bediening een applet-element kunnen verlaten. Hiervoor is handmatige bevestiging nodig.",
+ "pt-br": "Assegure-se de que um usuário que tenha apenas um teclado como dispositivo de entrada possa escapar de um elemento applet. Isso requer confirmação manual."
+ },
+ "guidelines": [],
+ "tags": [
+ "objects",
+ "applet",
+ "content"
+ ],
+ "options": {
+ "selector": "applet"
+ }
+ },
+ "appletTextEquivalentsGetUpdated": {
+ "type": "selector",
+ "testability": 0,
+ "guidelines": {
+ "508": [
+ "m"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "G74",
+ "H35"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "objects",
+ "applet",
+ "content"
+ ],
+ "options": {
+ "selector": "applet"
+ }
+ },
+ "appletUIMustBeAccessible": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Jede Benutzerschnittstelle in einem Applet muss barrierefrei sein",
+ "en": "Any user interface in an applet must be accessible",
+ "nl": "Elke user interface in een applet moet toegankelijk zijn",
+ "pt-br": "Qualquer interface de usuário em um applet deve ser acessível"
+ },
+ "description": {
+ "de": "Inhalte in Applets sollten auf Barrierefreiheit geprüft werden.",
+ "en": "Applet content should be assessed for accessibility.",
+ "nl": "Content in een applet moet getoetst worden op toegankelijkheid.",
+ "pt-br": "O conteúdo do applet deve ser avaliado quanto à acessibilidade."
+ },
+ "guidelines": {
+ "508": [
+ "m"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "G74",
+ "H35"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "objects",
+ "applet",
+ "content"
+ ],
+ "options": {
+ "selector": "applet"
+ }
+ },
+ "appletsDoNotFlicker": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Applets sollten nicht flackern oder blinken",
+ "en": "All applets do not flicker",
+ "nl": "Applets knipperen of flitsen niet",
+ "pt-br": "Todos os applets não cintilam"
+ },
+ "description": {
+ "de": "Applets sollten nicht flackern oder blinken.",
+ "en": "Applets should not flicker.",
+ "nl": "Geen enkele applet mag knipperen of flitsen.",
+ "pt-br": "Todos os applets não devem cintilar"
+ },
+ "guidelines": {
+ "508": [
+ "j"
+ ],
+ "wcag": {
+ "2.2.2": {
+ "techniques": [
+ "F7"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "objects",
+ "applet",
+ "content"
+ ],
+ "options": {
+ "selector": "applet"
+ }
+ },
+ "appletsDonotUseColorAlone": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Applets sollten nicht nur Farben verwenden, um Inhalte zu kommunizieren",
+ "en": "Applets should not use color alone to communicate content",
+ "nl": "Applets mogen niet alleen kleur gebruiken om een boodschap over te brengen",
+ "pt-br": "Applets não devem usar uma cor única para comunicar conteúdo"
+ },
+ "description": {
+ "de": "Applets sollten Inhalte so darstellen, das sie ohne Farben verständlich und für farbenblinde Benutzer zugänglich sind.",
+ "en": "Applets should contain content that makes sense without color and is accessible to users who are color blind.",
+ "nl": "Applets moeten content bevatten die ook bruikbaar is zonder kleur en die toegankelijk is voor gebruikers met kleurenblindheid.",
+ "pt-br": "Applets devem conter conteúdo que faz sentido sem cor e é acessível para usuários que são daltônicos."
+ },
+ "guidelines": {
+ "508": [
+ "c"
+ ]
+ },
+ "tags": [
+ "objects",
+ "applet",
+ "content"
+ ],
+ "options": {
+ "selector": "applet"
+ }
+ },
+ "areaAltIdentifiesDestination": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Alle \"area\"-Elementes müssen ein \"alt\"-Attribut haben, welches das Verknüpfungsziel beschreibt",
+ "en": "All \"area\" elements must have an \"alt\" attribute which describes the link destination",
+ "nl": "Alle \"area\"-elementen moeten een \"alt\"-attribuut hebben die de bestemming van de link beschrijft",
+ "pt-br": "Todos os elementos de \"área\" devem ter um atributo \"alt\" que descreve o destino do link"
+ },
+ "description": {
+ "de": "Alle area-Element mit einem map-Element müsssen ein \"alt\"-Attribut haben",
+ "en": "All area elements within a map must have an \"alt\" attribute",
+ "nl": "Alle area-elementen binnen een map moeten een \"alt\"-attribuut hebben.",
+ "pt-br": "Todos os elementos area dentro de um mapa devem ter um atributo \"alt\""
+ },
+ "guidelines": {
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "G74"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "objects",
+ "applet",
+ "content"
+ ],
+ "options": {
+ "selector": "area[alt]"
+ }
+ },
+ "areaAltRefersToText": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Alternativtexte für \"area\"-Elemente sollten den Text wiedergeben, der in den Grafik-Verknüpfungen dargestellt ist",
+ "en": "Alt text for \"area\" elements should replicate the text found in the image",
+ "nl": "Alt-tekst voor \"area\"-elementen moeten de tekst bevatten zoals die ook in de afbeelding staat",
+ "pt-br": "Texto alternativo para elementos \"área\" devem replicar o texto encontrado na imagem"
+ },
+ "description": {
+ "de": "Wenn ein Grafik als map verwendet wird und ein area-Element den Text im Grafik umschließt, sollte das \"alt\"-Attribut dieser area denselben Text enthalten, wie der im Grafik dargestellte Text.",
+ "en": "If an image is being used as a map, and an area encompasses text within the image, then the \"alt\" attribute of that area element should be the same as the text found in the image.",
+ "nl": "Als een afbeelding als kaart wordt gebruikt, en een area bevat tekst binnen de afbeelding, dan moet het \"alt\"-attribuut van dat area-element hetzelfde zijn als de tekst die in de afbeelding staat.",
+ "pt-br": "Se uma imagem está sendo usada como um mapa e uma área code> abrange texto dentro da imagem, então o atributo \"alt\" desse elemento area code> deve ser o mesmo que o texto encontrado na imagem."
+ },
+ "guidelines": [],
+ "tags": [
+ "imagemap",
+ "content"
+ ],
+ "options": {
+ "selector": "area"
+ }
+ },
+ "areaDontOpenNewWindow": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Kein \"area\"-Element sollte ein neues Fenster ohne Warnung öffnen",
+ "en": "No \"area\" elements should open a new window without warning",
+ "nl": "\"area\"-elementen mogen geen nieuw scherm openen zonder melding",
+ "pt-br": "Nenhum elemento \"área\" deve abrir uma nova janela sem aviso prévio"
+ },
+ "description": {
+ "de": "area-Elemente sollte ein neues Fenster nicht ohne vorhergehende Warnung öffnen.",
+ "en": "No area elements should open a new window without warning.",
+ "nl": "area-elementen mogen geen nieuw scherm openen zonder dat de gebruiker hiervan een melding krijgt.",
+ "pt-br": "Nenhum elemento area code> deve abrir uma nova janela sem aviso prévio."
+ },
+ "guidelines": [],
+ "tags": [
+ "imagemap",
+ "content"
+ ],
+ "options": {
+ "selector": "area[target='new window'], area[target=_new], area[target=_blank], area[target=_blank]"
+ }
+ },
+ "areaHasAltValue": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"area\"-Elemente müssen ein \"alt\"-Attribut haben",
+ "en": "All \"area\" elements must have an \"alt\" attribute",
+ "nl": "Alle \"area\"-elementen moeten een \"alt\"-attribuut hebben",
+ "pt-br": "Todos os elementos de \"área\" devem ter um atributo \"alt\""
+ },
+ "description": {
+ "de": "Alle area-Elemente in einem map-Element müssen ein \"alt\"-Attribut haben.",
+ "en": "All area elements within a map must have an \"alt\" attribute.",
+ "nl": "Alle area-elementen binnen een map moeten een \"alt\"-attribuut hebben.",
+ "pt-br": "Todos os elementos area dentro de um mapa code> devem ter um atributo \"alt\"."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "F65",
+ "G74",
+ "H24"
+ ]
+ },
+ "1.4.3": {
+ "techniques": [
+ "G145"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "imagemap",
+ "content"
+ ],
+ "options": {
+ "selector": "area",
+ "test": ":not(area[alt])"
+ }
+ },
+ "areaLinksToSoundFile": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"area\"-Elemente mit einer Verknüpfung zu einer Audio-Datei sollten auch eine Verknüpfung zu einem Transkript enthalten",
+ "en": "All \"area\" elements which link to a sound file should also provide a link to a transcript",
+ "nl": "Alle \"area\"-elementen met een link naar een geluidsbestand moeten ook een link bevatten naar een transcriptie",
+ "pt-br": "Todos os elementos de \"area\" que ligam a um arquivo de som devem também fornecer um link para uma transcrição"
+ },
+ "description": {
+ "de": "Alle \"area\"-Elemente mit einer Verknüpfung Audio-Datei sollten eine Verknüpfung zu einem Transkript haben.",
+ "en": "All area elements which link to a sound file should have a text transcript.",
+ "nl": "Alle \"area\"-elementen met een link naar een geluidsbestand moeten een transcriptie hebben in tekst.",
+ "pt-br": "Todos os elementos area que ligam a um arquivo de som devem ter uma transcrição de texto."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "G74"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "imagemap",
+ "media",
+ "content"
+ ],
+ "options": {
+ "selector": "area[href$=wav], area[href$=snd], area[href$=mp3], area[href$=iff], area[href$=svx], area[href$=sam], area[href$=smp], area[href$=vce], area[href$=vox], area[href$=pcm], area[href$=aif]"
+ }
+ },
+ "ariaOrphanedContent": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Seiten mit ARIA-roles sollten keinen verwaisten Inhalt haben",
+ "en": "Pages using ARIA roles should not have orphaned content",
+ "nl": "Pagina's die ARIA-rollen gebruiken mogen geen verweesde content hebben",
+ "pt-br": "Páginas que usam funções ARIA não devem ter conteúdo orfão"
+ },
+ "description": {
+ "de": "Wenn eine Seite ARIA-roles verwendet, sollte es keinen Seiteninhalt ohne ARIA-role geben, da dies fehlerhafte Darstellungen in Bildschirmleseprogrammen bewirken kann.",
+ "en": "If a page makes use of ARIA roles, then there should not be any content on the page which is not within an element that exposes a role, as it could cause that content to be rendreed inaccessible to users with screen readers.",
+ "nl": "Als een pagina gebruik maakt van ARIA-rollen, mag er geen content op de pagina staan buiten een element dat een rol vertegenwoordigt. In dat geval kan het zijn dat deze content niet toegankelijk is voor gebruikers van schermlezers.",
+ "pt-br": "Se uma página fizer uso de funções ARIA, então não deve haver nenhum conteúdo na página que não esteja dentro de um elemento que expõe uma função, pois poderia causar que o conteúdo fosse tornado inacessível para usuários com leitores de tela."
+ },
+ "guidelines": [],
+ "tags": [
+ "aria",
+ "content"
+ ],
+ "callback": "ariaOrphanedContent"
+ },
+ "basefontIsNotUsed": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Basefont sollte nicht verwendet werden",
+ "en": "Basefont should not be used",
+ "nl": "Basefont moet niet worden gebruikt",
+ "pt-br": "Basefont não deve ser usado"
+ },
+ "description": {
+ "de": "Der basefont-Tag ist deprecated und sollte nicht verwendet werden. Verwenden Sie besser Stylesheets.",
+ "en": "The basefont tag is deprecated and should not be used. Investigate using stylesheets instead.",
+ "nl": "The basefont-tag is afgekeurd en moet niet worden gebruikt. Gebruik in plaats hiervan stylesheets.",
+ "pt-br": "A tag basefont está obsoleta e não deve ser usada. Investigue usando folhas de estilo."
+ },
+ "guidelines": [],
+ "tags": [
+ "document",
+ "deprecated"
+ ],
+ "options": {
+ "selector": "basefont"
+ }
+ },
+ "blinkIsNotUsed": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Der \"blink\"-Tag sollte nicht verwendet werden",
+ "en": "The \"blink\" tag should not be used",
+ "nl": "De \"blink\"-tag moet niet worden gebruikt",
+ "pt-br": "A tag \"blink\" não deve ser usada"
+ },
+ "description": {
+ "de": "Der blink-Tag sollte niemals verwendet werden.",
+ "en": "The blink tag should not be used. Ever.",
+ "nl": "Het is nooit toegestaan om de \"blink\"-tag te gebruiken.",
+ "pt-br": "A tag blink code> não deve ser usada. Nunca."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.2.2": {
+ "techniques": [
+ "F47"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "deprecated",
+ "content"
+ ],
+ "options": {
+ "selector": "blink"
+ }
+ },
+ "blockquoteNotUsedForIndentation": {
+ "type": "selector",
+ "testability": 0.5,
+ "title": {
+ "de": "Der \"blockquote\"-Tag sollte nicht zur Einrückung verwnendet werden",
+ "en": "The block quote should not be used just for indentation",
+ "nl": "De \"blockquote\"-tag mag niet gebruikt worden om in te springen",
+ "pt-br": "A citação de bloco não deve ser usada apenas para indentação"
+ },
+ "description": {
+ "de": "Blockquotes sind für längere Zitate gedacht und sollten nicht zum Einrücken von Text verwendet werden.",
+ "en": "Blockquote tags are for longer quotes, and should not be used to indent text.",
+ "nl": "Blockquotes zijn bedoeld voor lange stukken geciteerde tekst, en niet om tekst te laten inspringen.",
+ "pt-br": "As tags Blockquote são para citações mais longas e não devem ser usadas para recuar texto."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "H49"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "blockquote",
+ "content"
+ ],
+ "options": {
+ "selector": "blockquote:not(blockquote[cite])"
+ }
+ },
+ "blockquoteUseForQuotations": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Für längere Zitate sollte das \"blockquote\"-Element verwendet werden",
+ "en": "If long quotes are in the document, use the \"blockquote\" element to mark them",
+ "nl": "Gebruik voor lange citaten in het document het \"blockquote\"-element",
+ "pt-br": "e as citações longas estiverem no documento, use o elemento \"blockquote\" para marcá-las"
+ },
+ "description": {
+ "de": "Wenn längere Zitate über einen Absatz wiedergegeben werden sollen, sollte das \"blockquote\"-Element verwendet werden.",
+ "en": "If there is a paragraph or more of a quote, use the blockquote element to mark it as such.",
+ "nl": "Als er een hele alinea of meer alinea's zijn van geciteerde tekst, gebruik dan blockquote om deze als zodanig te markeren.",
+ "pt-br": "Se houver um parágrafo ou mais de uma citação, use o elemento blockquote para marcá-lo como tal."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "H49"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "blockquote",
+ "content"
+ ],
+ "callback": "blockquoteUseForQuotations"
+ },
+ "boldIsNotUsed": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Das \"b\"-Element (fett) wird nicht verwendet.",
+ "en": "The \"b\" (bold) element is not used",
+ "nl": "Het \"b\"-element (bold) wordt niet gebruikt",
+ "pt-br": "O elemento \"b \" (negrito) não é usado"
+ },
+ "description": {
+ "de": "Das b-Element bietet keine Hervorhebung für sehbehinderte Benutzer. Das strong-Element sollte anstelle dessen verwendet werden.",
+ "en": "The b (bold) element provides no emphasis for non-sighted readers. Use the strong tag instead.",
+ "nl": "Het b-element voorziet niet in nadruk voor blinde en slechtziende gebruikers. Gebruik de strong-tag instead.",
+ "pt-br": "O elemento b code> (negrito) não dá ênfase aos leitores não-videntes. Use a tag strong code> em vez disso."
+ },
+ "guidelines": [],
+ "tags": [
+ "semantics",
+ "content"
+ ],
+ "options": {
+ "selector": "bold"
+ }
+ },
+ "buttonHasName": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Schaltflächen sollten beschriftet sein",
+ "en": "Button should contain text",
+ "nl": "Een knop moet tekst bevatten",
+ "pt-br": "Botões devem conter texto"
+ },
+ "description": {
+ "de": "Schaltflächen sollten eine Beschriftung im Element oder im \"value\"-Attribut enthalten.",
+ "en": "Buttons should contain a text value within the element, or have a value attribute.",
+ "nl": "Knoppen moeten een tekstwaarde binnen het element hebben, of een waarde-attribuut.",
+ "pt-br": "Os botões devem conter um valor de texto dentro do elemento ou ter um atributo de valor."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.1.1": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "4.1.2": {
+ "techniques": [
+ "H91"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "content": true,
+ "empty": true,
+ "attribute": "title",
+ "selector": "button"
+ }
+ },
+ "checkboxHasLabel": {
+ "type": "label",
+ "testability": 1,
+ "title": {
+ "de": "Alle Checkboxen muüssen ein dazugehöriges Label haben",
+ "en": "All checkboxes must have a corresponding label",
+ "nl": "Alle keuzevakjes moeten een bijbehorend label hebben",
+ "pt-br": "Todas as caixas de seleção devem ter um rótulo correspondente"
+ },
+ "description": {
+ "de": "Alle input-Elemente vom Typ \"checkbox\" sollten ein dazugehöriges label-Element haben. Bildschirmleseprogramme haben oftmals eine Formular-Modus, in dem nur Labels vorgelesen werden.",
+ "en": "All input elements with a type of \"checkbox\" should have a corresponding label element. Screen readers often enter a \"form mode\" where only label text is read aloud to the user",
+ "nl": "Alle input-elementen met een \"keuzevakje\" moeten een bijbehorend label-element hebben. Schermlezers maken vaak gebruik van een \"formuliereninstelling\" waarbij alleen de tekst van de labels hardop aan de gebruiker wordt voorgelezen.",
+ "pt-br": "Todos os elementos input code> com um tipo de \"checkbox\" devem ter um elemento label code> correspondente. Os leitores de tela costumam entrar em um \"modo de formulário\" onde somente o texto do rótulo é lido em voz alta para o usuário"
+ },
+ "guidelines": {
+ "508": [
+ "c"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H44"
+ ]
+ },
+ "1.3.1": {
+ "techniques": [
+ "H44",
+ "F68"
+ ]
+ },
+ "2.1.1": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "3.3.2": {
+ "techniques": [
+ "H44"
+ ]
+ },
+ "4.1.2": {
+ "techniques": [
+ "H44",
+ "H91"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "label"
+ ],
+ "options": {
+ "selector": "input[type=checkbox]"
+ }
+ },
+ "checkboxLabelIsNearby": {
+ "type": "labelProximity",
+ "testability": 0.5,
+ "title": {
+ "de": "Alle \"checkbox\"-Elemente sollten ein dazugehöriges Label haben",
+ "en": "All \"checkbox\" input elements have a label that is close",
+ "nl": "Van alle \"keuzevakjes\" invoerelementen staat het label in de buurt",
+ "pt-br": "Todos os elementos de entrada \"checkbox\" têm um rótulo que está próximo"
+ },
+ "description": {
+ "de": "Alle Eingabeelemente vom Typ \"checkbox\" müssen ein dazugehöriges Label haben das in der Nähe des Eingabeelements positioniert ist. Nutzer von Bildschirmvergrößerung oder mit reduzierten räumlichen Fähigkeiten werden bei der Verwendung eines Formularelements behindert, wenn das Label für das Element weit entfernt positioniert ist.",
+ "en": "All input elements of type \"checkbox\" must have a corresponding label that is close to the form element. Users of screen magnification or with reduced spatial skills are hampered in using a form element if the label for that element is located far away.",
+ "nl": "Alle inputelementen van het type \"keuzevakje\" moeten een bijbehorend label hebben dat dicht bij het formulierelement staat. Gebruikers die het scherm vergroten of met beperkte ruimtelijke vaardigheden kunnen een formulier niet gebruiken als het label van een veld te ver weg staat.",
+ "pt-br": "Todos os elementos de entrada do tipo \"checkbox\" devem ter um rótulo correspondente próximo ao elemento do formulário. Usuários de ampliação de tela ou com habilidades espaciais reduzidas são impedidos de usar um elemento de formulário se o rótulo para esse elemento estiver localizado longe."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "labelProximity"
+ ],
+ "options": {
+ "selector": "input[type=checkbox]"
+ }
+ },
+ "closingTagsAreUsed": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Alle schließenden Tags müssen vorhanden sein, wenn erforderlich",
+ "en": "All tags that require closing tags have closing tags",
+ "nl": "Alle tags die een afsluitende tag behoeven, hebben een afsluitende tag",
+ "pt-br": "Todas as tags que exigem tags de fechamento têm tags de fechamento"
+ },
+ "description": {
+ "de": "Wenn Tags wie p, ul or li verwendet werden, müssen sie einen schließenden Tag besitzen.",
+ "en": "When using tags such as p, ul, or li, there must be a closing tag.",
+ "nl": "Gebruik voor tags als p, ul, of li altijd een afsluitende tag, dus /p, /ul, /li.",
+ "pt-br": "Ao usar tags como p, ul ou li, deve haver uma tag de fechamento, tal como /p, /ul, /li."
+ },
+ "guidelines": {
+ "wcag": {
+ "4.1.1": {
+ "techniques": [
+ "H74"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "html"
+ ],
+ "components": [
+ "htmlSource"
+ ],
+ "callback": "closingTagsAreUsed"
+ },
+ "contentPositioningShouldNotChangeMeaning": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Bedeutung sollte nicht über Positionierung gegeben werden",
+ "en": "Meaning should not be created through positioning",
+ "nl": "Cre�er geen betekenis door positionering",
+ "pt-br": "O significado não deve ser criado através do posicionamento"
+ },
+ "description": {
+ "de": "Die Position sollte nicht die Bedeutung eines Elementes verändern.",
+ "en": "Positioning should not be used to change the meaning of an element.",
+ "nl": "Positionering moet niet worden gebruikt om de betekenis van een element te veranderen.",
+ "pt-br": "O posicionamento não deve ser usado para alterar o significado de um elemento."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.2": {
+ "techniques": [
+ "C6",
+ "F1",
+ "G57"
+ ]
+ },
+ "1.4.5": {
+ "techniques": [
+ "C6"
+ ]
+ },
+ "1.4.9": {
+ "techniques": [
+ "C6"
+ ]
+ },
+ "2.4.1": {
+ "techniques": [
+ "C6"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "content",
+ "structure"
+ ],
+ "callback": "contentPositioningShouldNotChangeMeaning"
+ },
+ "cssDocumentMakesSenseStyleTurnedOff": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Das Dokument muss lesbar sein, wenn die Stylesheets deaktiviert sind",
+ "en": "The document must be readable with styles turned off",
+ "nl": "Het document moet leesbaar zijn met stijlen uit",
+ "pt-br": "O documento deve ser legível com estilos desligados"
+ },
+ "description": {
+ "de": "Wenn alle Stylesheets für die Seite deaktiviert sind, sollte der Inhalt der Seite immernoch sinnvoll sein. Versuchen Sie die Stylesheets zu deaktivieren und prüfen Sie, ob der Inhalt dann noch lesbar und verständlich ist.",
+ "en": "With all the styles for a page turned off, the content of the page should still make sense. Try to turn styles off in the browser and see if the page content is readable and clear.",
+ "nl": "Als alle stijlen voor een pagina zijn uitgezet, moet de content van de pagina nog steeds betekenisvol zijn. Zet stijlen uit in de browser en controleer of de content op de pagina nog steeds leesbaar en duidelijk is.",
+ "pt-br": "Com todos os estilos para uma página desativada, o conteúdo da página ainda deve fazer sentido. Tente desativar estilos no navegador e verifique se o conteúdo da página é legível e claro."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "G140"
+ ]
+ },
+ "1.4.5": {
+ "techniques": [
+ "G140"
+ ]
+ },
+ "1.4.9": {
+ "techniques": [
+ "G140"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "color"
+ ],
+ "options": {
+ "selector": "link[rel=stylesheet], stylesheet, *[style]"
+ }
+ },
+ "colorFontContrast": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Alle Elemente sollten einen angemessenen Farbkontrast haben",
+ "en": "All elements should have appropriate color contrast",
+ "nl": "Alle elementen moeten een toepasselijk kleurcontract hebben",
+ "pt-br": "Todos os elementos devem ter o contraste de cor apropriado"
+ },
+ "description": {
+ "de": "Für farbenblinde Benutzer sollten alle Texte und andere Elemente ein Kontrastverhältnis von 5:1 haben.",
+ "en": "For users who have color blindness, all text or other elements should have a color contrast of 5:1.",
+ "nl": "Voor gebruikers met kleurenblindheid moeten alle tekst- en andere elementen een kleurcontrast hebben van 5:1.",
+ "pt-br": "Para usuários que têm daltonismo, todos os textos ou outros elementos devem ter um contraste de cor de 5:1."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.4.3": {
+ "techniques": [
+ "G18"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "color"
+ ],
+ "callback": [
+ "colorFontContrast"
+ ],
+ "options": {
+ "algorithm": "wcag",
+ "selector": "*",
+ "gradientSampleMultiplier": 3
+ }
+ },
+ "colorElementBehindContrast": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Alle Elemente sollten einen angemessenen Farbkontrast haben",
+ "en": "All elements should have appropriate color contrast",
+ "nl": "Alle elementen moeten een toepasselijk kleurcontract hebben",
+ "pt-br": "Todos os elementos devem ter o contraste de cor apropriado"
+ },
+ "description": {
+ "de": "Für farbenblinde Benutzer sollten alle Texte und andere Elemente ein Kontrastverhältnis von 5:1 haben.",
+ "en": "For users who have color blindness, all text or other elements should have a color contrast of 5:1.",
+ "nl": "Voor gebruikers met kleurenblindheid moeten alle tekst- en andere elementen een kleurcontrast hebben van 5:1.",
+ "pt-br": "Para usuários que têm daltonismo, todos os textos ou outros elementos devem ter um contraste de cor de 5:1."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.4.3": {
+ "techniques": [
+ "G18"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "color"
+ ],
+ "callback": [
+ "colorElementBehindContrast"
+ ],
+ "options": {
+ "algorithm": "wcag",
+ "selector": "*",
+ "gradientSampleMultiplier": 3
+ }
+ },
+ "colorBackgroundImageContrast": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Alle Elemente sollten einen angemessenen Farbkontrast haben",
+ "en": "All elements should have appropriate color contrast",
+ "nl": "Alle elementen moeten een toepasselijk kleurcontract hebben",
+ "pt-br": "Todos os elementos devem ter o contraste de cor apropriado"
+ },
+ "description": {
+ "de": "Für farbenblinde Benutzer sollten alle Texte und andere Elemente ein Kontrastverhältnis von 5:1 haben.",
+ "en": "For users who have color blindness, all text or other elements should have a color contrast of 5:1.",
+ "nl": "Voor gebruikers met kleurenblindheid moeten alle tekst- en andere elementen een kleurcontrast hebben van 5:1.",
+ "pt-br": "Para usuários que têm daltonismo, todos os textos ou outros elementos devem ter um contraste de cor de 5:1."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.4.3": {
+ "techniques": [
+ "G18"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "color"
+ ],
+ "callback": [
+ "colorBackgroundImageContrast"
+ ],
+ "options": {
+ "algorithm": "wcag",
+ "selector": "*",
+ "gradientSampleMultiplier": 3
+ }
+ },
+ "colorElementBehindBackgroundImageContrast": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Alle Elemente sollten einen angemessenen Farbkontrast haben",
+ "en": "All elements should have appropriate color contrast",
+ "nl": "Alle elementen moeten een toepasselijk kleurcontract hebben",
+ "pt-br": "Todos os elementos devem ter o contraste de cor apropriado"
+ },
+ "description": {
+ "de": "Für farbenblinde Benutzer sollten alle Texte und andere Elemente ein Kontrastverhältnis von 5:1 haben.",
+ "en": "For users who have color blindness, all text or other elements should have a color contrast of 5:1.",
+ "nl": "Voor gebruikers met kleurenblindheid moeten alle tekst- en andere elementen een kleurcontrast hebben van 5:1.",
+ "pt-br": "Para usuários que têm daltonismo, todos os textos ou outros elementos devem ter um contraste de cor de 5:1."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.4.3": {
+ "techniques": [
+ "G18"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "color"
+ ],
+ "callback": [
+ "colorElementBehindBackgroundImageContrast"
+ ],
+ "options": {
+ "algorithm": "wcag",
+ "selector": "*",
+ "gradientSampleMultiplier": 3
+ }
+ },
+ "colorBackgroundGradientContrast": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Alle Elemente sollten einen angemessenen Farbkontrast haben",
+ "en": "All elements should have appropriate color contrast",
+ "nl": "Alle elementen moeten een toepasselijk kleurcontract hebben",
+ "pt-br": "Todos os elementos devem ter o contraste de cor apropriado"
+ },
+ "description": {
+ "de": "Für farbenblinde Benutzer sollten alle Texte und andere Elemente ein Kontrastverhältnis von 5:1 haben.",
+ "en": "For users who have color blindness, all text or other elements should have a color contrast of 5:1.",
+ "nl": "Voor gebruikers met kleurenblindheid moeten alle tekst- en andere elementen een kleurcontrast hebben van 5:1.",
+ "pt-br": "Para usuários que têm daltonismo, todos os textos ou outros elementos devem ter um contraste de cor de 5:1."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.4.3": {
+ "techniques": [
+ "G18"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "color"
+ ],
+ "callback": [
+ "colorBackgroundGradientContrast"
+ ],
+ "options": {
+ "algorithm": "wcag",
+ "selector": "*",
+ "gradientSampleMultiplier": 3
+ }
+ },
+ "colorElementBehindBackgroundGradientContrast": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Alle Elemente sollten einen angemessenen Farbkontrast haben",
+ "en": "All elements should have appropriate color contrast",
+ "nl": "Alle elementen moeten een toepasselijk kleurcontract hebben",
+ "pt-br": "Todos os elementos devem ter o contraste de cor apropriado"
+ },
+ "description": {
+ "de": "Für farbenblinde Benutzer sollten alle Texte und andere Elemente ein Kontrastverhältnis von 5:1 haben.",
+ "en": "For users who have color blindness, all text or other elements should have a color contrast of 5:1.",
+ "nl": "Voor gebruikers met kleurenblindheid moeten alle tekst- en andere elementen een kleurcontrast hebben van 5:1.",
+ "pt-br": "Para usuários que têm daltonismo, todos os textos ou outros elementos devem ter um contraste de cor de 5:1."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.4.3": {
+ "techniques": [
+ "G18"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "color"
+ ],
+ "callback": [
+ "colorElementBehindBackgroundGradientContrast"
+ ],
+ "options": {
+ "algorithm": "wcag",
+ "selector": "*",
+ "gradientSampleMultiplier": 3
+ }
+ },
+ "definitionListsAreUsed": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Eine Definitionsliste sollte zum definieren von Begriffen verwendet werden",
+ "en": "Use a definition list for defining terms",
+ "nl": "Gebruik een definition list voor definities",
+ "pt-br": "Use uma lista de definições para definir termos"
+ },
+ "description": {
+ "de": "Das \"dl\"-Element sollte verwendet werden, um eine Definitionsliste zum definieren von Begriffen zu erstellen",
+ "en": "When providing a list of terms or definitions, use a definition list.",
+ "nl": "Wanneer er gebruik wordt gemaakt van een lijst termen of definities, gebruik hiervoor dan een definition list.",
+ "pt-br": "Ao fornecer uma lista de termos ou definições, use uma lista de definições."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "H48"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "structure"
+ ],
+ "callback": "definitionListsAreUsed"
+ },
+ "doctypeProvided": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Das Dokument sollte eine valide \"doctype\"-Deklaration enthalten",
+ "en": "The document should contain a valid \"doctype\" declaration",
+ "nl": "Het document moet een geldige \"doctype\"-verklaring hebben",
+ "pt-br": "O documento deve conter uma declaração \"doctype\" válida"
+ },
+ "description": {
+ "de": "Jedes Dokument muss eine valide DOCTYPE-Deklaration enthalten.",
+ "en": "Each document must contain a valid doctype declaration.",
+ "nl": "Ieder document moet een geldige doctype-verklaring hebben.",
+ "pt-br": "Cada documento deve conter uma declaração válida de doctype."
+ },
+ "guidelines": [],
+ "tags": [
+ "doctype"
+ ],
+ "callback": "doctypeProvided"
+ },
+ "documentAbbrIsUsed": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Abkürzungen müssen mit einem \"abbr\"-Element gekennzeichnet werden",
+ "en": "Abbreviations must be marked with an \"abbr\" element",
+ "nl": "Afkortingen moeten worden gemarkeerd met een \"abbr\"-element",
+ "pt-br": "As abreviações devem ser marcadas com um elemento \"abbr\""
+ },
+ "description": {
+ "de": "Abkürzungen sollten mindestens einmal pro Seite mit einem abbr-Element gekennzeichnet werden.",
+ "en": "Abbreviations should be marked with an abbr element, at least once on the page for each abbreviation.",
+ "nl": "Afkortingen moeten worden gemarkeerd door middel van het abbr-element. Doe dit ten minste een keer per pagina voor elke afkorting.",
+ "pt-br": "As abreviações devem ser marcadas com um elemento abbr, pelo menos uma vez na página para cada abreviatura."
+ },
+ "guidelines": {
+ "wcag": {
+ "3.1.4": {
+ "techniques": [
+ "H28"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "acronym",
+ "content"
+ ],
+ "components": [
+ "acronym"
+ ],
+ "callback": "documentAbbrIsUsed"
+ },
+ "documentAcronymsHaveElement": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Akronyme müssen mit einem \"acronym\"-Element gekennzeichnet werden",
+ "en": "Acronyms must be marked with an \"acronym\" element",
+ "nl": "Acroniemen moeten worden gemarkeerd met een \"acronym\"-element",
+ "pt-br": "As siglas devem ser marcadas com um elemento \"acronym\""
+ },
+ "description": {
+ "de": "Akronyme sollten mindestens einmal pro Seite mit einem acronym-Element gekennzeichnet werden.",
+ "en": "Acronyms should be marked with an acronym element, at least once on the page for each acronym.",
+ "nl": "Acroniemen moeten worden gemarkeerd door middel van het acronym-element. Doe dit ten minste een keer per pagina voor elke acroniem.",
+ "pt-br": "As siglas devem ser marcadas com um elemento acronym, pelo menos uma vez na página de cada acrônimo."
+ },
+ "guidelines": {
+ "wcag": {
+ "3.1.4": {
+ "techniques": [
+ "H28"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "acronym",
+ "content"
+ ],
+ "components": [
+ "acronym"
+ ],
+ "callback": "documentAcronymsHaveElement"
+ },
+ "documentAutoRedirectNotUsed": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Automatische Umleitungen per \"meta\"-Elements sind unzulässig",
+ "en": "Auto-redirect with \"meta\" elements must not be used",
+ "nl": "Auto-redirect met \"meta\"-elementen moeten niet worden gebruikt",
+ "pt-br": "Redirecionamento automático com elementos \"meta\" não deve ser usado"
+ },
+ "description": {
+ "de": "Weil Benutzer unterschiedliche Geschwindigkeiten und Fähigkeiten haben, wenn es um das Erfassen von Inhalten einer Seite geht, kann die \"meta-refresh\"-Methode dazu führen, dass Benutzer den Inhalt nicht vollständig verstehen, bevor sie umgeleitet werden.",
+ "en": "Because different users have different speeds and abilities when it comes to parsing the content of a page, a \"meta-refresh\" method to redirect users can prevent users from fully understanding the document before being redirected.",
+ "nl": "Omdat verschillende gebruikers verschillende snelheden en vaardigheden hebben met het scannen van content op een pagina, kan een \"meta-refresh\"-methode om gebruikers door te sturen hen verhinderen het document volledig te begrijpen voor ze worden doorgestuurd.",
+ "pt-br": "Como diferentes usuários têm diferentes velocidades e habilidades quando se trata de analisar o conteúdo de uma página, um método de \"meta-atualização\" para redirecionar os usuários pode impedir que os usuários entendam completamente o documento antes de serem redirecionados."
+ },
+ "guidelines": [],
+ "tags": [
+ "document"
+ ],
+ "options": {
+ "selector": "meta[http-equiv=refresh]"
+ }
+ },
+ "documentContentReadableWithoutStylesheets": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Inhalte sollten ohne Stylesheets lesbar sein",
+ "en": "Content should be readable without style sheets",
+ "nl": "Content moet zonder stylesheets leesbaar zijn",
+ "pt-br": "O conteúdo deve ser legível sem folhas de estilo"
+ },
+ "description": {
+ "de": "Wenn alle Stylesheets für die Seite deaktiviert sind, sollte der Inhalt der Seite immernoch sinnvoll sein. Versuchen Sie die Stylesheets zu deaktivieren und prüfen Sie, ob der Inhalt dann noch lesbar und verständlich ist.",
+ "en": "With all the styles for a page turned off, the content of the page should still make sense. Try to turn styles off in the browser and see if the page content is readable and clear.",
+ "nl": "Ook als alle stijlen voor een pagina zijn uitgezet, moet de content van de pagina nog steeds betekenisvol zijn. Zet de stylesheets uit in de browser en controleer of de content nog steeds leesbaar en duidelijk is.",
+ "pt-br": "Com todos os estilos para uma página desativada, o conteúdo da página ainda deve fazer sentido. Tente desativar estilos no navegador e verifique se o conteúdo da página é legível e claro."
+ },
+ "guidelines": {
+ "508": [
+ "d"
+ ],
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "G140"
+ ]
+ },
+ "1.4.5": {
+ "techniques": [
+ "G140"
+ ]
+ },
+ "1.4.9": {
+ "techniques": [
+ "G140"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "document",
+ "color"
+ ],
+ "options": {
+ "selector": "html:has(link[rel=stylesheet], style) body, body:has(*[style])"
+ }
+ },
+ "documentHasTitleElement": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Das Dokument sollte ein \"title\"-Element haben",
+ "en": "The document should have a title element",
+ "nl": "Het document moet een titelelement hebben",
+ "pt-br": "O documento deve ter um elemento de título"
+ },
+ "description": {
+ "de": "Das Dokument sollte ein \"title\"-Element haben",
+ "en": "The document should have a title element.",
+ "nl": "Het document moet een titelelement hebben.",
+ "pt-br": "O documento deve ter um elemento de título."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.2": {
+ "techniques": [
+ "H25"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "document",
+ "head"
+ ],
+ "options": {
+ "selector": "html:not(html:has(title))"
+ }
+ },
+ "documentIDsMustBeUnique": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"id\"-Attribute von Elementen müssen einmalig sein",
+ "en": "All element \"id\" attributes must be unique",
+ "nl": "Alle element \"id\"-attributen moeten uniek zijn",
+ "pt-br": "Todos os atributos \"id\" dos elementos devem ser único"
+ },
+ "description": {
+ "de": "Alle \"id\"-Attribute von Elementen müssen einmalig sein",
+ "en": "Element \"id\" attributes must be unique.",
+ "nl": "Element \"id\"-attributen moeten uniek zijn.",
+ "pt-br": "O atributo \"id\" de um elemento deve ser único"
+ },
+ "guidelines": {
+ "wcag": {
+ "4.1.1": {
+ "techniques": [
+ "F77",
+ "H93"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "document",
+ "semantics"
+ ],
+ "callback": "documentIDsMustBeUnique"
+ },
+ "documentIsWrittenClearly": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Das Dokument sollte zur Zielgruppe passend geschrieben und deutlich lesbar sein.",
+ "en": "The document should be written to the target audience and read clearly",
+ "nl": "Het document moet geschreven zijn op het niveau van de doelgroep",
+ "pt-br": "O documento deve ser escrito para o público-alvo e ser lido claramente"
+ },
+ "description": {
+ "de": "Bei umfangreichen Dokumenten sollte eine Zusammenfassung oder eine Hilfestellung für das Verständnis des Inhalts vorgesehen werden.",
+ "en": "If a document is beyond a 10th grade level, then a summary or other guide should also be provided to guide the user through the content.",
+ "nl": "Als de inhoud van een document moeilijker is dan het vastgestelde taalniveau, moet een samenvatting of andere begeleiding worden toegevoegd om de gebruiker te helpen met de content.",
+ "pt-br": "Se um documento está além de um nível de 10ª série, um guia de resumo ou outro também deve ser fornecido para orientar o usuário através do conteúdo."
+ },
+ "guidelines": {
+ "wcag": {
+ "3.1.5": {
+ "techniques": [
+ "G86"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "language",
+ "content"
+ ],
+ "components": [
+ "textStatistics"
+ ],
+ "callback": "documentIsWrittenClearly"
+ },
+ "documentLangIsISO639Standard": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Das \"language\"-Attribut des Dokumentes sollte einen ISO-Standardcode enthalten",
+ "en": "The document's language attribute should be a standard code",
+ "nl": "Het language-attribuut van het document moet een standaard code zijn",
+ "pt-br": "O atributo de idioma do documento deve ser um código padrão"
+ },
+ "description": {
+ "de": "Das Dokument sollte eine Standardsprache haben und diese Sprache sollte durch einen validen 2- bis 3-stelligen Sprachcode nach ISO 639 gekennzeichnet sein.",
+ "en": "The document should have a default langauge, and that language should use the valid 2 or 3 letter language code according to ISO specification 639.",
+ "nl": "Het document moet een standaardtaal hebben en die taal moet de geldige 2- of 3-letterige taalcode hebben volgens de ISO-specificatie 639.",
+ "pt-br": "O documento deve ter um idioma padrão, e esse idioma deve usar o código de idioma válido de 2 ou 3 letras de acordo com a especificação ISO 639."
+ },
+ "guidelines": {
+ "wcag": {
+ "3.1.1": {
+ "techniques": [
+ "H57"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "document",
+ "language"
+ ],
+ "strings": [
+ "languageCodes"
+ ],
+ "callback": "documentLangIsISO639Standard"
+ },
+ "documentLangNotIdentified": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Das Dokument muss ein \"lang\"-Attribut haben.",
+ "en": "The document must have a \"lang\" attribute",
+ "nl": "Het document moet een \"lang\"-attribuut hebben",
+ "pt-br": "O documento deve ter um atributo \"lang\""
+ },
+ "description": {
+ "de": "Das Dokument sollte eine Standardsprache haben, die im \"lang\"-Attribut im HTML-Element gesetzt ist.",
+ "en": "The document should have a default language, by setting the \"lang\" attribute in the html element.",
+ "nl": "Het document moet een standaardtaal hebben, vastgelegd in het \"lang\"-attribuut in het html-element.",
+ "pt-br": "O documento deve ter um idioma padrão, definindo o atributo \"lang\" no elemento html."
+ },
+ "guidelines": [],
+ "tags": [
+ "document",
+ "language"
+ ],
+ "options": {
+ "selector": "html:not(html[lang])"
+ }
+ },
+ "documentMetaNotUsedWithTimeout": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Meta-Elemente dürfen nicht zum Aktualisieren der Seite verwendet werden",
+ "en": "Meta elements must not be used to refresh the content of a page",
+ "nl": "Meta-elementen mogen niet worden gebruikt om content op een pagina te verversen",
+ "pt-br": "Meta elementos não devem ser usados para atualizar o conteúdo de uma página"
+ },
+ "description": {
+ "de": "Weil Benutzer unterschiedliche Geschwindigkeiten und Fähigkeiten haben, wenn es um das Erfassen von Inhalten einer Seite geht, kann die \"meta-refresh\"-Methode dazu führen, dass Benutzer den Inhalt nicht vollständig verstehen, bevor sie umgeleitet werden. Verwenden Sie eine \"Inhalt aktualisieren\"-Verknüpfung.",
+ "en": "Because different users have different speeds and abilities when it comes to parsing the content of a page, a \"meta-refresh\" method to reload the content of the page can prevent users from having full access to the content. Try to use a \"refresh this\" link instead.",
+ "nl": "Omdat verschillende gebruikers verschillende snelheden en vaardigheden hebben met het scannen van content op een pagina, kan een \"meta-refresh\"-methode om de pagina te herladen gebruikers hinderen in toegang tot de content. Gebruik een \"refresh this\" link hiervoor.",
+ "pt-br": "Como diferentes usuários têm diferentes velocidades e habilidades quando se trata de analisar o conteúdo de uma página, um método de \"meta-refresh\" para recarregar o conteúdo da página pode impedir que os usuários tenham acesso total ao conteúdo. Tente usar um link \"atualizar este\" em vez disso."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.2.1": {
+ "techniques": [
+ "F40",
+ "F41"
+ ]
+ },
+ "2.2.4": {
+ "techniques": [
+ "F40",
+ "F41"
+ ]
+ },
+ "3.2.5": {
+ "techniques": [
+ "F41"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "document"
+ ],
+ "options": {
+ "selector": "meta[http-equiv=refresh]"
+ }
+ },
+ "documentReadingDirection": {
+ "type": "selector",
+ "testability": 0.5,
+ "title": {
+ "de": "Die Leserichtung des Textes ist korrekt angegeben",
+ "en": "Reading direction of text is correctly marked",
+ "nl": "De leesrichting van de tekst staat juist aangegeven",
+ "pt-br": "Direção de leitura do texto está marcada corretamente"
+ },
+ "description": {
+ "de": "Wenn notwendig, muss die Leserichtung (für Sprachen mit abweichender Leserichtung) für das Dokument oder Textabschnitte deklariert sein.",
+ "en": "Where required, the reading direction of the document (for language that read in different directions), or portions of the text, must be declared.",
+ "nl": "Voor talen die een andere leesrichting hebben, moet de leesrichting van (een deel van) de tekst in een document worden opgenomen.",
+ "pt-br": "Quando necessário, deve ser declarada a direção de leitura do documento (para o idioma que lê em direções diferentes) ou partes do texto."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.2": {
+ "techniques": [
+ "H34"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "document",
+ "language"
+ ],
+ "options": {
+ "selector": "*[lang=he]:not(*[dir=rtl]), *[lang=ar]:not(*[dir=rtl])"
+ }
+ },
+ "documentStrictDocType": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Die Seite verwendet einen strikten DOCTYPE",
+ "en": "The page uses a strict doctype",
+ "nl": "De pagina gebruikt een strikt doctype",
+ "pt-br": "A página usa um doctype estrito"
+ },
+ "description": {
+ "de": "Der Doctype Seite sollte entweder HTML Strict oder XHTML Strict sein.",
+ "en": "The doctype of the page or document should be either an HTML or XHTML strict doctype.",
+ "nl": "Het doctype van een pagina of document moet een HTML of XHTML strikt doctype zijn.",
+ "pt-br": "O doctype da página ou documento deve ser um doctype HTML ou XHTML estrito."
+ },
+ "guidelines": [],
+ "tags": [
+ "document",
+ "doctype"
+ ],
+ "callback": "documentStrictDocType"
+ },
+ "documentTitleDescribesDocument": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Der Titel beschreibt das Dokument",
+ "en": "The title describes the document",
+ "nl": "De titel beschrijft het document",
+ "pt-br": "O título descreve o documento"
+ },
+ "description": {
+ "de": "Der Dokumententitel sollte die Seite beschreiben. Bildschirmleseprogramme verwenden oft den Titel um von Fenster zu Fenster zu navigieren.",
+ "en": "The document title should actually describe the page. Often, screen readers use the title to navigate from one window to another.",
+ "nl": "De documenttitel moet een beschrijving zijn van de pagina. Schermlezen gebruiken de titels van pagina's om van het ene naar het andere scherm te navigeren.",
+ "pt-br": "O título do documento deve realmente descrever a página. Muitas vezes, os leitores de tela usam o título para navegar de uma janela para outra."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.2": {
+ "techniques": [
+ "F25",
+ "G88"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "document",
+ "head"
+ ],
+ "options": {
+ "selector": "head title:first"
+ }
+ },
+ "documentTitleIsNotPlaceholder": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Der Dokumententitel sollte kein Platzhaltertext sein",
+ "en": "The document title should not be placeholder text",
+ "nl": "De documenttitle moet geen placeholder tekst zijn",
+ "pt-br": "O título do documento não deve ser um texto de espaço reservado"
+ },
+ "description": {
+ "de": "Der Dokumententitel sollte nicht durch einen Platzhalter verschwendet werden, der die Seite nicht beschreibt.",
+ "en": "The document title should not be wasted placeholder text which does not describe the page.",
+ "nl": "De documenttitel moet geen placeholder tekst zijn die geen goede beschrijving van de pagina is.",
+ "pt-br": "O título do documento não deve ser desperdiçado com um texto que não descreve a página."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.2": {
+ "techniques": [
+ "F25",
+ "G88"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "document",
+ "head"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "content": true,
+ "selector": "head title:first"
+ }
+ },
+ "documentTitleIsShort": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Der Dokumententitel sollte kurz sein",
+ "en": "The document title should be short",
+ "nl": "De documenttitel moet kort zijn",
+ "pt-br": "O título do documento deve ser curto"
+ },
+ "description": {
+ "de": "Der Dokumententitel sollte kurz und prägnant sein. Dieser Test schlägt bei 150 Zeichen fehl, es sollte aber als Empfehlung aufgefasst werden.",
+ "en": "The document title should be short and succinct. This test fails at 150 characters, but authors should consider this to be a suggestion.",
+ "nl": "De documenttitel moet kort en beknopt zijn. Probeer bij een titel langer dan 150 tekense de titel in te korten waar mogelijk.",
+ "pt-br": "O título do documento deve ser curto e sucinto. Este teste falha em 150 caracteres, mas os autores devem considerar isso como uma sugestão."
+ },
+ "guidelines": [],
+ "tags": [
+ "document",
+ "head"
+ ],
+ "callback": "documentTitleIsShort"
+ },
+ "documentTitleNotEmpty": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Das Dokument sollte keinen leeren Titel haben",
+ "en": "The document should not have an empty title",
+ "nl": "Het document mag geen lege titel hebben",
+ "pt-br": "O documento não deve ter um título vazio"
+ },
+ "description": {
+ "de": "Das Dokument sollte einen Titel haben, der nicht leer ist.",
+ "en": "The document should have a title element that is not white space.",
+ "nl": "Het document moet een titelelement hebben dat is ingevuld.",
+ "pt-br": "O documento deve ter um elemento de título que não seja espaço em branco."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.2": {
+ "techniques": [
+ "F25",
+ "H25"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "document",
+ "head"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "content": true,
+ "empty": true,
+ "selector": "head title"
+ }
+ },
+ "documentValidatesToDocType": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Das Dokument muss sich gegen den Doctype validieren lassen",
+ "en": "Document must validate to the doctype",
+ "nl": "Het document moet valideren met het doctype",
+ "pt-br": "Documento deve validar para o doctype"
+ },
+ "description": {
+ "de": "Das Dokument muss sich gegen den Doctype validieren lassen",
+ "en": "The document must validate to the declared doctype.",
+ "nl": "Het document moet valideren met het vastgestelde doctype.",
+ "pt-br": "O documento deve validar para o doctype declarado."
+ },
+ "guidelines": {
+ "wcag": {
+ "4.1.1": {
+ "techniques": [
+ "G134"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "document",
+ "doctype"
+ ],
+ "callback": "documentValidatesToDocType"
+ },
+ "documentVisualListsAreMarkedUp": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Listen sollten mittels Listen-Markup deklariert werden",
+ "en": "Lists of items should be marked using list markup",
+ "nl": "Lijsten moeten gemarkeerd worden als ordered of unordered lists",
+ "pt-br": "As listas de itens devem ser marcadas usando marcação de lista"
+ },
+ "description": {
+ "de": "Verwende die sortierten (ol) oder unsortierten (ul) Listen-Elemente anstelle von Zeilenumbrüchen mit Zahlen oder Zeichen, um Listen auszuzeichen.",
+ "en": "Use the ordered or unordered (bulleted) list elements to mark lists instead of using new lines that start with numbers or other characters to create a visual list.",
+ "nl": "Gebruik ordered (ol) of unordered (ul) elementen voor lijsten, in plaats van een nieuwe regel per item aan te maken die je laat beginnen met een nummer of teken om een visuele lijst te maken.",
+ "pt-br": "Use os elementos de lista ordenados ou não ordenados (com marcadores) para marcar listas em vez de usar novas linhas que começam com números ou outros caracteres para criar uma lista visual."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "H28",
+ "H48",
+ "T2"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "list",
+ "semantics",
+ "content"
+ ],
+ "strings": [
+ "symbols"
+ ],
+ "callback": "documentVisualListsAreMarkedUp"
+ },
+ "domOrderMatchesVisualOrder": {
+ "type": "selector",
+ "testability": 0.5,
+ "title": {
+ "de": "Stellen Sie sicher, dass die visuelle Reihenfolge der Seitet mit dem DOM übereinstimmt",
+ "en": "Ensure that the visual order of the page matches the DOM",
+ "nl": "Zorg ervoor dat de visuele ordening van de pagina overeenkomt met de DOM",
+ "pt-br": "Certifique-se de que a ordem visual da página corresponde ao DOM"
+ },
+ "description": {
+ "de": "Wenn Sie Positionierungstechniken verwenden, stellen Sie sicher, dass die visuelle Reihenfolge mit dem Document Object Model (DOM) übereinstimmt.",
+ "en": "When using positioning techniques, make sure that the visual order of the page matches the DOM.",
+ "nl": "Wanneer je gebruik maakt van positioneringstechnieken, zorg er dan voor dat de visuele ordening van de pagina overeenkomt met de DOM.",
+ "pt-br": "Ao usar técnicas de posicionamento, certifique-se de que a ordem visual da página corresponde ao DOM."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.2": {
+ "techniques": [
+ "C27"
+ ]
+ },
+ "2.4.3": {
+ "techniques": [
+ "C27"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "content"
+ ],
+ "options": {
+ "selector": "*:quailCss(position=absolute), *:quailCss(position=fixed), *:quailCss(float=right), *:quailCss(float=left)"
+ }
+ },
+ "elementAttributesAreValid": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Attribute sollten mit Leerzeichen getrennt sein und in Anführungszeichen gesetzt werden",
+ "en": "Attributes should have spaces between them and be wrapped in quotes",
+ "nl": "Attributen moeten gescheiden zijn door spaties en ze moeten tussen aanhalingstekens",
+ "pt-br": "Os atributos devem ter espaços entre eles e ser envolvidos entre aspas"
+ },
+ "description": {
+ "de": "Attribute sollten mit Leerzeichen getrennt sein und in Anführungszeichen gesetzt werden.",
+ "en": "Attributes should have spaces between them and be wrapped in quotes",
+ "nl": "Tussen attributen moeten spaties staan en ze moeten tussen aanhalingstekens staan.",
+ "pt-br": "Os atributos devem ter espaços entre eles e ser envolvidos entre aspas"
+ },
+ "guidelines": {
+ "4.1.1": {
+ "techniques": [
+ "F70"
+ ]
+ }
+ },
+ "callback": "elementAttributesAreValid"
+ },
+ "embedHasAssociatedNoEmbed": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"embed\"-Elemente sollten ein zugehöriges \"noembed\"-Element haben",
+ "en": "All \"embed\" elements have an associated \"noembed\" element",
+ "nl": "Alle \"embed\" elementen moeten een bijbehorend \"noembed\"-element hebben",
+ "pt-br": "Todos os elementos \"embed\" têm um elemento \"noembed\" associado"
+ },
+ "description": {
+ "de": "Da einige Benutzer das embed-Element nicht verwenden können, sollte eine alternativer Inhalt im noembed-Element angeboten werden.",
+ "en": "Because some users cannot use the embed element, provide alternative content in a noembed element.",
+ "nl": "Sommige gebruikers kunnen het embed-element niet gebruiken. Biedt hiervoor alternatieve content aan in een noembed-element.",
+ "pt-br": "Como alguns usuários não podem usar o elemento embed , forneça conteúdo alternativo em um elemento noembed ."
+ },
+ "guidelines": [],
+ "tags": [
+ "object",
+ "embed",
+ "content"
+ ],
+ "callback": "embedHasAssociatedNoEmbed"
+ },
+ "elementsDoNotHaveDuplicateAttributes": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Elemente sollten keine doppelten Attribute haben",
+ "en": "Elements should not have duplicate attributes",
+ "nl": "Elementen mogen geen dubbele attributen hebben",
+ "pt-br": "Elementos não devem ter atributos duplicados"
+ },
+ "description": {
+ "de": "Elemente sollten jedes Attribut nur einmal haben. Zum Beispiel dürfen keine zwei \"class\"-Attribute vorhanden sein.",
+ "en": "Elements should only have one type of any attribute. For example, there should not be two 'class' attributes.",
+ "nl": "Elementen mogen maar een type attribuut hebben. Er mogen bijvoorbeeld niet twee 'class'-attributen zijn.",
+ "pt-br": "Os elementos devem ter apenas um tipo de qualquer atributo. Por exemplo, não deve haver dois atributos 'class'."
+ },
+ "guidelines": [],
+ "tags": [
+ "content"
+ ],
+ "components": [
+ "htmlSource"
+ ],
+ "libraries": [
+ "node-htmlparser/lib/htmlparser.js"
+ ],
+ "callback": "elementsDoNotHaveDuplicateAttributes"
+ },
+ "embedMustHaveAltAttribute": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "\"Embed\"-Elemente müssen ein \"alt\"-Attribut haben",
+ "en": "\"Embed\" elements must have an \"alt\" attribute",
+ "nl": "\"Embed\"-elementen moeten een \"alt\"-attribuut hebben",
+ "pt-br": "Elementos \"embed\" devem ter um atributo \"alt\""
+ },
+ "description": {
+ "de": "Alle embed-Elemente müssen ein \"alt\"-Attribut haben.",
+ "en": "All embed elements must have an \"alt\" attribute.",
+ "nl": "Alle embed-elementen moeten een \"alt\"-attribuut hebben.",
+ "pt-br": "Todos os elementos embed devem ter um atributo \"alt\"."
+ },
+ "guidelines": [],
+ "tags": [
+ "object",
+ "embed",
+ "content"
+ ],
+ "options": {
+ "selector": "embed:not([alt])"
+ }
+ },
+ "embedMustNotHaveEmptyAlt": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "\"Embed\"-Elemente dürfen kein leeres \"alt\"-Attribut haben",
+ "en": "\"Embed\" elements cannot have an empty \"alt\" attribute",
+ "nl": "\"Embed\"-elementen mogen geen leeg \"alt\"-attribuut hebben",
+ "pt-br": "Elementos \"embed\" não podem ter um atributo \"alt\" vazio"
+ },
+ "description": {
+ "de": "Alle embed-Elemente müssen ein \"alt\"-Attribut haben, dass nicht leer ist.",
+ "en": "All embed elements must have an \"alt\" attribute that is not empty.",
+ "nl": "Alle embed-elementen moeten een gevuld \"alt\"-attribuut hebben.",
+ "pt-br": "Todos os elementos embed devem ter um atributo \"alt\" que não esteja vazio."
+ },
+ "guidelines": [],
+ "tags": [
+ "object",
+ "embed",
+ "content"
+ ],
+ "options": {
+ "selector": "embed[alt=]"
+ }
+ },
+ "embedProvidesMechanismToReturnToParent": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Alle embed-Elemente sollten einen Weg für Tastatur-Benutzern bieten das Element zu verlassen.",
+ "en": "All embed elements should provide a way for keyboard users to escape",
+ "nl": "Alle embed-elementen moeten een manier bieden voor toetsenbordgebruikers om het element te verlaten",
+ "pt-br": "Todos os elementos 'embed' devem fornecer uma maneira para que os usuários do teclado escapem"
+ },
+ "description": {
+ "de": "Stellen Sie sicher, dass embed-Elemente einem Tastatur-Benutzer die Möglichkeit zum Verlassen des Elements bietet. Dies muss manuell getestet werden.",
+ "en": "Ensure that a user who has only a keyboard as an input device can escape an embed element. This requires manual confirmation.",
+ "nl": "Zorg ervoor dat een gebruiker die alleen het toetsenbord gebruikt voor bediening een embed-element kan verlaten. Hiervoor is handmatige bevestiging nodig.",
+ "pt-br": "Certifique-se de que um usuário que tenha apenas um teclado como um dispositivo de entrada pode escapar de um elemento embed. Isso requer confirmação manual."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.1.2": {
+ "techniques": [
+ "G21"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "object",
+ "embed",
+ "content"
+ ],
+ "options": {
+ "selector": "embed"
+ }
+ },
+ "emoticonsExcessiveUse": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Emoticons sollten nicht exzessiv genutzt werden",
+ "en": "Emoticons should not be used excessively",
+ "nl": "Gebruik emoticons spaarzaam",
+ "pt-br": "Emoticons não devem ser usados excessivamente"
+ },
+ "description": {
+ "de": "Emoticons sollten nicht exzessiv genutzt werden um Gefühle oder Inhalte zu kommunizieren. Versuchen Sie das Dokument so umzuschreiben, dass der Inhalt durch den Text wiedergegeben wird oder betten Sie Emoticons in ein abbr-Element ein. Emoticons werden von Bildschirmleseprogrammen nicht vorgelesen und werden oft verwendet, um Gefühle mitzuteilen, die für das Verständnis des Dokuments notwendig sind.",
+ "en": "Emoticons should not be used excessively to communicate feelings or content. Try to rewrite the document to have more textual meaning, or wrapping the emoticons in an abbr element as outlined below. Emoticons are not read by screen-readers, and are often used to communicate feelings or other things which are relevant to the content of the document.",
+ "nl": "Gebruik emoticons spaarzaam om gevoel of content over te brengen. Probeer het document te herschrijven in tekst, of geef de emoticons een abbr-element. Emoticons worden niet voorgelezen door schermlezers, maar bevatten wel vaak informatie die relevant is voor de content van het document.",
+ "pt-br": "Emoticons não devem ser usados excessivamente para comunicar sentimentos ou conteúdo. Tente reescrever o documento para ter mais significado textual ou envolver os emoticons em um elemento abbr conforme descrito abaixo. Emoticons não são lidos por leitores de tela, e são freqüentemente usados para comunicar sentimentos ou outras coisas que são relevantes para o conteúdo do documento."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H86"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "language",
+ "emoticons",
+ "content"
+ ],
+ "callback": "emoticonsExcessiveUse"
+ },
+ "emoticonsMissingAbbr": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Emoticons sollten Abkürzungen haben",
+ "en": "Emoticons should have abbreviations",
+ "nl": "Emoticons moeten afkortingen hebben",
+ "pt-br": "Emoticons devem ter abreviaturas"
+ },
+ "description": {
+ "de": "Emoticons werden von Bildschirmleseprogrammen nicht vorgelesen und werden oft verwendet, um Gefühle mitzuteilen, die für das Verständnis des Dokuments notwendig sind. Wenn ein Emoticon inhaltlich relevant ist, verwenden Sie ein \"abbr\"-Element oder \"acronym\"-Element, um zu markieren.",
+ "en": "Emoticons are not read by screen-readers, and are often used to communicate feelings or other things which are relevant to the content of the document. If this emoticon is important content, mark it up with an \"abbr\" or \"acronym\" tag.",
+ "nl": "Emoticons worden niet voorgelezen door schermlezers, maar bevatten wel vaak informatie die relevant is voor de content van het document. Als een emoticon belangrijke content is, gebruik dan een \"abbr\" or \"acronym\" tag om het te markeren.",
+ "pt-br": "Emoticons não são lidos por leitores de tela, e são frequentemente usados para comunicar sentimentos ou outras coisas que são relevantes para o conteúdo do documento. Se este emoticon for conteúdo importante, marque-o com uma tag \"abbr\" ou \"acronym\"."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H86"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "language",
+ "emoticons",
+ "content"
+ ],
+ "callback": "emoticonsMissingAbbr"
+ },
+ "fieldsetHasLabel": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Fieldsets benötigen ein \"label\"-Element",
+ "en": "Fieldsets require a label element",
+ "nl": "Fieldsets behoeven een label-element",
+ "pt-br": "Fieldsets requerem um elemento label"
+ },
+ "description": {
+ "de": "Fieldsets zur Gruppierung von gleichen Formular-Elementen, bspw. Checkboxen, sollten ein Label haben, welches die Gruppierung beschreibt.",
+ "en": "Fieldsets used to group similar form elements like checkboxes should have a label that describes the group of elements.",
+ "nl": "Fieldsets die een groep gelijkwaardige elementen bevatten moeten een label hebben die deze groep elementen beschrijft.",
+ "pt-br": "Fieldsets usados para agrupar elementos de formulário semelhantes como caixas de seleção devem ter um rótulo que descreve o grupo de elementos."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.1.1": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "4.1.2": {
+ "techniques": [
+ "H91"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "options": {
+ "selector": "fieldset:not(fieldset:has(legend))"
+ }
+ },
+ "fileHasLabel": {
+ "type": "label",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"file\"-Eingabeelemente haben ein dazugehöriges Label",
+ "en": "All \"file\" input elements have a corresponding label",
+ "nl": "Alle \"file\"-invoerelementen hebben een bijbehorend label",
+ "pt-br": "Todos os elementos de entrada \"file\" têm um rótulo correspondente"
+ },
+ "description": {
+ "de": "Alle input-Elemente vom Typ \"file\" sollten ein dazugehöriges label-Element haben. Bildschirmleseprogramme haben oftmals eine Formular-Modus, in dem nur Labels vorgelesen werden.",
+ "en": "All input elements of type \"file\" should have a corresponding label element. Screen readers often enter a \"form mode\" where only label text is read aloud to the user.",
+ "nl": "Alle input-elementen van het type \"file\" moeten een bijbehorend label-element hebben. Schermlezers maken vaak gebruik van een \"formuliereninstelling\" waarbij alleen de tekst van de labels hardop aan de gebruiker wordt voorgelezen.",
+ "pt-br": "Todos os elementos input do tipo \"file\" devem ter um elemento label correspondente. Os leitores de tela costumam entrar em um \"modo de formulário\" onde somente o texto da etiqueta é lido em voz alta para o usuário."
+ },
+ "guidelines": {
+ "508": [
+ "n"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H44"
+ ]
+ },
+ "1.3.1": {
+ "techniques": [
+ "H44",
+ "F68"
+ ]
+ },
+ "3.3.2": {
+ "techniques": [
+ "H44"
+ ]
+ },
+ "4.1.2": {
+ "techniques": [
+ "H44"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "label"
+ ],
+ "options": {
+ "selector": "input[type=file]"
+ }
+ },
+ "fileLabelIsNearby": {
+ "type": "labelProximity",
+ "testability": 0.5,
+ "title": {
+ "de": "Alle \"file\"-Eingabeelemente sollten ein dazugehöriges Label haben",
+ "en": "All \"file\" input elements have a label that is close",
+ "nl": "Van alle \"file\"-invoerelementen staat het label in de buurt",
+ "pt-br": "Todos os elementos de entrada \"file\" têm um rótulo que está próximo"
+ },
+ "description": {
+ "de": "Alle Eingabeelemente vom Typ \"file\" müssen ein dazugehöriges Label haben das in der Nähe des Eingabeelements positioniert ist. Nutzer von Bildschirmvergrößerung oder mit reduzierten räumlichen Fähigkeiten werden bei der Verwendung eines Formularelements behindert, wenn das Label für das Element weit entfernt positioniert ist.",
+ "en": "All input elements of type \"file\" must have a corresponding label that is close to the form element. Users of screen magnification or with reduced spatial skills are hampered in using a form element if the label for that element is located far away.",
+ "nl": "Alle inputelementen van het type \"file\" moeten een bijbehorend label hebben dat dicht bij het formulierelement staat. Gebruikers die het scherm vergroten of met beperkte ruimtelijke vaardigheden kunnen een formulier niet gebruiken als het label van een veld te ver weg staat.",
+ "pt-br": "Todos os elementos de entrada do tipo \"arquivo\" devem ter um rótulo correspondente que esteja próximo ao elemento do formulário. Usuários de ampliação de tela ou com habilidades espaciais reduzidas são impedidos de usar um elemento de formulário se o rótulo para esse elemento estiver localizado longe."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "labelProximity"
+ ],
+ "options": {
+ "selector": "input[type=file]"
+ }
+ },
+ "focusIndicatorVisible": {
+ "type": "custom",
+ "title": {
+ "de": "Focus indicators müssen gut sichtbar sein",
+ "en": "Focus indicators have high visibility",
+ "nl": "Focus indicators moeten goed zichtbaar zijn",
+ "pt-br": "Indicadores de foco têm alta visibilidade"
+ },
+ "description": {
+ "de": "Wenn ein focus indicator verwendet wird, sollte es ausreichend Kontrast zum Hintergrund aufweisen und groß genug sein, um sichtbar zu sein.",
+ "en": "When a focus indicator is used, it should have enough contrast with the background and big enough to be highly visible.",
+ "nl": "Wanneer je een focus indicator gebruikt, moet het contrast tussen de indicator en de achtergrond groot genoeg zijn in verband met de zichtbaarheid.",
+ "pt-br": "Quando um indicador de foco é usado, ele deve ter bastante contraste com o fundo e grande o suficiente para ser altamente visível."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.7": {
+ "techniques": [
+ "C15",
+ "G165",
+ "G195"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "focus",
+ "content"
+ ],
+ "components": [
+ "color",
+ "convertToPx"
+ ],
+ "callback": "focusIndicatorVisible"
+ },
+ "fontIsNotUsed": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Font.Elemente sollten nicht verwendet werden",
+ "en": "Font elements should not be used",
+ "nl": "Het font element moet niet worden gebruikt",
+ "pt-br": "Os elementos de fonte não devem ser usados"
+ },
+ "description": {
+ "de": "Der basefontbasefont tag is deprecated and should not be used. Investigate using stylesheets instead.",
+ "nl": "De basefont-tag is afgekeurd en moet niet worden gebruikt. Gebruik in plaats hiervan stylesheets.",
+ "pt-br": "A tag basefont está obsoleta e não deve ser usada. Investigue usando folhas de estilo."
+ },
+ "guidelines": [],
+ "tags": [
+ "deprecated",
+ "content"
+ ],
+ "options": {
+ "selector": "font"
+ }
+ },
+ "formAllowsCheckIfIrreversable": {
+ "type": "selector",
+ "testability": 0,
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "options": {
+ "selector": "form"
+ }
+ },
+ "formButtonsHaveValue": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "\"input\"-Elemente für button, submit oder reset müssen ein \"value\"-Attribut haben",
+ "en": "Input elements for button, submit, or reset must have a value attribute",
+ "nl": "Invoerelementen voor knoppen, indienen of resetten moeten een waarde-attribuut hebben",
+ "pt-br": "Elementos de entrada para botão, enviar ou redefinir devem ter um atributo de valor"
+ },
+ "description": {
+ "de": "Jedes form-Element, welches als Schaltfläche (\"button\") angezeigt wird, muss ein lesbares \"value\"-Attribut haben.",
+ "en": "Any form element that is rendered as a button has to have a readable value attribute.",
+ "nl": "Elk invoerelement dat eruit ziet als een knop moet een leesbaar waarde-attribuut hebben.",
+ "pt-br": "Qualquer elemento de formulário que é processado como um botão tem que ter um atributo de valor legível."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.1.1": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "4.1.2": {
+ "techniques": [
+ "H91"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "options": {
+ "selector": "input[type=button], input[type=submit], input[type=reset]",
+ "test": ":not([value])"
+ }
+ },
+ "formDeleteIsReversable": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Das Löschen von Elementen über Formulare sollte rückgängig gemacht werden können",
+ "en": "Deleting items using a form should be reversable",
+ "nl": "De verwijdering van een item in een formulier moet ongedaan gemaakt kunnen worden",
+ "pt-br": "Excluir itens usando um formulário deve ser reversível"
+ },
+ "description": {
+ "de": "Wenn ein Formular die Option bietet ein Element zu löschen, stellen Sie sicher, dass der Benutzer den Vorgang rückgängig machen kann oder den Löschvorgang zuvor bestätigen muss. Dies muss manuell getestet werden.",
+ "en": "Check that, if a form has the option to delete an item, that the user has a chance to either reverse the delete process, or is asked for confirmation before the item is deleted. This is not something that can be checked through automated testing and requires manual confirmation.",
+ "nl": "Controleer of een gebruiker de verwijdering van een invoer in een formulier ongedaan kan maken wanneer het mogelijk is om een invoer te verwijderen. Dit kan niet met een automatische test en moet handmatig gecontroleerd en bevestigd worden.",
+ "pt-br": "Verifique se, se um formulário tem a opção de excluir um item, que o usuário tem a chance de inverter o processo de exclusão ou é solicitada confirmação antes que o item seja excluído. Isso não é algo que pode ser verificado através de testes automatizados e requer confirmação manual."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "options": {
+ "selector": "form"
+ }
+ },
+ "formErrorMessageHelpsUser": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Formulare erlauben es dem Benutzer die Eingabe zu prüfen, bevor eine irreversible Aktion durchgeführt wird",
+ "en": "Forms offer the user a way to check the results of their form before performing an irrevocable action",
+ "nl": "Formulieren bieden gebruikers de gelegenheid om hun formulier te controleren voor ze een onomkeerbare actie uitvoeren",
+ "pt-br": "Os formulários oferecem ao usuário uma maneira de verificar os resultados de seu formulário antes de executar uma ação irrevogável"
+ },
+ "description": {
+ "de": "Wenn ein Formular eine irreversible Aktion durchführt, bspw. eine Bestellung, muss sichergestellt werden, dass der Benutzer die Eingabe vor dem Absenden des Formulars prüfen kann. Dies muss manuell getestet werden.",
+ "en": "If the form allows users to perform some irrevocable action, like ordreing a product, ensure that users have the ability to review the contents of the form they submitted first. This is not something that can be checked through automated testing and requires manual confirmation.",
+ "nl": "Als een formulier een gebruiker toestaat om een onomkeerbare actie uit te voeren, zoals het bestellen van een product, zorg er dan voor dat ze eerst het formulier kunnen controleren. Dit kan niet met een automatische test en moet handmatig gecontroleerd en bevestigd worden.",
+ "pt-br": "Se o formulário permitir que os usuários executem alguma ação irrevogável, como ordenar um produto, assegure-se de que os usuários tenham a capacidade de revisar o conteúdo do formulário que enviaram primeiro. Isso não é algo que pode ser verificado através de testes automatizados e requer confirmação manual."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "options": {
+ "selector": "form"
+ }
+ },
+ "formHasGoodErrorMessage": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Fehlermeldungen im Formular sollten beim Ausfüllen unterstützen",
+ "en": "Form error messages should assist in solving errors",
+ "nl": "Foutmeldingen in formulieren moeten fouten helpen oplossen",
+ "pt-br": "Mensagens de erro de formulário devem ajudar a resolver erros"
+ },
+ "description": {
+ "de": "Wenn ein Formular Pflichtfelder hat oder der Benutzer das Formular aufgrund fehlerhafter Eingaben nicht absenden kann, sollten die Fehlermeldungen verständlich sein. Verwenden Sie die Begriffe \"Pflicht\" oder \"Fehler\" im label-Element des Eingabefeldes, in dem der Fehler aufgetreten ist",
+ "en": "If the form has some required fields or other ways in which the user can commit an error, check that the reply is accessible. Use the words \"required\" or \"error\" within the label element of input items where the errors happened.",
+ "nl": "Als het formulier verplichte velden heeft of op andere manier verkeerd ingevuld kan worden, controleer dan of de bijbehorende foutmelding begrijpelijk is. Gebruik de woorden \"required\" of \"error\" in het label-element of in de invoeritems waar de fout is opgetredenitems where the errors happened.",
+ "pt-br": "Se o formulário tiver alguns campos obrigatórios ou outras formas pelas quais o usuário pode cometer um erro, verifique se a resposta está acessível. Use as palavras \"required\" ou \"error\" dentro do elemento label dos itens de entrada onde ocorreram os erros."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "options": {
+ "selector": "form"
+ }
+ },
+ "formHasSubmitButton": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Formulare sollten eine Absenden-Schaltfläche haben",
+ "en": "Form should have a submit button",
+ "nl": "Formulieren moeten een indienknop hebben",
+ "pt-br": "O formulário deve ter um botão de submissão de dados"
+ },
+ "description": {
+ "de": "Formulare sollten eine Schaltfläche haben, die es dem Benutzer erlaubt zu entscheiden, wann er das Formular absendet.",
+ "en": "Forms should have a button that allows the user to select when they want to submit the form.",
+ "nl": "Formulieren moeten een knop hebben waarmee de gebruiker kan bepalen wanneer zij een formulieren willen versturen.",
+ "pt-br": "Os formulários devem ter um botão que permite ao usuário selecionar quando deseja enviar o formulário."
+ },
+ "guidelines": {
+ "wcag": {
+ "3.2.2": {
+ "techniques": [
+ "H32",
+ "G80"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "options": {
+ "selector": "form:not(form:has(input[type=image], input[type=submit], button[type=submit]))"
+ }
+ },
+ "formWithRequiredLabel": {
+ "type": "custom",
+ "testability": 0,
+ "title": {
+ "de": "Pflichtfelder in einem Formular sollten auch im \"label\"-Element als solche markiert sein",
+ "en": "Input items which are required are marked as so in the label element",
+ "nl": "Invoervelden die verplicht zijn, zijn zo gemarkeerd in het label-element",
+ "pt-br": "Os itens de entrada que são necessários são marcados como tal no elemento de etiqueta"
+ },
+ "description": {
+ "de": "Pflichtfelder in Formularen sollten entsprechend gekennzeichnet sein. Es sollte kein einfaches, rotes Sternchen sein sondern als \"Pflicht\" im Text markiert sein. Der Hinweis, dass ein Feld ein Pflichtfeld ist, sollte im label-Element enthalten sein.",
+ "en": "If a form element is required, it should be marked as so. This should not be a mere red asterisk, but instead either a 'required' image with alt text of \"required\" or the actual text \"required\". The indicator that an item is required should be included in the input element's label element.",
+ "nl": "Als een formulierveld verplicht is, moet het ook zichtbaar zijn. Doe dit niet alleen met een asterisk achter het veld, maar met bijvoorbeeld een afbeelding met als alttekst \"required\" of de tekst \"required\". De indicatie dat een veld verplicht is moet opgenomen zijn in het label-element van het invoerveld.",
+ "pt-br": "Se for necessário um elemento de formulário, ele deve ser marcado como tal. Este não deve ser um mero asterisco vermelho, mas sim uma imagem 'necessária' com texto alternativo de \"required\" ou o texto real \"required\". O indicador de que um item é necessário deve ser incluído no elemento label do elemento de entrada."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "ARIA2"
+ ]
+ },
+ "1.4.1": {
+ "techniques": [
+ "F81"
+ ]
+ },
+ "3.3.2": {
+ "techniques": [
+ "ARIA2",
+ "H90"
+ ]
+ },
+ "3.3.3": {
+ "techniques": [
+ "ARIA2"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "callback": "formWithRequiredLabel"
+ },
+ "frameIsNotUsed": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Verwenden Sie keine Frames",
+ "en": "Frames are not used",
+ "nl": "Gebruik geen frames",
+ "pt-br": "Os quadros não são usados"
+ },
+ "description": {
+ "de": "Frames sollten nicht verwendet werden, um eine Seite zu organisieren",
+ "en": "Frames should not be used to organize a page.",
+ "nl": "Gebruik geen frames om een pagina te organiseren.",
+ "pt-br": "Os quadros não devem ser usados para organizar uma página."
+ },
+ "guidelines": [],
+ "tags": [
+ "deprecated",
+ "frame"
+ ],
+ "options": {
+ "selector": "frame"
+ }
+ },
+ "frameRelationshipsMustBeDescribed": {
+ "type": "selector",
+ "testability": 0.5,
+ "title": {
+ "de": "Komplexe Framesets sollten ein \"longdesc\"-Attribut enthalten",
+ "en": "Complex framesets should contain a \"longdesc\" attribute",
+ "nl": "Complexe framesets moeten een \"longdesc\"-attribuut bevatten",
+ "pt-br": "Conjuntos de quadros complexos devem conter um atributo \"longdesc\""
+ },
+ "description": {
+ "de": "Wenn ein frameset drei oder mehr Frames enthält, sollte ein \"longdesc\"-Attribut verwendet werden, um den Zweck der Frames zu beschreiben.",
+ "en": "If a frameset contains three or more frames, use a \"longdesc\" attribute to help describe the purpose of the frames.",
+ "nl": "Als een frameset drie of meer frames bevat, gebruik dan een \"longdesc\"-attribuut om het doel van de frames te beschrijven.",
+ "pt-br": "Se um frameset contém três ou mais quadros, use um atributo \"longdesc\" para ajudar a descrever o propósito dos quadros."
+ },
+ "guidelines": [],
+ "tags": [
+ "deprecated",
+ "frame"
+ ],
+ "options": {
+ "selector": "frameset:not(frameset[longdesc])"
+ }
+ },
+ "framesAreUsedToGroupContent": {
+ "type": "selector",
+ "testability": 0.5,
+ "title": {
+ "de": "Verwenden Sie \"frame\"-Elemente um sich wiederholenden Inhalt darzustellen",
+ "en": "Use frame elements to group repeated materials",
+ "nl": "Gebruik frame-elementen om herhaalde content te groeperen",
+ "pt-br": "Use elementos de estrutura para agrupar materiais repetidos"
+ },
+ "description": {
+ "de": "Wenn sich in einer Seite Inhaltsblöcke wiederholen, sollten Frames verwendet werden, um den gleichartigen Inhalt zu gruppieren",
+ "en": "When blocks of repeated content are used on a site, use frames to group content that is the same across pages.",
+ "nl": "Wanneer blokken content op een site herhaald worden, gebruik dan frames om content die op verschillende pagina's voorkomt te groeperen.",
+ "pt-br": "Quando blocos de conteúdo repetido são usados em um site, use quadros para agrupar conteúdo que é o mesmo em páginas."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.1": {
+ "techniques": [
+ "H70"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "deprecated",
+ "frame"
+ ],
+ "options": {
+ "selector": "body:not(body:has(frameset))"
+ }
+ },
+ "frameSrcIsAccessible": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Die Quelle jedes Frames sollte barrierefreien Inhalt beinhalten",
+ "en": "The source for each frame is accessible content.",
+ "nl": "De bron van elk frame is toegankelijke content.",
+ "pt-br": "A fonte para cada quadro é um conteúdo acessível."
+ },
+ "description": {
+ "de": "Jeder Frame sollte barrierefreien Inhalt enthalten und für Bildschirmleseprogramme zugänglichen Inhalt beinhalten, bspw. als HTML anstatt von Grafiken",
+ "en": "Each frame should contain accessible content, and contain content accessible to screen readers, like HTML as opposed to an image.",
+ "nl": "Elk frame moet toegankelijke content bevatten, en content die toegankelijk is voor schermlezers, zoals HTML in tegenstelling tot een afbeelding.",
+ "pt-br": "Cada quadro deve conter conteúdo acessível e conter conteúdo acessível aos leitores de tela, como HTML em oposição a uma imagem."
+ },
+ "guidelines": [],
+ "tags": [
+ "deprecated",
+ "frame"
+ ],
+ "options": {
+ "selector": "frame"
+ }
+ },
+ "frameTitlesDescribeFunction": {
+ "type": "placeholder",
+ "testability": 0,
+ "title": {
+ "de": "Alle \"frame\"-Elemente sollten ein \"title\"-Attribut haben, dass den Zweck des Frames beschreibt",
+ "en": "All \"frame\" elements should have a \"title\" attribute that describes the purpose of the frame",
+ "nl": "Alle \"frame\" elementen moeten een \"title\"-attribuut hebben dat het doel van het frame beschrijft",
+ "pt-br": "Todos os elementos \"frame\" devem ter um atributo \"title\" que descreva a finalidade do frame"
+ },
+ "description": {
+ "de": "Jedes frame-Element sollte ein \"title\"-Attribut haben, welches den Zweck und die Funktion des Frames beschreibt",
+ "en": "Each frame elements should have a \"title\" attribute which describes the purpose or function of the frame.",
+ "nl": "Elk frame-element moet een \"title\"-attribuut hebben dat het doel of de functie van het frame beschrijft.",
+ "pt-br": "Cada elemento frame deve ter um atributo \"title\" que descreva a finalidade ou função da moldura."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.1": {
+ "techniques": [
+ "H64"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "deprecated",
+ "frame"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "attribute": "title",
+ "empty": true,
+ "selector": "frame[title], iframe[title]"
+ }
+ },
+ "frameTitlesNotEmpty": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Frames dürfen kein leeres \"title\"-Attribut haben",
+ "en": "Frames cannot have empty \"title\" attributes",
+ "nl": "Frames mogen geen leeg \"title\"-attribuut hebben",
+ "pt-br": "Os quadros não podem ter atributos \"título\" vazios"
+ },
+ "description": {
+ "de": "Alle frame-Elemente müssen ein korrektes \"title\"-Attribut haben",
+ "en": "All frame elements must have a valid \"title\" attribute.",
+ "nl": "Alle frame-elementen moeten een geldig \"title\"-attribuut hebben.",
+ "pt-br": "Todos os elementos frame devem ter um atributo \"title\" válido."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.1": {
+ "techniques": [
+ "H64"
+ ]
+ },
+ "4.1.2": {
+ "techniques": [
+ "H64"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "deprecated",
+ "frame"
+ ],
+ "options": {
+ "selector": "frame:not(frame[title]), frame[title=''], iframe:not(iframe[title]), iframe[title='']"
+ }
+ },
+ "frameTitlesNotPlaceholder": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Frames dürfen kein \"title\"-Attributes haben, dass nur aus Platzhaltertext besteht",
+ "en": "Frames cannot have \"title\" attributes that are just placeholder text",
+ "nl": "Frames mogen geen \"title\"-attribuut hebben met placeholdertekst",
+ "pt-br": "Os quadros não podem ter atributo \"title\" que são apenas texto de espaço reservado"
+ },
+ "description": {
+ "de": "\"title\"-Attribute in Frames sollten kein einfacher Platzhaltertext wie bspw. \"frame\" enthalten.",
+ "en": "Frame \"title\" attributes should not be simple placeholder text like \"frame\".",
+ "nl": "Frame \"title\"-attributen mogen geen placeholdertekst bevatten zoals \"frame\".",
+ "pt-br": "Atributos \"title\" de frames não devem possuir texto simples como \"frame\"."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.1": {
+ "techniques": [
+ "H64"
+ ]
+ },
+ "4.1.2": {
+ "techniques": [
+ "H64"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "deprecated",
+ "frame"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "attribute": "title",
+ "selector": "frame, iframe"
+ }
+ },
+ "framesHaveATitle": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"frame\"-Elemente sollten ein \"title\"-Attribut haben",
+ "en": "All \"frame\" elements should have a \"title\" attribute",
+ "nl": "Alle \"frame\"-elementen moeten een \"title\"-attribuut hebben",
+ "pt-br": "Todos os elementos \"frame\" devem ter um atributo \"title\""
+ },
+ "description": {
+ "de": "Jedes frame-Element sollte ein \"title\"-Attribut haben.",
+ "en": "Each frame elements should have a \"title\" attribute.",
+ "nl": "Elk frame-elementen moeten een \"title\"-attribuut hebben.",
+ "pt-br": "Cada elemento frame deve ter um atributo \"title\"."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.1": {
+ "techniques": [
+ "H64"
+ ]
+ },
+ "4.1.2": {
+ "techniques": [
+ "H64"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "deprecated",
+ "frame"
+ ],
+ "options": {
+ "selector": "frame:visible, iframe:visible",
+ "test": ":not([title])"
+ }
+ },
+ "framesetIsNotUsed": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Das \"frameset\"-Element sollte nicht verwendet werden",
+ "en": "The \"frameset\" element should not be used",
+ "nl": "Het \"frameset\"-element wordt niet gebruikt",
+ "pt-br": "O elemento \"frameset\" não deve ser usado"
+ },
+ "description": {
+ "de": "Frames und Framesets sollten nicht verwendet werden, um Inhalt zu organisieren",
+ "en": "Frames and framesets should not be used to organize content.",
+ "nl": "Frames en framesets moeten niet gebruikt worden om content te organiseren.",
+ "pt-br": "Frames e framesets não devem ser usados para organizar o conteúdo."
+ },
+ "guidelines": [],
+ "tags": [
+ "deprecated",
+ "frame"
+ ],
+ "options": {
+ "selector": "frameset"
+ }
+ },
+ "framesetMustHaveNoFramesSection": {
+ "type": "selector",
+ "testability": 0.5,
+ "title": {
+ "de": "Alle Framesets sollten ein noframes-Element beinhalten",
+ "en": "All framesets should contain a noframes section",
+ "nl": "Alle framesets moeten een noframes-sectie bevatten",
+ "pt-br": "Todos os framesets devem conter uma seção noframes"
+ },
+ "description": {
+ "de": "Jedes frameset sollte ein noframes-Element beinhalten, welches den Inhalt des Framesets beschreibt.",
+ "en": "If a frameset contains three or more frames, use a \"longdesc\" attribute to help describe the purpose of the frames.",
+ "nl": "Als een frameset drie of meer frames bevat, gebruik dan een \"longdesc\"-attribuut om het doel van de frames te beschrijven.",
+ "pt-br": "Se um frameset contém três ou mais quadros, use um atributo \"longdesc\" para ajudar a descrever o propósito dos quadros."
+ },
+ "guidelines": [],
+ "tags": [
+ "deprecated",
+ "frame"
+ ],
+ "options": {
+ "selector": "frameset:not(frameset:has(noframes))"
+ }
+ },
+ "headersAttrRefersToATableCell": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Tabellenzellen mit \"header\"-Attribut müssen eine entsprechende Datenzelle in der gleichen Tabelle mit demselben \"id\"-Attribut haben.",
+ "en": "Table cell headers attributes must within the same table have an associated data cell with the same id",
+ "nl": "Tabel cellen met een headers attribuut moeten binnen dezelfde tabel een overeenkomende data cel hebben in het id attribuut dezelfde waarde",
+ "pt-br": "Os atributos de cabeçalhos de tabela devem ter dentro da mesma tabela uma célula de dados associada com o mesmo id"
+ },
+ "description": {
+ "de": "",
+ "en": "",
+ "nl": "",
+ "pt-br": ""
+ },
+ "guidelines": [],
+ "tags": [
+ "headers",
+ "td",
+ "th"
+ ],
+ "callback": "headersAttrRefersToATableCell"
+ },
+ "headerH1": {
+ "type": "headingLevel",
+ "testability": 0,
+ "title": {
+ "de": "Überschriften mit Level 1 können nur gefolgt werden von Level 2",
+ "en": "Header level 1 can only be followed by level 2",
+ "nl": "De header die volgt op een h1 is niet h3 tot h6",
+ "pt-br": "Cabeçalho nível 1 só pode ser seguido por nível 2"
+ },
+ "description": {
+ "de": "Überschriften sollten keinen Level überspringen. Auf eine h1-Überschrift sollte kein h3, h4, h5 oder h6 folgen.",
+ "en": "Header order should not skip a level. Do not follow a header level 1 with a level 3, 4, 5, or 6.",
+ "nl": "Headers mogen geen niveau overslaan. Laat een h1-header niet volgen door een h3, h4, h5, of h6.",
+ "pt-br": "Ordem de cabeçalho não deve saltar um nível. Não siga um nível de cabeçalho 1 com um nível 3, 4, 5 ou 6."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.6": {
+ "techniques": [
+ "G130"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "header",
+ "content"
+ ],
+ "components": [
+ "headingLevel"
+ ],
+ "options": {
+ "headingLevel": 1
+ }
+ },
+ "headerH1Format": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Alle h1-Elemente werden nicht für Formatierungen verwendet",
+ "en": "All h1 elements are not used for formatting",
+ "nl": "H1-elementen worden niet gebruikt voor formatting",
+ "pt-br": "Todos os elementos h1 não são usados para formatação"
+ },
+ "description": {
+ "de": "Ein h1-Element darf nicht nur für Formatierung verwendet werden",
+ "en": "An h1 element may not be used purely for formatting.",
+ "nl": "Een h1-element mag niet alleen gebruikt worden voor formatting.",
+ "pt-br": "Um elemento h1 não pode ser usado apenas para formatação."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "T3"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "header",
+ "content"
+ ],
+ "components": [
+ "header"
+ ],
+ "options": {
+ "selector": "h1"
+ }
+ },
+ "headerH2": {
+ "type": "headingLevel",
+ "testability": 0,
+ "title": {
+ "de": "Überschriften mit Level 2 können nicht gefolgt werden von Level 4 bis 6",
+ "en": "Header level 2 can not be followed by levels from 4 to 6",
+ "nl": "De header volgend op een h2 is geen h4, h5, of h6",
+ "pt-br": "O nível de cabeçalho 2 não pode ser seguido por níveis de 4 a 6"
+ },
+ "description": {
+ "de": "Überschriften sollten keinen Level überspringen. Auf eine h2-Überschrift sollte kein h4, h5 oder h6 folgen.",
+ "en": "Header order should not skip a level. Do not follow a header level 2 with a level 4, 5, or 6.",
+ "nl": "Headers mogen geen niveau overslaan. Laat een h2-header niet volgen door een h4, h5, of h6.",
+ "pt-br": "Ordem de cabeçalho não deve saltar um nível. Não siga um nível de cabeçalho 2 com um nível 4, 5 ou 6."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.6": {
+ "techniques": [
+ "G130"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "header",
+ "content"
+ ],
+ "components": [
+ "headingLevel"
+ ],
+ "options": {
+ "headingLevel": 2
+ }
+ },
+ "headerH2Format": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Alle h2-Elemente werden nicht für Formatierungen verwendet",
+ "en": "All h2 elements are not used for formatting",
+ "nl": "H2-elementen worden niet gebruikt voor formatting",
+ "pt-br": "Todos os elementos h2 não são usados para formatação"
+ },
+ "description": {
+ "de": "Alle h2-Elemente dürfen nicht nur für Formatierung verwendet werden",
+ "en": "An h2 element may not be used purely for formatting.",
+ "nl": "Een h2-element mag niet alleen gebruikt worden voor formatting.",
+ "pt-br": "Um elemento h2 não pode ser usado puramente para formatação."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "T3"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "header",
+ "content"
+ ],
+ "components": [
+ "header"
+ ],
+ "options": {
+ "selector": "h2"
+ }
+ },
+ "headerH3": {
+ "type": "headingLevel",
+ "testability": 0,
+ "title": {
+ "de": "Überschriften mit Level 3 können nicht gefolgt werden von Level 5 und 6",
+ "en": "Header level 3 can not be followed by levels 5 and 6",
+ "nl": "De header volgend op een h3 is geen h5, of h6",
+ "pt-br": "Cabeçalho nível 3 não pode ser seguido por níveis 5 e 6"
+ },
+ "description": {
+ "de": "Überschriften sollten keinen Level überspringen. Auf eine h3-Überschrift sollte kein h5 oder h6 folgen.",
+ "en": "Header order should not skip a level. Do not follow a header level 3 with a level 5 or 6.",
+ "nl": "Headers mogen geen niveau overslaan. Laat een h3-header niet volgen door een h5, of h6.",
+ "pt-br": "Ordem de cabeçalho não deve saltar um nível. Não siga um nível de cabeçalho 3 com um nível 5 ou 6."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.6": {
+ "techniques": [
+ "G130"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "header",
+ "content"
+ ],
+ "components": [
+ "headingLevel"
+ ],
+ "options": {
+ "headingLevel": 3
+ }
+ },
+ "headerH3Format": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Alle h3-Elemente werden nicht für Formatierungen verwendet",
+ "en": "All h3 elements are not used for formatting",
+ "nl": "H3-elementen worden niet gebruikt voor formatting",
+ "pt-br": "Todos os elementos h3 não são usados para formatação"
+ },
+ "description": {
+ "de": "Ein h3-Element darf nicht nur für Formatierung verwendet werden",
+ "en": "An h3 element may not be used purely for formatting.",
+ "nl": "Een h3-element mag niet alleen gebruikt worden voor formatting.",
+ "pt-br": "Um elemento h3 não pode ser usado apenas para formatação."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "T3"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "header",
+ "content"
+ ],
+ "components": [
+ "header"
+ ],
+ "options": {
+ "selector": "h3"
+ }
+ },
+ "headerH4": {
+ "type": "headingLevel",
+ "testability": 0,
+ "title": {
+ "de": "Überschriften mit Level 4 können nicht gefolgt werden von Level 6",
+ "en": "Header level 4 can not be followed by level 6",
+ "nl": "De header volgend op een h4 is geen h6",
+ "pt-br": "Cabeçalho nível 4 não pode ser seguido por nível 6"
+ },
+ "description": {
+ "de": "Überschriften sollten keinen Level überspringen. Auf eine h4-Überschrift sollte kein h6 folgen.",
+ "en": "Header order should not skip a level. Do not follow a header level 4 with level 6 header.",
+ "nl": "Headers mogen geen niveau overslaan. Laat een h4/code> header niet volgen door een h6.",
+ "pt-br": "Ordem de cabeçalho não deve saltar um nível. Não siga um cabeçalho nível 4 com nível 6 cabeçalho."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.6": {
+ "techniques": [
+ "G130"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "header",
+ "content"
+ ],
+ "components": [
+ "headingLevel"
+ ],
+ "options": {
+ "headingLevel": 4
+ }
+ },
+ "headerH4Format": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Alle h4-Elemente werden nicht für Formatierungen verwendet",
+ "en": "All h4 elements are not used for formatting",
+ "nl": "H4-elementen worden niet gebruikt voor formatting",
+ "pt-br": "Todos os elementos h4 não são usados para formatação"
+ },
+ "description": {
+ "de": "Ein h4-Element darf nicht nur für Formatierung verwendet werden",
+ "en": "An h4 element may not be used purely for formatting.",
+ "nl": "Een h4-element mag niet alleen gebruikt worden voor formatting.",
+ "pt-br": "Um elemento h4 não pode ser usado apenas para formatação."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "T3"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "header",
+ "content"
+ ],
+ "components": [
+ "header"
+ ],
+ "options": {
+ "selector": "h4"
+ }
+ },
+ "headerH5Format": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Alle h5-Elemente werden nicht für Formatierungen verwendet",
+ "en": "All h5 elements are not used for formatting",
+ "nl": "H5-elementen worden niet gebruikt voor formatting",
+ "pt-br": "Todos os elementos h5 não são usados para formatação"
+ },
+ "description": {
+ "de": "Ein h5-Element darf nicht nur für Formatierung verwendet werden",
+ "en": "An h5 element may not be used purely for formatting.",
+ "nl": "Een h5-element mag niet alleen gebruikt worden voor formatting.",
+ "pt-br": "Um elemento h5 não pode ser usado apenas para formatação."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "T3"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "header",
+ "content"
+ ],
+ "options": {
+ "selector": "h5"
+ }
+ },
+ "headerH6Format": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Alle h6-Elemente werden nicht für Formatierungen verwendet",
+ "en": "All h6 elements are not used for formatting",
+ "nl": "H6-elementen worden niet gebruikt voor formatting",
+ "pt-br": "Todos os elementos h6 não são usados para formatação"
+ },
+ "description": {
+ "de": "Ein h6-Element darf nicht nur für Formatierung verwendet werden",
+ "en": "An h6 element may not be used purely for formatting.",
+ "nl": "Een h6-element mag niet alleen gebruikt worden voor formatting.",
+ "pt-br": "Um elemento h6 não pode ser usado apenas para formatação."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "T3"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "header",
+ "content"
+ ],
+ "options": {
+ "selector": "h6"
+ }
+ },
+ "headerTextIsTooLong": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Überschriftentext ist zu lang",
+ "en": "Header text is too long",
+ "nl": "Koptekst is te lang",
+ "pt-br": "O texto do cabeçalho é muito longo"
+ },
+ "description": {
+ "de": "Überschriften sollten keinen zu langen Text enthalten, da sie die Dokumentenstruktur zeigen sollen. Benutzer überfliegen Dokumente oft nur anhand der Überschriften.",
+ "en": "Headers should not contain too long text as they're designed to show document structure. Users will often skim document only by its headings.",
+ "nl": "Headers moet niet te lang tekst bevatten als ze zijn ontworpen om de documentstructuur te tonen. Gebruikers zullen vaak magere document alleen door zijn koppen.",
+ "pt-br": "Cabeçalhos não devem conter texto muito longo como eles são projetados para mostrar a estrutura do documento. Os usuários muitas vezes identificam os documentos apenas por seus títulos."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "H42"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "content"
+ ],
+ "callback": "headerTextIsTooLong"
+ },
+ "headersHaveText": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Alle Überschriften sollten lesbaren Text enthalten",
+ "en": "All headers should contain readable text",
+ "nl": "Alle headers moeten leesbare tekst bevatten",
+ "pt-br": "Todos os cabeçalhos devem conter texto legível"
+ },
+ "description": {
+ "de": "Benutzer mit Bildschirmleseprogrammen verwenden Überschriften wie Tabulatoren, um über die Seitenstruktur zu navigieren.",
+ "en": "Users with screen readers use headings (e.g. h1 elements), just like the tabs to navigate the structure of a page. All headings should contain either text, or images with appropriate alternative text.",
+ "nl": "Gebruikers van schermlezers gebruiken headers om via de structuur van een pagina te navigeren. Alle headers moeten daarom tekst bevatten of afbeeldingen met toepasselijk alt-attributen.",
+ "pt-br": "Os usuários com leitores de tela usam títulos (por exemplo, elementos h1), assim como as guias para navegar pela estrutura de uma página. Todos os títulos devem conter texto ou imagens com texto alternativo apropriado."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "G141"
+ ]
+ },
+ "2.4.10": {
+ "techniques": [
+ "G141"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "header",
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "content": true,
+ "empty": true,
+ "selector": "h1, h2, h3, h4, h5, h6"
+ }
+ },
+ "headersUsedToIndicateMainContent": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Verwenden Sie Überschriften, um den Beginn des Inhalts kenntlich zu machen",
+ "en": "Use header to indicate start of main content",
+ "nl": "Gebruik headers om de start van belangrijke content aan te geven",
+ "pt-br": "Usar o cabeçalho para indicar o início do conteúdo principal"
+ },
+ "description": {
+ "de": "Für jeden Hauptinhaltsbereich sollte eine Überschrift vergeben werden",
+ "en": "For every main content area, indicate the beginning of the main content using a header.",
+ "nl": "Geef het begin van de belangrijkste content in elk contentvlak aan door middel van een header.",
+ "pt-br": "Para cada área de conteúdo principal, indique o início do conteúdo principal usando um cabeçalho."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.1": {
+ "techniques": [
+ "H69"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "header",
+ "content"
+ ],
+ "callback": "headersUsedToIndicateMainContent"
+ },
+ "headersUseToMarkSections": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Verwenden Sie Überschriften, um den Anfang eines Absatz kenntlich zu machen",
+ "en": "Use headers to mark the beginning of each section",
+ "nl": "Gebruik headers om de start van elke sectie aan te geven.",
+ "pt-br": "Use cabeçalhos para marcar o início de cada seção"
+ },
+ "description": {
+ "de": "Stellen Sie sicher, dass jeder logische Abschnitt in der Seite durch eine Überschrift abgetrennt wird.",
+ "en": "Check that each logical section of the page is broken or introduced with a header (h1-h6) element.",
+ "nl": "Controleer dat elke logische sectie van een pagina wordt onderbroken door of start met een header-element (h1-h6).",
+ "pt-br": "Verifique se cada seção lógica da página está quebrada ou introduzida com um elemento de cabeçalho (h1-h6)."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "G141"
+ ]
+ },
+ "2.4.1": {
+ "techniques": [
+ "G141",
+ "H69"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "header",
+ "content"
+ ],
+ "callback": "headersUseToMarkSections"
+ },
+ "idRefHasCorrespondingId": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Elemente mit einem \"idref type\"-Attribut müssen mit einem Element mit der ID korrespondieren",
+ "en": "Elements with an idref type attribute must correspond to an element with an ID",
+ "nl": "Elementen met een idref type attribuut moeten corresponderen met een element met een ID",
+ "pt-br": "Os elementos com um atributo de tipo idref devem corresponder a um elemento com um ID"
+ },
+ "description": {
+ "de": "Wenn ein \"idref type\"-Attrbiut verwendet wird, muss das Ziel-Element mit der ID auf der Seite existieren.",
+ "en": "When using an idref type attribute, the target element with the ID must exist on the page.",
+ "nl": "Wanneer je een idref type attibuut gebruikt, moet het doelelement met dit ID ook bestaan op de pagina.",
+ "pt-br": "Ao usar um atributo de tipo idref, o elemento de destino com o ID deve existir na página."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "F17"
+ ]
+ },
+ "4.1.1": {
+ "techniques": [
+ "F17"
+ ]
+ }
+ }
+ },
+ "callback": "idRefHasCorrespondingId"
+ },
+ "idrefsHasCorrespondingId": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Elemente mit einem \"idref\"-Attribut muss mit einem Element mit der ID korrespondieren",
+ "en": "Elements with an idref attribute must correspond to an element with an ID",
+ "nl": "Elementen met een idref-attribuut moeten corresponderen met een element met een ID",
+ "pt-br": "Os elementos com um atributo idref devem corresponder a um elemento com um ID"
+ },
+ "description": {
+ "de": "",
+ "en": "",
+ "nl": "",
+ "pt-br": ""
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "F17"
+ ]
+ },
+ "4.1.1": {
+ "techniques": [
+ "F17"
+ ]
+ }
+ }
+ },
+ "callback": "idrefsHasCorrespondingId"
+ },
+ "iIsNotUsed": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Das \"i\"-Element (italic) darf nicht verwendet werden",
+ "en": "The \"i\" (italic) element is not used",
+ "nl": "Het \"i\"-element (cursief) wordt niet gebruikt",
+ "pt-br": "O elemento \"i\" (itálico) não é usado"
+ },
+ "description": {
+ "de": "Das i-Element (italic) bietet keine Hervorhebung für sehbehinderte Benutzer. Das em-Element sollte anstelle dessen verwendet werden",
+ "en": "The i (italic) element provides no emphasis for non-sighted readers. Use the em tag instead.",
+ "nl": "Het i-element biedt geen nadruk voor slechtziende en blinde lezers. Gebruik in plaats daarvan de em-tag.",
+ "pt-br": "O elemento i (itálico) não fornece ênfase para os leitores não-videntes. Em vez disso, use a tag em."
+ },
+ "guidelines": [],
+ "tags": [
+ "deprecated",
+ "content"
+ ],
+ "options": {
+ "selector": "i"
+ }
+ },
+ "iframeMustNotHaveLongdesc": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Inline-Frames (\"ifframes\") sollten kein \"longdesc\"-Attribut haben",
+ "en": "Inline frames (\"iframes\") should not have a \"longdesc\" attribute",
+ "nl": "Inline frames (\"iframes\") krijgen geen \"longdesc\"-attribuut",
+ "pt-br": "Os frames inline (\"iframes\") não devem ter um atributo \"longdesc\""
+ },
+ "description": {
+ "de": "Inline-Frames (\"ifframes\") sollten kein \"longdesc\"-Attribut haben",
+ "en": "Inline frames (iframe) should not have a \"longdesc\" attribute.",
+ "nl": "Inline frames (\"iframes\") krijgen geen \"longdesc\"-attribuut.",
+ "pt-br": "Os frames inline (iframe) não devem ter um atributo \"longdesc\"."
+ },
+ "guidelines": [],
+ "tags": [
+ "objects",
+ "iframe",
+ "content"
+ ],
+ "options": {
+ "selector": "iframe[longdesc]"
+ }
+ },
+ "imageMapServerSide": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Alle Verknüpfungen in einer server-seitigen map sollten duplizierte Verknüpfungen im Dokument haben",
+ "en": "All links in a server-side map should have duplicate links available in the document",
+ "nl": "Alle links in een server-side map moeten elders in het document terugkeren",
+ "pt-br": "Todos os links em um mapa do lado do servidor devem ter links duplicados disponíveis no documento"
+ },
+ "description": {
+ "de": "Für jede Grafik mit einem \"usemap\"-Attribut, für eine server-seitige \"image map\", sollten die Verknüpfungen der \"image map\" an andere Stelle dupliziert haben",
+ "en": "Any image with an \"usemap\" attribute for a server-side image map should have the available links duplicated elsewhere.",
+ "nl": "Elke afbeelding met een \"usemap\"-attribuut voor een server-side map moet de beschikbare links ook elders hebben.",
+ "pt-br": "Qualquer imagem com um atributo \"usemap\" para um mapa de imagem do lado do servidor deve ter os links disponíveis duplicados em outro lugar."
+ },
+ "guidelines": [],
+ "tags": [
+ "objects",
+ "iframe",
+ "content"
+ ],
+ "options": {
+ "selector": "img[ismap]"
+ }
+ },
+ "imgAltEmptyForDecorativeImages": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Wenn eine Grafik nur für dekorative Zwecke verwendet wird, muss das \"alt\"-Attribut leer sein",
+ "en": "If an image is purely decorative, the \"alt\" text must be empty",
+ "nl": "Als een afbeelding alleen ter decoratie is, moet de \"alt\"-tekst leeg zijn",
+ "pt-br": "Se uma imagem é puramente decorativa, o texto \"alt\" deve estar vazio"
+ },
+ "description": {
+ "de": "Bei jeder Grafik, die nur dekorativen Zwecken dient (ohne Funktion oder inhaltliche Bedeutung), muss das \"alt\"-Attribut leer sein",
+ "en": "Any image that is only decorative (serves no function or adds to the purpose of the page content) should have an empty \"alt\" attribute.",
+ "nl": "Elke afbeelding die alleen ter decoratie is (en die dus geen functie heeft of bijdraagt aan het doel van een contentpagina) moet een leeg \"alt\"-attirbuut hebben.",
+ "pt-br": "Qualquer imagem que seja apenas decorativa (não serve a nenhuma função ou adiciona à finalidade do conteúdo da página) deve ter um atributo \"alt\" vazio."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.3": {
+ "techniques": [
+ "F26"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "image",
+ "content"
+ ],
+ "options": {
+ "selector": "img[alt]"
+ }
+ },
+ "imgAltIdentifiesLinkDestination": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Jede Grafik mit einer Verknüpfung muss einen \"alt\"-Text haben, der das Verknüpfungsziel beschreibt",
+ "en": "Any image within a link must have \"alt\" text the describes the link destination",
+ "nl": "Elke afbeelding binnen een link moet een \"alt\"-tekst hebben die de bestemming van de link beschrijft",
+ "pt-br": "Qualquer imagem dentro de um link deve ter texto \"alt\" descreve o destino do link"
+ },
+ "description": {
+ "de": "Jede Grafik in einer Verknüpfung muss einen \"alt\"-Text haben, der das Ziel und den Zweck der Verknüpfung beschreibt",
+ "en": "Any image that is within a link should have an \"alt\" attribute which identifies the destination or purpose of the link.",
+ "nl": "Elke afbeelding binnen link moet een \"alt\"-tekst hebben die de bestemming of het doel van de link beschrijft."
+ },
+ "guidelines": [],
+ "tags": [
+ "image",
+ "content"
+ ],
+ "options": {
+ "selector": "a img[alt]:first"
+ }
+ },
+ "imgAltIsDifferent": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Der Alternativtext einer Grafik sollte nicht mit dem Dateinamen übereinstimmen",
+ "en": "Image alternative text should not be the same as the file name",
+ "nl": "\"Alt\"-attributen van afbeeldingen moeten niet hetzelfde zijn als de bestandsnaam",
+ "pt-br": "O texto alternativo da imagem não deve ser o mesmo que o nome do arquivo"
+ },
+ "description": {
+ "de": "Jede Grafik sollte einen aussagekräftigen Alternativtext haben. Der Dateiname ist selten aussagekräftig und reflektiert nicht immer die in der Grafik dargestellte Information.",
+ "en": "All images should have a meaningful alternative text. The file name is rarely meaningful and does not always reflect information presented by the image.",
+ "nl": "Alle img-elementen moeten een \"alt\"-attribuut hebben dat anders is dan de bestandsnaam van de afbeelding.",
+ "pt-br": "Todas as imagens devem ter um texto alternativo significativo. O nome do arquivo raramente é significativo e nem sempre reflete as informações apresentadas pela imagem."
+ },
+ "guidelines": {
+ "508": [
+ "a"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H37"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "image",
+ "content"
+ ],
+ "callback": "imgAltIsDifferent"
+ },
+ "imgAltIsSameInText": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Prüfen Sie, das Texte in einer Grafik auch im \"alt\"-Attribut vorhanden sind",
+ "en": "Check that any text within an image is also in the \"alt\" attribute",
+ "nl": "Controleer dat tekst in een afbeelding ook is opgenomen in het \"alt\"-attribuut",
+ "pt-br": "Verifique se qualquer texto dentro de uma imagem também está no atributo \"alt\""
+ },
+ "description": {
+ "de": "Wenn eine Grafik einen Text enthält, sollte dieser auch im \"alt\"-Attribut enthalten sein",
+ "en": "If an image has text within it, that text should be repeated in the \"alt\" attribute",
+ "nl": "Als een afbeelding tekst bevat, moet deze tekst herhaald worden in het \"alt\"-attribuut.",
+ "pt-br": "Se uma imagem tiver texto dentro dele, esse texto deve ser repetido no atributo \"alt\""
+ },
+ "guidelines": {
+ "508": [
+ "a"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "G74",
+ "H37"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "image",
+ "content"
+ ],
+ "options": {
+ "selector": "img"
+ }
+ },
+ "imgAltIsTooLong": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Der Alternativtext der Grafik ist zu lang",
+ "en": "Image alternative text is too long",
+ "nl": "Altteksten voor een afbeelding zijn kort",
+ "pt-br": "O texto alternativo da imagem é muito longo"
+ },
+ "description": {
+ "de": "Der Alternativtext der Grafik sollte kurz und prägnant sein. Es sollte geprüft werden, ob Alternativtexte die länger als 100 Zeichen sind, gekürzt werden können",
+ "en": "Image alternative text should be clear and concise. Alternative text longer than 100 characters should be reviewed to see if it can be shortened.",
+ "nl": "Alle \"alt\"-attributen voor img-elementen moeten duidelijk en bondig zijn. Verifieer \"alt\"-attributen langer dan 100 tekens en kort ze in waar mogelijk.",
+ "pt-br": "O texto alternativo da imagem deve ser claro e conciso. Texto alternativo com mais de 100 caracteres deve ser revisado para ver se ele pode ser encurtado."
+ },
+ "guidelines": {
+ "508": [
+ "a"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H37"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "image",
+ "content"
+ ],
+ "callback": "imgAltIsTooLong"
+ },
+ "imgAltNotEmptyInAnchor": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Eine Grafik innerhalb einer Verknüpfung darf keinen leeren Alternativtext haben, wenn kein anderer Text in der Verknüpfung vorkommt",
+ "en": "An image within a link cannot have an empty alternative text if there is no other text within the link",
+ "nl": "Een afbeelding binnen een link mag geen leeg \"alt\"-attribuut hebben als er geen andere tekst is in de link",
+ "pt-br": "Uma imagem dentro de um link não pode ter um texto alternativo vazio se não houver outro texto dentro do link"
+ },
+ "description": {
+ "de": "Jede Grafik innerhalb einer Verknüpfung ohne Verknüpfungstext, darf keinen leeren Alternativtext haben",
+ "en": "Any image that is within a link that has no other text cannot have an empty or missing alternative text.",
+ "nl": "Elke afbeelding binnen een link (een a-element) die geen andere tekst heeft, mag geen leeg of ontbrekend \"alt\"-attribuut hebben.",
+ "pt-br": "Qualquer imagem que esteja dentro de um link que não tenha outro texto não pode ter um texto alternativo vazio ou ausente."
+ },
+ "guidelines": {
+ "508": [
+ "a"
+ ],
+ "wcag": {
+ "2.4.4": {
+ "techniques": [
+ "H30"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "image",
+ "content"
+ ],
+ "callback": "imgAltNotEmptyInAnchor"
+ },
+ "imgAltNotPlaceHolder": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Grafiken sollten keinen einfachen Platzhaltertext im \"alt\"-Attribut haben",
+ "en": "Images should not have a simple placeholder text as an \"alt\" attribute",
+ "nl": "Afbeeldingen mogen geen placeholdertkest als \"alt\"-attribuut hebben",
+ "pt-br": "As imagens não devem ter um texto de espaço reservado simples como um atributo \"alt\""
+ },
+ "description": {
+ "de": "Jede Grafik die nicht zur Dekoration oder für das Layout verwendet wird, muss einen Alternativtext haben, der nicht nur ein Platzhalter ist",
+ "en": "Any image that is not used decorativey or which is purely for layout purposes cannot have an \"alt\" attribute that consists solely of placeholders.",
+ "nl": "Elke afbeelding die niet ter decoratie is of die alleen voor lay-out doeleinden is bedoeld, mag geen \"alt\"-attribuut hebben met daarin placeholdertekst.",
+ "pt-br": "Qualquer imagem que não é usada decorativamente ou que é puramente para fins de layout não pode ter um atributo \"alt\" que consiste exclusivamente em espaços reservados."
+ },
+ "guidelines": {
+ "508": [
+ "a"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "F30",
+ "F39"
+ ]
+ },
+ "1.2.1": {
+ "techniques": [
+ "F30"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "image",
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "attribute": "alt",
+ "selector": "img"
+ }
+ },
+ "imgAltTextNotRedundant": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Der Alternativtext sollten nur einmal vorkommen, außer die Grafik wird redundant verwendet",
+ "en": "Unless the image files are the same, no image should contain redundant alt text",
+ "nl": "Tenzij afbeeldingen hetzelfde zijn, mag geen enkele afbeelding dezelfde alttekst hebben",
+ "pt-br": "A menos que os arquivos de imagem sejam iguais, nenhuma imagem deve conter texto alternativo redundante"
+ },
+ "description": {
+ "de": "Jede Grafik auf einer Seite solle einen eigenen Alternativtext haben, der sich von anderen unterscheidet, um Verwirrungen oder Redundanz zu vermeiden",
+ "en": "Every distinct image on a page should have it's own alt text which is different than all the others on the page to avoid redundancy and confusion.",
+ "nl": "Elke unieke afbeelding op een pagina moet zijn eigen alttekst hebben die anders is dan die van andere afbeeldingen op de pagina om dubbeling en verwarring te voorkomen.",
+ "pt-br": "Cada imagem distinta em uma página deve ter seu próprio texto alternativo que é diferente de todos os outros na página para evitar redundância e confusão."
+ },
+ "guidelines": [],
+ "tags": [
+ "image",
+ "content"
+ ],
+ "callback": "imgAltTextNotRedundant"
+ },
+ "imgGifNoFlicker": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Animierte GIFs sollte nicht flackern",
+ "en": "Any animated GIF should not flicker",
+ "nl": "Geen enkele animated GIF mag knipperen of flitsen",
+ "pt-br": "Qualquer GIF animado não deve piscar"
+ },
+ "description": {
+ "de": "Animierte GIF-Dateien sollten nicht flackern (über 2 Hz und unter 55 Hz). Sie können die Flacker-Rate der GIF mit Hilfe eines Online-Werkzeugs prüfen.",
+ "en": "Animated GIF files should not flicker with a frequency over 2 Hz and lower than 55 Hz. You can check the flicker rate of this GIF using an online tool.",
+ "nl": "Animated GIF-bestanden mogen niet knipperen of flitsen met een frequentie hoger dan 2 Hz en lager dan 55 Hz. Controleer de frequentie van deze GIF met een online tool.",
+ "pt-br": "Arquivos GIF animados não devem piscar com uma freqüência acima de 2 Hz e inferior a 55 Hz. Você pode verificar a taxa de cintilação deste GIF usando uma ferramenta on-line ."
+ },
+ "guidelines": {
+ "508": [
+ "j"
+ ],
+ "wcag": {
+ "2.2.2": {
+ "techniques": [
+ "G152"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "image",
+ "content"
+ ],
+ "callback": "imgGifNoFlicker"
+ },
+ "imgHasAlt": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Grafiken sollten einen Alternativtext haben",
+ "en": "Images must provide alternative text",
+ "nl": "Afbeeldingselementen moeten een \"alt\"-attribuut hebben",
+ "pt-br": "As imagens devem fornecer texto alternativo"
+ },
+ "description": {
+ "de": "Der Alternativtext sollte dieselben Informationen liefern, wie die Grafik. Dieser Text wird verwendet, wenn Grafiken im Browser deaktiviert wurden, die Grafik auf dem Server nicht gefunden werden kann oder für sehbehinderte Benutzer, die ein Bildschirmleseprogramm verwenden.",
+ "en": "Alternative text needs to convey the same information as the image. This text will be used when the browser has disabled images, the image was not found on the server, or by non-sighted visitors who use screen readers.",
+ "nl": "Alle img-elementen moeten een \"alt\"-attribuut hebben.",
+ "pt-br": "O texto alternativo precisa transmitir as mesmas informações da imagem. Este texto será usado quando o navegador tiver desativado imagens, a imagem não foi encontrada no servidor ou por visitantes sem visão que usam leitores de tela."
+ },
+ "guidelines": {
+ "508": [
+ "a"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "F65",
+ "H37"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "image",
+ "content"
+ ],
+ "options": {
+ "selector": "img:not(img[alt])"
+ }
+ },
+ "imgHasLongDesc": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Ein \"longdesc\"-Attribut wird für jede Grafik benötigt, bei der die Informationen im \"alt\"-Attribut nicht ausreichend ist",
+ "en": "A \"longdesc\" attribute is required for any image where additional information not in the \"alt\" attribute is required",
+ "nl": "Een \"longdesc\"-attribuut is verplicht voor elke afbeelding waar aanvullende informatie niet benodigd is in het \"alt\"-attribuut",
+ "pt-br": "Um atributo \"longdesc\" é necessário para qualquer imagem onde informações adicionais que não estejam no atributo \"alt\" sejam necessárias"
+ },
+ "description": {
+ "de": "Jede Grafik mit einem \"alt\"-Attribut, welches die volle Bedeutung der Grafik nicht vollständig beschreibt, muss ein \"longdesc\"-Attribut haben",
+ "en": "Any image that has an \"alt\" attribute that does not fully convey the meaning of the image must have a \"longdesc\" attribute.",
+ "nl": "Elke afbeelding die een \"alt\"-attribuut heeft dat de volledige betekenis van de afbeelding bevat, moet een \"longdesc\"-attribuut hebben.",
+ "pt-br": "Qualquer imagem que tenha um atributo \"alt\" que não transmita completamente o significado da imagem deve ter um atributo \"longdesc\"."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.4": {
+ "techniques": [
+ "G91"
+ ]
+ },
+ "2.4.9": {
+ "techniques": [
+ "G91"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "image",
+ "content"
+ ],
+ "callback": "imgHasLongDesc"
+ },
+ "imgImportantNoSpacerAlt": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Wichtige Grafiken sollten nicht nur ein leeres \"alt\"-Attribut haben",
+ "en": "Images that are important should not have a purely white-space \"alt\" attribute",
+ "nl": "Afbeeldingen die belangrijk zijn mogen geen leeg \"alt\"-attribuut hebben",
+ "pt-br": "As imagens que são importantes não devem ter um atributo \"alt\" de espaço branco"
+ },
+ "description": {
+ "de": "Jede Grafik, die nicht nur zur Dekoration oder für das Layout verwendet wird, sollte ein \"alt\"-Attribut haben, dass nicht nur aus Leerzeichen besteht",
+ "en": "Any image that is not used decorativey or which is purely for layout purposes cannot have an \"alt\" attribute that consists solely of white space (i.e. a space).",
+ "nl": "Elke afbeelding die niet ter decoratie is of die alleen voor lay-out doeleinden is bedoeld, mag geen leeg \"alt\"-attribuut hebben (bijvoorbeeld alleen een spatie).",
+ "pt-br": "Qualquer imagem que não é usada decorativamente ou que é puramente para fins de layout não pode ter um atributo \"alt\" que consiste exclusivamente em espaço em branco (ou seja, um espaço)."
+ },
+ "guidelines": [],
+ "tags": [
+ "image",
+ "content"
+ ],
+ "callback": "imgImportantNoSpacerAlt"
+ },
+ "imgMapAreasHaveDuplicateLink": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Alle Verknüpfungen in einer client-seitigen image map sollten duplizierte Verknüpfungen im Dokument haben",
+ "en": "All links within a client-side image are duplicated elsewhere in the document",
+ "nl": "Alle links met een client-side afbeelding moeten elders in het document terugkeren",
+ "pt-br": "Todos os links dentro de uma imagem do lado do cliente são duplicados em outro local do documento"
+ },
+ "description": {
+ "de": "Für jede Grafik mit einem \"usemap\"-Attribut, für eine client-seitige \"image map\", sollten die Verknüpfungen der \"image map\" an andere Stelle dupliziert haben",
+ "en": "Any image that has a \"usemap\" attribute must have links replicated somewhere else in the document.",
+ "nl": "Elke afbeelding met een \"usemap\"-attribuut moet een link elders in het document hebben.",
+ "pt-br": "Qualquer imagem que tenha um atributo \"usemap\" deve ter links replicados em outro lugar no documento."
+ },
+ "guidelines": {
+ "508": [
+ "ef",
+ "ef"
+ ]
+ },
+ "tags": [
+ "image",
+ "imagemap"
+ ],
+ "callback": "imgMapAreasHaveDuplicateLink"
+ },
+ "imgNonDecorativeHasAlt": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Jede nicht-dekorative Grafik sollte ein nicht-leeres \"alt\"-Attribut haben",
+ "en": "Any non-decorative images should have a non-empty \"alt\" attribute",
+ "nl": "Elke niet-decoratieve afbeelding moet een gevuld \"alt\"-attribuut hebben",
+ "pt-br": "Todas as imagens não-decorativas devem ter um atributo \"alt\" não vazio"
+ },
+ "description": {
+ "de": "Jede Grafik die nicht zur Dekoration oder für das Layout verwendet wird, darf kein leeres \"alt\"-Attribut haben",
+ "en": "Any image that is not used decorativey or which is purely for layout purposes cannot have an empty \"alt\" attribute.",
+ "nl": "Elke afbeelding die niet ter decoratie is of voor lay-out doeleinden wordt gebruikt, moet een gevuld \"alt\"-attribuut hebben.",
+ "pt-br": "Qualquer imagem que não seja usada decorativamente ou que seja puramente para fins de layout não pode ter um atributo \"alt\" vazio."
+ },
+ "guidelines": {
+ "508": [
+ "a"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "F38"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "image",
+ "content"
+ ],
+ "callback": "imgNonDecorativeHasAlt"
+ },
+ "imgNotReferredToByColorAlone": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Der Alternativtext einer Grafik kann nicht nur auf eine Farbe verweisen",
+ "en": "For any image, the \"alt\" text cannot refer to color alone",
+ "nl": "Voor elke afbeelding geldt dat de \"alt\"-tekst niet alleen aan kleur mag refereren",
+ "pt-br": "Para qualquer imagem, o texto \"alt\" não pode se referir à cor sozinho"
+ },
+ "description": {
+ "de": "Der \"alt\"-Text oder Inhaltstext einer Grafik sollte nicht nur auf die Farbe der Grafik verweisen. Das \"alt\"-Attribut sollte die Bedeutung der Grafik beinhalten",
+ "en": "The \"alt\" text or content text for any image should not refer to the image by color alone. This is often fixed by changing the \"alt\" text to the meaning of the image",
+ "nl": "De \"alt\"-tekst of content voor elke afbeelding mag niet alleen maar een kleur bevatten. Neem in de \"alt\"-tekst de betekenis van de afbeelding op.",
+ "pt-br": "O texto \"alt\" ou texto de conteúdo para qualquer imagem não deve se referir à imagem por cor sozinho. Isso é muitas vezes corrigido alterando o texto \"alt\" para o significado da imagem"
+ },
+ "guidelines": {
+ "508": [
+ "c"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "F13"
+ ]
+ },
+ "1.4.1": {
+ "techniques": [
+ "F13"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "image",
+ "color",
+ "content"
+ ],
+ "options": {
+ "selector": "img"
+ }
+ },
+ "imgServerSideMapNotUsed": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Server-seitige image maps sollten nicht verwendet werden",
+ "en": "Server-side image maps should not be used",
+ "nl": "Server-side image maps moeten niet worden gebruikt",
+ "pt-br": "Mapas de imagens do lado do servidor não devem ser usados"
+ },
+ "description": {
+ "de": "Server-seitige image maps sollten nicht verwendet werden",
+ "en": "Server-side image maps should not be used.",
+ "nl": "Server-side image maps mogen niet worden gebruikt.",
+ "pt-br": "Os mapas de imagem do lado do servidor não devem ser usados."
+ },
+ "guidelines": [],
+ "tags": [
+ "image",
+ "imagemap",
+ "content"
+ ],
+ "options": {
+ "selector": "img[ismap]"
+ }
+ },
+ "imgShouldNotHaveTitle": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Grafiken sollten kein \"title\"-Attribut haben",
+ "en": "Images should not have a \"title\" attribute",
+ "nl": "Afbeeldingen moeten geen \"title\"-attribuut hebben",
+ "pt-br": "As imagens não devem ter um atributo \"title\""
+ },
+ "description": {
+ "de": "Grafiken sollten kein \"title\"-Attribut haben",
+ "en": "Images should not contain a \"title\" attribute.",
+ "nl": "Afbeeldingen zouden geen \"title\"-attribuut moeten bevatten.",
+ "pt-br": "As imagens não devem conter um atributo \"title\"."
+ },
+ "guidelines": [],
+ "tags": [
+ "image",
+ "content"
+ ],
+ "options": {
+ "selector": "img[title]"
+ }
+ },
+ "imgWithEmptyAlt": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Leere Alternativtexte sollte nur für dekorative Grafiken verwendet werden",
+ "en": "Use empty alternative text only for decorative images",
+ "nl": "",
+ "pt-br": "Utilize texto alternativo vazio apenas para imagens decorativas"
+ },
+ "description": {
+ "de": "Leere Alternativtexte können nur für Grafiken verwendet werden, die rein dekorativ sind. Wenn eine Grafik eine Information übermitteln soll, muss ein korrekter Alternativtext gesetzt werden.",
+ "en": "Empty alternative text can only be used if the image serves purely decoration purposes. If the image is supposed to convey any information whatsoever, you need to set a proper alternative text for it.",
+ "nl": "",
+ "pt-br": "Texto alternativo vazio só pode ser usado se a imagem serve apenas para fins decorativos. Se a imagem é suposto para transmitir qualquer informação que seja, você precisa definir um texto alternativo adequado para ele."
+ },
+ "guidelines": [],
+ "tags": [
+ "image",
+ "content"
+ ],
+ "options": {
+ "selector": "img[alt=\"\"]"
+ }
+ },
+ "imgWithMapHasUseMap": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Jede Grafik mit einem \"ismap\"-Attribut muss ein korrektes \"usemap\"-Attribut haben",
+ "en": "Any image with an \"ismap\" attribute have a valid \"usemap\" attribute",
+ "nl": "Elke afbeelding met een \"ismap\"-attribuut heeft een geldig \"usemap\"-attribuut",
+ "pt-br": "Qualquer imagem com um atributo \"ismap\" tem um atributo \"usemap\" válido"
+ },
+ "description": {
+ "de": "Wenn eine Grafik ein \"ismap\"-Attribut hat, muss es ein korrektes \"usemap\"-Attribut haben",
+ "en": "If an image has an \"ismap\" attribute it must have a valid \"usemap\" attribute.",
+ "nl": "Als een afbeelding een \"ismap\"-attribuut heeft, moet het ook een geldig \"usemap\"-attribuut hebben",
+ "pt-br": "Se uma imagem tem um atributo \"ismap\" ela deve ter um atributo \"usemap\" válido."
+ },
+ "guidelines": {
+ "508": [
+ "ef",
+ "ef"
+ ]
+ },
+ "tags": [
+ "image",
+ "imagemap",
+ "content"
+ ],
+ "options": {
+ "selector": "img[ismap]:not(img[usemap])"
+ }
+ },
+ "imgWithMathShouldHaveMathEquivalent": {
+ "type": "custom",
+ "testability": 0,
+ "title": {
+ "de": "Grafiken, die mathematische Gleichungen enthalten, sollten ein equivalentes MathML beinhalten",
+ "en": "Images which contain math equations should provide equivalent MathML",
+ "nl": "Afbeeldingen met wiskundige vergelijking moeten een equivalent in MathML bieden",
+ "pt-br": "As imagens que contêm equações matemáticas devem fornecer MathML equivalente"
+ },
+ "description": {
+ "de": "Grafiken die eine mathematische Gleichung enthalten, sollten von einem MathML-Markup oder eine Verknüpfung dazu begleitet werden.",
+ "en": "Images which contain math equations should be accompanied or link to a document with the equivalent equation marked up with MathML.",
+ "nl": "Afbeeldingen die wiskundige vergelijkingen bevatten moeten vergezeld zijn van of linken naar een document met daarin een equivalent van de vergelijking in MathML.",
+ "pt-br": "As imagens que contêm equações matemáticas devem ser acompanhadas ou conectadas à um documento com a equação equivalente marcada com MathML ."
+ },
+ "guidelines": [],
+ "tags": [
+ "image",
+ "content"
+ ],
+ "callback": "imgWithMathShouldHaveMathEquivalent"
+ },
+ "inputCheckboxHasTabIndex": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"checkbox\"-Eingabeelemente erfordern ein korrektes \"tabindex\"-Attribut",
+ "en": "All \"checkbox\" input elements require a valid \"tabindex\" attribute",
+ "nl": "Alle \"checkbox\"-invoerelementen moeten een geldig \"tabindex\"-attribuut hebben",
+ "pt-br": "Todos os elementos de entrada \"checkbox\" requerem um atributo \"tabindex\" válido"
+ },
+ "description": {
+ "de": "Alle input-Elemente vom Typ \"checkbox\" sollten ein \"tabindex\"-Attribut haben, um das Navigieren per Tastatur zu unterstützen",
+ "en": "All input elements of type \"checkbox\" should have a \"tabindex\" attribute to help navigate the form with a keyboard alone.",
+ "nl": "Alle invoerelementen van het type \"checkbox\" moeten \"tabindex\"-attribuut hebben dat ervoor zorgt dat je door een formulier kunt navigeren met het toetsenbord.",
+ "pt-br": "Todos os elementos input do tipo \"checkbox\" devem ter um atributo \"tabindex\" para ajudar a navegar no formulário com um teclado."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "attribute": "tabindex",
+ "empty": true,
+ "selector": "input[type=checkbox]"
+ }
+ },
+ "inputCheckboxRequiresFieldset": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Logische Gruppen von Checkboxen sollten durch ein \"fieldset\" gruppiert werden",
+ "en": "Logical groups of check boxes should be grouped with a fieldset",
+ "nl": "Logische groepen van keuzevakjes moeten gegroepeerd zijn in een fieldset",
+ "pt-br": "Os grupos lógicos de caixas de seleção devem ser agrupados com um fieldset"
+ },
+ "description": {
+ "de": "Zusammengehörige \"checkbox\"-Eingabefelder sollten mit Hilfe eines fieldset gruppiert werden.",
+ "en": "Related \"checkbox\" input fields should be grouped together using a fieldset.",
+ "nl": "Gerelateerde \"keuzevakjes\"-invoervelden moeten bij elkaar staan in een fieldset.",
+ "pt-br": "Os campos de entrada \"checkbox\" relacionados devem ser agrupados usando um fieldset."
+ },
+ "guidelines": {
+ "wcag": {
+ "3.3.2": {
+ "techniques": [
+ "H71"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "callback": "inputCheckboxRequiresFieldset"
+ },
+ "inputDoesNotUseColorAlone": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Ein \"input\"-Element sollte nicht nur Farbe verwenden",
+ "en": "An \"input\" element should not use color alone",
+ "nl": "Een invoerveld mag niet alleen maar kleur gebruiken",
+ "pt-br": "Um elemento \"input\" não deve usar cor sozinho"
+ },
+ "description": {
+ "de": "\"input\"-Elemente sollten sicht nicht nur über Farbe auf Inhalte beziehen",
+ "en": "All input elements should not refer to content by color alone.",
+ "nl": "Elk invoerveld moet naar content verwijzen door middel van meer dan alleen kleur.",
+ "pt-br": "Todos os elementos de entrada não devem referir-se ao conteúdo apenas por cor."
+ },
+ "guidelines": {
+ "508": [
+ "c"
+ ]
+ },
+ "tags": [
+ "form",
+ "color",
+ "content"
+ ],
+ "options": {
+ "selector": "input:not(input[type=hidden])"
+ }
+ },
+ "inputElementsDontHaveAlt": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Eingabelemente, die keine Grafiken sind, sollten kein \"alt\"-Attribut haben",
+ "en": "Input elements which are not images should not have an \"alt\" attribute",
+ "nl": "Invoervelden die geen afbeelding zijn, moeten geen \"alt\"-attribuut hebben",
+ "pt-br": "Os elementos de entrada que não são imagens não devem ter um atributo \"alt\"."
+ },
+ "description": {
+ "de": "Eingabeelemente, die keine Grafik sind, sollten kein \"alt\"-Attribut haben, weil dies zu Inkonsistenz bei der Benutzung von Alternativtexten führt.",
+ "en": "Input elements which are not images should not have an \"alt\" attribute, because of inconsistencies in how user agents use the \"alt\" attribute.",
+ "nl": "Invoervelden die geen afbeelding zijn, moeten geen \"alt\"-attribuut hebben, omdat user agents het \"alt\"-attribuut niet consistent gebruiken.",
+ "pt-br": "Os elementos de entrada que não são imagens não devem ter um atributo \"alt\", devido a inconsistências na forma como os agentes de utilizador utilizam o atributo \"alt\"."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "options": {
+ "selector": "input[type!=image][alt]"
+ }
+ },
+ "inputFileHasTabIndex": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"file\"-Eingabeelemente erfordern ein korrektes \"tabindex\"-Attribut",
+ "en": "All \"file\" input elements require a valid \"tabindex\" attribute",
+ "nl": "Alle \"document\"-invoerelementen moeten een geldig \"tabindex\"-attribuut hebben",
+ "pt-br": "Todos os elementos de entrada \"file\" requerem um atributo \"tabindex\" válido"
+ },
+ "description": {
+ "de": "Alle input-Elemente vom Typ \"file\" sollten ein \"tabindex\"-Attribut haben, um das Navigieren per Tastatur zu unterstützen",
+ "en": "All input elements of type \"file\" should have a \"tabindex\" attribute to help navigate the form with a keyboard alone.",
+ "nl": "Alle invoer-elementen van het type \"file\" moeten een \"tabindex\"-attribuut hebben om navigatie van het formulier met het toetsenbord mogelijk te maken.",
+ "pt-br": "Todos os elementos input code> do tipo \"file\" devem ter um atributo \"tabindex\" para ajudar a navegar o formulário com um teclado sozinho."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "tabindex"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "attribute": "tabindex",
+ "empty": true,
+ "selector": "input[type=file]"
+ }
+ },
+ "inputImageAltIdentifiesPurpose": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Alle \"input\"-Elemente vom typ \"image\" müssen ein \"alt\"-Attribut haben, dass die Funktion beschreibt",
+ "en": "All \"input\" elements with a type of \"image\" must have an \"alt\" attribute that describes the function of the input",
+ "nl": "Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben dat de functie van de invoer beschrijft",
+ "pt-br": "Todos os elementos \"input\" com um tipo de \"imagem\" devem ter um atributo \"alt\" que descreve a função da entrada"
+ },
+ "description": {
+ "de": "Alle input-Elemente vom Typ \"image\" sollten ein \"alt\"-Attribut haben",
+ "en": "All input elements with a type of \"image\" should have an \"alt\" attribute.",
+ "nl": "Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben.",
+ "pt-br": "Todos os elementos input code> com um tipo de \"imagem\" devem ter um atributo \"alt\"."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H36"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "options": {
+ "selector": "input[type=image][alt]"
+ }
+ },
+ "inputImageAltIsNotFileName": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"input\"-Elemente vom Typ \"image\" müssen ein \"alt\"-Attribut haben, dass nicht dem Dateinamen entspricht",
+ "en": "All \"input\" elements with a type of \"image\" must have an \"alt\" attribute which is not the same as the filename",
+ "nl": "Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben dat anders is dan de bestandsnaam",
+ "pt-br": "Todos os elementos \"input\" com um tipo de \"imagem\" devem ter um atributo \"alt\" que não é o mesmo que o nome do arquivo"
+ },
+ "description": {
+ "de": "Alle input-Elemente vom Typ \"image\" müssen ein \"alt\"-Attribut haben, dass nicht dem Dateinamen entspricht",
+ "en": "All input elements with a type of \"image\" should have an \"alt\" attribute which is not the same as the filename.",
+ "nl": "Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben dat anders is dan de bestandsnaam.",
+ "pt-br": "Todos os elementos input code> com um tipo de \"imagem\" devem ter um atributo \"alt\" que não seja o mesmo que o nome do arquivo."
+ },
+ "guidelines": {
+ "508": [
+ "a"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H36"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "image",
+ "content"
+ ],
+ "callback": "inputImageAltIsNotFileName"
+ },
+ "inputImageAltIsNotPlaceholder": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"input\"-Elemente mit einem \"image\" müssen ein \"alt\"-Attribut haben, das kein Platzhalter ist",
+ "en": "All \"input\" elements with a type of \"image\" must have an \"alt\" attribute which is not placeholder text.",
+ "nl": "Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben anders dan alleen placeholdertekst.",
+ "pt-br": "Todos os elementos \"input\" com um tipo de \"imagem\" devem ter um atributo \"alt\" que não seja texto de espaço reservado."
+ },
+ "description": {
+ "de": "Alle \"input\"-Elemente mit einem \"image\" müssen ein \"alt\"-Attribut haben, das kein Platzhalter ist",
+ "en": "All \"input\" elements with a type of \"image\" must have an \"alt\" attribute which is not placeholder text.",
+ "nl": "Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben anders dan alleen placeholdertekst.",
+ "pt-br": "Todos os elementos \"input\" com um tipo de \"imagem\" devem ter um atributo \"alt\" que não seja texto de espaço reservado."
+ },
+ "guidelines": {
+ "508": [
+ "a"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H36"
+ ]
+ },
+ "2.1.1": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "4.1.2": {
+ "techniques": [
+ "H91"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "image",
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "attribute": "alt",
+ "selector": "input[type=image]"
+ }
+ },
+ "inputImageAltIsShort": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"input\"-Elemente mit einem \"image\" müssen ein \"alt\"-Attribut haben, das so kurz wie möglich ist",
+ "en": "All \"input\" elements with a type of \"image\" must have an \"alt\" attribute which is as short as possible",
+ "nl": "Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben dat zo kort mogelijk is",
+ "pt-br": "Todos os elementos \"input\" com um tipo de \"imagem\" devem ter um atributo \"alt\" o mais curto possível"
+ },
+ "description": {
+ "de": "Alle \"input\"-Elemente mit einem\"image\" müssen ein \"alt\"-Attribut haben, das so kurz wie möglich ist",
+ "en": "All \"input\" elements with a type of \"image\" must have an \"alt\" attribute which is as short as possible.",
+ "nl": "Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben dat zo kort mogelijk is.",
+ "pt-br": "Todos os elementos \"input\" com um tipo de \"imagem\" devem ter um atributo \"alt\" o mais curto possível."
+ },
+ "guidelines": {
+ "508": [
+ "a"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H36"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "image",
+ "content"
+ ],
+ "callback": "inputImageAltIsShort"
+ },
+ "inputImageAltNotRedundant": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Der \"alt\"-Text für grafische Absenden-Schaltflächen in Formularen darf kein Platzhalter sein",
+ "en": "The \"alt\" text for input \"image\" submit buttons must not be filler text",
+ "nl": "De \"alt\"-tekst for \"image\"-knoppen moet anders zijn dan alleen placeholdertekst",
+ "pt-br": "O texto \"alt\" para entrada \"imagem\" enviar botões não deve ser texto de preenchimento"
+ },
+ "description": {
+ "de": "Jede grafische Schaltfläche in einem Formular sollte nicht nur Platzhalter wie \"Schaltfläche\", \"Absenden\" als \"alt\"-Text haben",
+ "en": "Every form image button should not simply use filler text like \"button\" or \"submit\" as the \"alt\" text.",
+ "nl": "Elke formulierknop die een afbeelding is, moet bruikbare tekst als \"alt\"-tekst hebben, anders dan \"knop\" of \"verstuur\".",
+ "pt-br": "Cada botão de imagem de formulário não deve simplesmente usar texto de preenchimento como \"botão\" ou \"enviar\" como o texto \"alt\"."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H36"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "image",
+ "content"
+ ],
+ "strings": [
+ "redundant.inputImage"
+ ],
+ "callback": "inputImageAltNotRedundant"
+ },
+ "inputImageHasAlt": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"input\"-Elemente mit einem \"image\" müssen ein \"alt\"-Attribut haben",
+ "en": "All \"input\" elements with a type of \"image\" must have an \"alt\" attribute",
+ "nl": "Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben",
+ "pt-br": "Todos os elementos \"input\" com um tipo de \"imagem\" devem ter um atributo \"alt\""
+ },
+ "description": {
+ "de": "Alle input-Elemente mit einem \"image\" müssen ein \"alt\"-Attribut haben",
+ "en": "All input elements with a type of \"image\" should have an \"alt\" attribute.",
+ "nl": "Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben.",
+ "pt-br": "Todos os elementos input com um tipo de \"imagem\" devem ter um atributo \"alt\"."
+ },
+ "guidelines": {
+ "508": [
+ "a"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "F65",
+ "G94",
+ "H36"
+ ]
+ },
+ "2.1.1": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "4.1.2": {
+ "techniques": [
+ "H91"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "image",
+ "content"
+ ],
+ "options": {
+ "selector": "input[type=image]:visible",
+ "test": ":not(input[type=image][alt])"
+ }
+ },
+ "inputImageNotDecorative": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Der \"alt\"-Text für eine grafische Schaltfläche muss derselben sein, wie in der Grafik",
+ "en": "The \"alt\" text for input \"image\" buttons must be the same as text inside the image",
+ "nl": "De \"alt\"-tekst voor afbeeldingen van invoerknoppen moet hetzelfde zijn als de tekst in de afbeeldingen"
+ },
+ "description": {
+ "de": "Jede grafische Schaltfläche mit einem Text in der Grafik (bspw. \"Suche\" in der Grafik in einer speziellen Schrifthart) sollte diesen Text im \"alt\"-Text haben",
+ "en": "Every form image button which has text within the image (say, a picture of the word \"Search\" in a special font) must also have this text in the \"alt\" text.",
+ "nl": "Elke formulierknop die een afbeelding is en tekst in de afbeelding heeft (bijvoorbeeld \"Zoek\") moet deze tekst ook in de \"alt\"-tekst hebben."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H36"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "image",
+ "content"
+ ],
+ "options": {
+ "selector": "input[type=image]"
+ }
+ },
+ "inputPasswordHasTabIndex": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"password\"-Eingabeelemente erfordern ein korrektes \"tabindex\"-Attribut",
+ "en": "All \"password\" input elements require a valid \"tabindex\" attribute",
+ "nl": "Alle \"paswoord\"-invoervelden moeten een geldig \"tabindex\"-attribuut hebben",
+ "pt-br": "Todos os elementos de entrada \"password\" requerem um atributo \"tabindex\" válido"
+ },
+ "description": {
+ "de": "Alle input-Elemente vom Typ \"password\" sollten ein \"tabindex\"-Attribut haben, um das Navigieren per Tastatur zu unterstützen",
+ "en": "All input elements of type \"password\" should have a \"tabindex\" attribute to help navigate the form with a keyboard alone.",
+ "nl": "Alle input-elementen van het type \"paswoord\" moeten een \"tabindex\"-attribuut hebben om navigatie met alleen het toetsenbord mogelijk te maken.",
+ "pt-br": "Todos os elementos input do tipo \"password\" devem ter um atributo \"tabindex\" para ajudar a navegar o formulário com um teclado sozinho."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "attribute": "tabindex",
+ "empty": true,
+ "selector": "input[type=password]"
+ }
+ },
+ "inputRadioHasTabIndex": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"radio\"-Eingabeelemente erfordern ein korrektes \"tabindex\"-Attribut",
+ "en": "All \"radio\" input elements require a valid \"tabindex\" attribute",
+ "nl": "Alle invoerelementen van het type \"radio\" moeten een geldig \"tabindex\"-attribuut hebben",
+ "pt-br": "Todos os elementos de entrada \"radio\" requerem um atributo \"tabindex\" válido"
+ },
+ "description": {
+ "de": "Alle input-Elemente vom Typ \"radio\" sollten ein \"tabindex\"-Attribut haben, um das Navigieren per Tastatur zu unterstützen",
+ "en": "All input elements of type \"radio\" should have a \"tabindex\" attribute to help navigate the form with a keyboard alone.",
+ "nl": "Alle input-elementen van het type \"radio\" moeten een \"tabindex\"-attribuut hebben om navigatie met alleen het toetsenbord mogelijk te maken.",
+ "pt-br": "Todos os elementos input do tipo \"radio\" devem ter um atributo \"tabindex\" para ajudar a navegar o formulário com um teclado sozinho."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "attribute": "tabindex",
+ "empty": true,
+ "selector": "input[type=radio]"
+ }
+ },
+ "inputSubmitHasTabIndex": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"submit\"-Eingabeelemente erfordern ein korrektes \"tabindex\"-Attribut",
+ "en": "All \"submit\" input elements require a \"tabindex\" attribute",
+ "nl": "Alle invoerelementen van het type \"submit\" moeten een geldig \"tabindex\"-attribuut hebben",
+ "pt-br": "Todos os elementos de entrada \"submit\" requerem um atributo \"tabindex\"."
+ },
+ "description": {
+ "de": "Alle input-Elemente vom Typ \"submit\" sollten ein \"tabindex\"-Attribut haben, um das Navigieren per Tastatur zu unterstützen",
+ "en": "All input elements of type \"submit\" should have a \"tabindex\" attribute to help navigate the form with a keyboard alone.",
+ "nl": "Alle input-elementen van het type \"submit\" moeten een \"tabindex\"-attribuut hebben om navigatie met alleen het toetsenbord mogelijk te maken.",
+ "pt-br": "Todos os elementos input do tipo \"submit\" devem ter um atributo \"tabindex\" para ajudar a navegar o formulário com um teclado."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "attribute": "tabindex",
+ "empty": true,
+ "selector": "input[type=submit]"
+ }
+ },
+ "inputTextHasLabel": {
+ "type": "label",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"input\"-Elemente sollten ein dazugehöriges \"label\" haben",
+ "en": "All \"input\" elements should have a corresponding \"label\"",
+ "nl": "Alle invoerelementen moeten een bijbehorend \"label\" hebben",
+ "pt-br": "Todos os elementos \"input\" devem ter um elemento \"label\" correspondente"
+ },
+ "description": {
+
+ "de": "Alle input-Elemente sollten ein dazugehöriges label-Element haben. Bildschirmleseprogramme haben oftmals eine Formular-Modus, in dem nur Labels vorgelesen werden.",
+ "en": "All input elements should have a corresponding label element. Screen readers often enter a \"form mode\" where only label text is read aloud to the user",
+ "nl": "Alle input-elementen moeten een bijbehorend label-element hebben. Schermlezers maken vaak gebruik van een \"formuliereninstelling\" waarbij alleen de tekst van de labels hardop aan de gebruiker wordt voorgelezen.",
+ "pt-br": "Todos os elementos input devem ter um elemento label correspondente. Os leitores de tela costumam entrar em um \"modo de formulário\" onde somente o texto do rótulo é lido em voz alta para o usuário"
+ },
+ "guidelines": {
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H44"
+ ]
+ },
+ "1.3.1": {
+ "techniques": [
+ "H44",
+ "F68"
+ ]
+ },
+ "2.1.1": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "3.3.2": {
+ "techniques": [
+ "H44"
+ ]
+ },
+ "4.1.2": {
+ "techniques": [
+ "H44",
+ "H91"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "options": {
+ "selector": "input[type=text]"
+ }
+ },
+ "inputTextHasTabIndex": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"text\"-Eingabeelemente erfordern ein korrektes \"tabindex\"-Attribut",
+ "en": "All \"text\" input elements require a valid \"tabindex\" attribute",
+ "nl": "Alle invoerelementen van het type \"text\" moeten een geldig \"tabindex\"-attribuut hebben",
+ "pt-br": "Todos os elementos de entrada \"text\" requerem um atributo \"tabindex\" válido"
+ },
+ "description": {
+ "de": "Alle input-Elemente vom Typ \"text\" sollten ein \"tabindex\"-Attribut haben, um das Navigieren per Tastatur zu unterstützen",
+ "en": "All input elements of type \"text\" should have a \"tabindex\" attribute to help navigate the form with a keyboard alone.",
+ "nl": "Alle input-elementen van het type \"text\" moeten een \"tabindex\"-attribuut hebben om navigatie met alleen het toetsenbord mogelijk te maken.",
+ "pt-br": "Todos os elementos input code> do tipo \"text\" devem ter um atributo \"tabindex\" para ajudar a navegar o formulário com um teclado."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "attribute": "tabindex",
+ "empty": true,
+ "selector": "input[type=text]"
+ }
+ },
+ "inputTextHasValue": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"input\"-Elemente vom Typ \"text\" müssen einen Standard-Text haben",
+ "en": "All \"input\" elements of type \"text\" must have a default text",
+ "nl": "Alle invoerelementen van het type \"text\" moeten een standaardtekst hebben",
+ "pt-br": "Todos os elementos \"input\" do tipo \"text\" devem ter um texto padrão"
+ },
+ "description": {
+ "de": "Alle input-Elements vom Typ \"text\" sollten einen Standard-Text haben.",
+ "en": "All input elements of type \"text\" should have a default text.",
+ "nl": "Alle invoerelementen van het type \"text\" moeten een standaardtekst hebben.",
+ "pt-br": "Todos os elementos input do tipo \"text\" devem ter um texto padrão."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "attribute": "value",
+ "empty": true,
+ "selector": "input[type=text]"
+ }
+ },
+ "inputTextValueNotEmpty": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Text-Eingabeelemente erfordert einen nicht-leeren Standardtext",
+ "en": "Text input elements require a non-whitespace default text",
+ "nl": "Tekstinvoerelementen mogen geen lege standaardtekst hebben",
+ "pt-br": "Elementos de entrada de texto requerem um texto padrão que não permita somente espaços em branco"
+ },
+ "description": {
+ "de": "Alle input-Elemente vom Typ \"text\" sollten einen Standardtext haben, der nicht leer ist",
+ "en": "All input elements with a type of \"text\" should have a default text which is not empty.",
+ "nl": "Alle invoerelementen van het type \"text\" moeten een standaardtekst hebben die gevuld is.",
+ "pt-br": "Todos os elementos input com um tipo de \"text\" devem ter um texto padrão que não esteja vazio."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "attribute": "value",
+ "empty": true,
+ "selector": "input[type=text]"
+ }
+ },
+ "inputWithoutLabelHasTitle": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Formular-Steuerelemente ohne \"label\" sollten ein \"title\"-Attribut haben",
+ "en": "Form controls without label should have a title attribute",
+ "nl": "Formulierelementen zonder label moeten een titelattribuut hebben",
+ "pt-br": "Os controles de formulário sem rótulo devem ter um atributo de título"
+ },
+ "description": {
+ "de": "Wenn es nicht möglich ist ein \"label\" für ein Formular-Steuerelement zu haben, sollte es ein \"title\"-Attribut haben, welches den Zweck des Steuerelements beschreibt",
+ "en": "If it is not possible to have a label for a form control, then a title attribute on the element should be provided that describes the purpose of the control.",
+ "nl": "Als een formulierelement geen label kan krijgen, dan moet een dat element een titelattribuut krijgen dat het doel van het element beschrijft.",
+ "pt-br": "Se não for possível ter um rótulo para um controle de formulário, um atributo de título no elemento deve ser fornecido que descreve a finalidade do controle."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H65"
+ ]
+ },
+ "1.3.1": {
+ "techniques": [
+ "H65"
+ ]
+ },
+ "3.3.2": {
+ "techniques": [
+ "H65"
+ ]
+ },
+ "4.1.2": {
+ "techniques": [
+ "H65"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "callback": "inputWithoutLabelHasTitle"
+ },
+ "labelDoesNotContainInput": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "\"label\"-Elemente sollten keine \"input\"-Elemente enthalten",
+ "en": "Label elements should not contain an input element",
+ "nl": "Labelelementen moeten geen invoerelementen bevatten",
+ "pt-br": "Os elementos de rótulo não devem conter um elemento de entrada"
+ },
+ "description": {
+ "de": "\"label\"-Elemente sollten kein \"input\"-Element enthalten, da diese sonst von Bildschirmleseprogrammen doppelt vorgelesen werden",
+ "en": "Label elements should not wrap around another input element, as this can cause the label to be read twice by screen readers.",
+ "nl": "Labelelementen moeten niet om een ander invoerelement heenstaan, omdat dan het label twee keer kan worden voorgelezen door schermlezers.",
+ "pt-br": "Elementos de rótulo não devem envolver outro elemento de entrada, pois isso pode causar o rótulo para ser lido duas vezes por leitores de tela."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "options": {
+ "selector": "label:has(input)"
+ }
+ },
+ "labelMustBeUnique": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Jedes Formular-Eingabeelement darf nur ein Label haben",
+ "en": "Every form input must have only one label",
+ "nl": "Elk formulierinvoerveld heeft maar een label",
+ "pt-br": "Cada entrada de formulário deve ter apenas um rótulo"
+ },
+ "description": {
+ "de": "Jedes Formular-Eingabeelement sollte nur ein label-Element haben",
+ "en": "Each form input should have only one label element.",
+ "nl": "Elk formulierinvoerveld mag maar een label element hebben.",
+ "pt-br": "Cada entrada de formulário deve ter apenas um elemento label ."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "F17"
+ ]
+ },
+ "4.1.1": {
+ "techniques": [
+ "F17"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "callback": "labelMustBeUnique"
+ },
+ "labelMustNotBeEmpty": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Labels müssen Text beinhalten",
+ "en": "Labels must contain text",
+ "nl": "Labels moeten tekst bevatten",
+ "pt-br": "As etiquetas devem conter texto"
+ },
+ "description": {
+ "de": "Labels in Formularen müssen lesbaren Text enthalten, der den Zweck des Elements beschreibt",
+ "en": "Labels in forms must contain readable text that describes the target form element.",
+ "nl": "Labels in formulieren moeten leesbare tekst bevatten die het formulierelement beschrijven.",
+ "pt-br": "Etiquetas em formulários devem conter texto legível que descreve o elemento de formulário de destino."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H44"
+ ]
+ },
+ "1.3.1": {
+ "techniques": [
+ "H44",
+ "F68"
+ ]
+ },
+ "3.3.2": {
+ "techniques": [
+ "H44"
+ ]
+ },
+ "4.1.2": {
+ "techniques": [
+ "H44"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "content": true,
+ "empty": true,
+ "selector": "label"
+ }
+ },
+ "labelsAreAssignedToAnInput": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Alle Labels müssen mit einem Eingabeelement verknüpft sein",
+ "en": "All labels should be associated with an input",
+ "nl": "Alle labels moeten horen bij een invoerveld",
+ "pt-br": "Todos os rótulos devem ser associados a uma entrada"
+ },
+ "description": {
+ "de": "Alle label-Elemente sollten einem Eingabeelement zugewiesen sein und ein for-Attribut haben, welches mit dem id-Attribut eines Formular-Elements übereinstimmt",
+ "en": "All label elements should be assigned to an input item, and should have a for attribute which equals the id attribute of a form element.",
+ "nl": "Alle label-elementen moeten horen bij een invoerveld, en moeten een een for-attribuut hebben dat hetzelfde is als het id-attribuut van een formulierelement.",
+ "pt-br": "Todos os elementos label devem ser atribuídos a um item de entrada e devem ter um atributo para que seja igual ao atributo id de um elemento de formulário."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "callback": "labelsAreAssignedToAnInput"
+ },
+ "languageDirAttributeIsUsed": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Das \"dir\"-Attribut sollte bei Änderungen der Leserichtung verwendet werden",
+ "en": "Use the dir attribute when the language direction changes",
+ "nl": "Gebruik het dir-attribuut als de richting van de taal verandert",
+ "pt-br": "Use o atributo dir quando a direção do idioma mudar"
+ },
+ "description": {
+ "de": "Wehn verschachtelte Änderungen der Leserichtung in einem Text enthalten sind, sollte ein \"inline\"-Element mit dir-Attribut verwendet werden.",
+ "en": "When there are nested directional changes in text, use an inline element with a dir attribute to indicate direction.",
+ "nl": "Gebruik een inline element met een dir-attribuut om richting aan te geven wanneer er geneste richtingsveranderingen in de tekst zijn.",
+ "pt-br": "Quando há alterações direcionais aninhadas no texto, use um elemento inline com um atributo dir para indicar direção."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.2": {
+ "techniques": [
+ "H56"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "language",
+ "content"
+ ],
+ "callback": "languageDirAttributeIsUsed",
+ "components": [
+ "language"
+ ]
+ },
+ "languageChangesAreIdentified": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Das \"language\"-Attribut sollte verwendet werden, um die Leserichtung zu ändern",
+ "en": "Use language attributes to indicate changes in language",
+ "nl": "Gebruik het taal-attribuut om aan te geven dat de taal verandert",
+ "pt-br": "Usar atributos de linguagem para indicar mudanças na linguagem"
+ },
+ "description": {
+ "de": "Wenn die Sprache in einem Dokument wechselt, setzen Sie den Text mit der Sprachänderung in eine Element mit lang-Attribut.",
+ "en": "When the language of the document changes, make sure to wrap those changes in an element with the lang attribute.",
+ "nl": "Als de taal van het document verandert, zet deze veranderingen dan in een element met het lang-attribuut.",
+ "pt-br": "Quando o idioma do documento é alterado, certifique-se de envolver essas alterações em um elemento com o atributo lang ."
+ },
+ "guidelines": {
+ "wcag": {
+ "3.1.2": {
+ "techniques": [
+ "H58"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "language",
+ "content"
+ ],
+ "callback": "languageChangesAreIdentified",
+ "components": [
+ "language"
+ ]
+ },
+ "languageDirectionPunctuation": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Setzen Sie Satzzeichen bei Änderungen der Leserichtung in der korrekten Reihenfolge",
+ "en": "Place punctuation around language direction changes in the right order",
+ "nl": "Zet interpunctie bij richtingsveranderingen in taal in de juiste volgorde",
+ "pt-br": "Coloque a pontuação em torno das mudanças na direção da linguagem na ordem correta"
+ },
+ "description": {
+ "de": "Wenn Satzzeichen bei einer Änderung der Leserichtung verwendet werden, stellen Sie die korrekte Reihenfolge sicher",
+ "en": "If punctuation is used around a change in language direction, ensure the punctuation appears in the correct place.",
+ "nl": "Als er interpunctie staat bij een richtingsverandering in de taal, zorg dat deze dan op de goede plek staat.",
+ "pt-br": "Se a pontuação é usada em torno de uma mudança na direção do idioma, verifique se a pontuação aparece no lugar correto."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.2": {
+ "techniques": [
+ "G57"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "language",
+ "content"
+ ],
+ "callback": "languageDirectionPunctuation",
+ "components": [
+ "language"
+ ]
+ },
+ "languageUnicodeDirection": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Verwenden Sie die Unicode-Sprachausrichtung",
+ "en": "Use the unicode language direction",
+ "nl": "Gebruik de unicode taalrichting",
+ "pt-br": "Use a direção da linguagem unicode"
+ },
+ "description": {
+ "de": "Wenn verschachtelte Änderungen der Leserichtung auftreten, verwenden Sie die Unicode-Zeichen RTL/LTR",
+ "en": "When there are nested directional changes in language, use unicode RTL/LTR characters.",
+ "nl": "Gebruik de unicode RTL/LTR afkortingen als er geneste richtingsveranderingen in de taal zijn.",
+ "pt-br": "Quando houver alterações direcionais aninhadas no idioma, use caracteres RTL / LTR unicode."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.2": {
+ "techniques": [
+ "H34"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "language",
+ "content"
+ ],
+ "callback": "languageUnicodeDirection",
+ "components": [
+ "language"
+ ]
+ },
+ "legendDescribesListOfChoices": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Alle \"legend\"-Elemente müssen die Auswahl-Gruppe beschreiben",
+ "en": "All \"legend\" elements must describe the group of choices",
+ "nl": "Alle \"legend\"-elementen moeten een groep keuzes beschrijven",
+ "pt-br": ""
+ },
+ "description": {
+ "de": "Wenn ein legend-Element in einem Fieldset verwendet wird, muss der Inhalt im legend-Element die Auswahlgruppe beschreiben",
+ "en": "If a legend element is used in a fieldset, the legend content must describe the group of choices.",
+ "nl": "Als een legend-element wordt gebruikt in een fieldset, moet de legend content de groep keuzes beschrijven.",
+ "pt-br": "Se um elemento legend for usado em um fieldset, o conteúdo legend deve descrever o grupo de opções."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.6": {
+ "techniques": [
+ "G131"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "options": {
+ "selector": "legend"
+ }
+ },
+ "legendTextNotEmpty": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Legenden dürfen keine Leerzeichen enthalten",
+ "en": "Legend text must not contain just whitespace",
+ "nl": "Legend-tekst moet ingevuld zijn",
+ "pt-br": "O texto da legenda não deve conter apenas espaços em branco"
+ },
+ "description": {
+ "de": "Wenn ein legend-Element in einem Fieldset verwendet wird, sollte das legend-Element nicht leer sein",
+ "en": "If a legend element is used in a fieldset, the legend should not contain empty text.",
+ "nl": "Als een legend-element wordt gebruikt in een fieldset, moet de legend ingevuld zijn.",
+ "pt-br": "Se um elemento legenda for usado em um fieldset, a legenda não deve conter texto vazio."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "H71"
+ ]
+ },
+ "2.4.6": {
+ "techniques": [
+ "G131"
+ ]
+ },
+ "3.3.2": {
+ "techniques": [
+ "H71"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "options": {
+ "selector": "legend:empty"
+ }
+ },
+ "legendTextNotPlaceholder": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "\"Legend\"-Texte drüfen keine Platzhalter enthalten",
+ "en": "\"Legend\" text must not contain placeholder text",
+ "nl": "\"Legend\"-tekst moet geen placeholdertekst bevatten",
+ "pt-br": "\"Legend\" não deve conter um texto reservado (placeholder)"
+ },
+ "description": {
+ "de": "Wenn ein legend-Element in einem Fieldset verwendet wird, sollte das legend-Element keine Platzhalter enthalten.",
+ "en": "If a legend element is used in a fieldset, the legend should not contain useless placeholder text like \"form\" or \"field\".",
+ "nl": "Als een legend-element wordt gebruikt in een fieldset, moet de legend geen placeholdertekst bevatten zoals \"form\" of \"field\".",
+ "pt-br":"Se um elemento legenda for usado em um fieldset, a legenda não deve conter texto reservado inútil como \"form\" ou \"field\"."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "H71"
+ ]
+ },
+ "2.1.1": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "2.4.6": {
+ "techniques": [
+ "G131"
+ ]
+ },
+ "3.3.2": {
+ "techniques": [
+ "H71"
+ ]
+ },
+ "4.1.3": {
+ "techniques": [
+ "H91"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "content": true,
+ "emtpy": true,
+ "selector": "legend"
+ }
+ },
+ "liDontUseImageForBullet": {
+ "type": "selector",
+ "testability": 0.5,
+ "guidelines": [],
+ "tags": [
+ "list",
+ "content"
+ ],
+ "options": {
+ "selector": "li:has(img)"
+ }
+ },
+ "linkHasAUniqueContext": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Verknüpfungen sollten einen eindeutigen Zusammenhang haben",
+ "en": "Links should have a unique context",
+ "nl": "Links moeten een unieke context hebben",
+ "pt-br": "Links devem ter um contexto único"
+ },
+ "description": {
+ "de": "",
+ "en": "",
+ "nl": "",
+ "pt-br": ""
+ },
+ "guidelines": [],
+ "tags": [
+ "link",
+ "content"
+ ],
+ "callback": "linkHasAUniqueContext"
+ },
+ "linkUsedForAlternateContent": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Verwende ein \"link\"-Element für alternative Inhalte",
+ "en": "Use a \"link\" element for alternate content",
+ "nl": "Gebruik een \"link\"-element for andersoortige content",
+ "pt-br": "Usar um elemento \"link\" para conteúdo alternativo"
+ },
+ "description": {
+ "de": "Dokumente die Inhalte, wie bspw. Videos, Audios oder andere Medien enthalten, die nicht barrrierefrei sind, sollten ein link-Element mit einem \"rel\"-Attribut der Alternative im Header des Dokumentes enthalten.",
+ "en": "Documents which contain things like videos, sound, or other forms of media that are not accessible, should provide a link element with a \"rel\" attribute of \"alternate\" in the document header.",
+ "nl": "Documenten die content zoals video's, geluid of andere niet-toegankelijke vormen van media bevatten, moeten een link-element met een \"rel\"-attribuut of \"alternate\" in de documentheaderlink aanbieden.",
+ "pt-br": "Os documentos que contenham coisas como vídeos, som ou outras formas de mídia que não estejam acessíveis devem fornecer um elemento link com um atributo \"rel\" de \"alternate\" no cabeçalho do documento."
+ },
+ "guidelines": [],
+ "tags": [
+ "document"
+ ],
+ "options": {
+ "selector": "html:not(html:has(link[rel=alternate])) body"
+ }
+ },
+ "linkUsedToDescribeNavigation": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Das Dokument verwendet Verknüpfungen um die Navigation zu beschreiben, wenn es in einer Sammlung ist",
+ "en": "The document uses link elements to describe navigation if it is within a collection.",
+ "nl": "Het document gebruikt link-elementen om navigatie te beschrijven wanneer het binnen een collectie staat.",
+ "pt-br": "O documento usa elementos de link para descrever a navegação se ela estiver dentro de uma coleção."
+ },
+ "description": {
+ "de": "Das Verknüpfungs-Element kann Metadaten über die Position einer HTML-Seite in einem Set von Webseiten liefern.",
+ "en": "The link element can provide metadata about the position of an HTML page within a set of Web units or can assist in locating content with a set of Web units.",
+ "nl": "Het link-element kan metadata bevatten over de positie van een HTML-pagina binnen een swet web units, of kan behulpzaamn zijn bij het lokaliseren van content binnen web units.",
+ "pt-br": "O elemento link pode fornecer metadados sobre a posição de uma página HTML dentro de um conjunto de unidades da Web ou pode ajudar a localizar conteúdo com um conjunto de unidades da Web."
+ },
+ "guidelines": [],
+ "tags": [
+ "document"
+ ],
+ "options": {
+ "selector": "html:not(html:has(link[rel=index]))"
+ }
+ },
+ "listNotUsedForFormatting": {
+ "type": "custom",
+ "testability": 0,
+ "title": {
+ "de": "Listen sollten nicht für die Formatierung genutzt werden",
+ "en": "Lists should not be used for formatting",
+ "nl": "Lijsten worden niet gebruikt voor opmaak",
+ "pt-br": "As listas não devem ser usadas para formatação"
+ },
+ "description": {
+ "de": "Listen, wie bspw. ul und ol dienen der Strukturierung von Listen und sollten nicht zur Formatierung von Text genutzt werden. Diese Test prüft Listen mit nur einem Eintrag, sollte aber manuell überprüft werden. ",
+ "en": "Lists like ul and ol are to provide a structured list, and should not be used to format text. This test views any list with just one item as suspicious, but should be manually reviewed.",
+ "nl": "Lijsten zoals ul en ol zijn bedoeld om gestructureerde lijsten te maken. Ze moeten niet gebruikt worden om text op te maken. Controleer of deze lijst echt bedoeld is als lijst of om tekst op te maken.",
+ "pt-br": "Listas como ul e ol são para fornecer uma lista estruturada e não devem ser usadas para formatar texto. Este teste exibe qualquer lista com apenas um item como suspeito, mas deve ser revisado manualmente."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.2": {
+ "techniques": [
+ "F1"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "list",
+ "content"
+ ],
+ "callback": "listNotUsedForFormatting"
+ },
+ "listOfLinksUseList": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Eine Liste von Verknüpfung sollte in einer geordneten oder ungeordneten Liste sein",
+ "en": "A list of links separated by non-readable characters should be in an ul or ol",
+ "nl": "Een lijst van links die worden gescheiden door onleesbare tekens moeten in een bulleted of genummerde lijst staan",
+ "pt-br": "Uma lista de links separados por caracteres não legíveis deve estar em um ul ou ol"
+ },
+ "description": {
+ "de": "Eine Liste von Verknüpfungen ohne Trennung zwischen den Verknüpfungen sollte in einem ul-Element oder ol-Element enthalten sein",
+ "en": "A list of links without separation between them should be placed in an ol or ul element.",
+ "nl": "Een lijst van links die niet duidelijk gescheiden zijn moeten in een bulleted of genummerde lijst staan.",
+ "pt-br": "Uma lista de links sem separação entre eles deve ser colocada em um elemento ol ou ul."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "H48"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "link",
+ "content"
+ ],
+ "callback": "listOfLinksUseList"
+ },
+ "marqueeIsNotUsed": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Der \"marquee\"-Tag sollte nicht verwendet werden",
+ "en": "The \"marquee\" tag should not be used",
+ "nl": "De \"marquee\"-tag wordt niet gebruikt",
+ "pt-br": "A tag \"marquee\" não deve ser usada"
+ },
+ "description": {
+ "de": "Das marquee-Element ist für Benutzer schwierig zu lesen und kein HTML-Standardelement. Nutzen Sie ein anderes Element zur Hervorhebung der Bedeutung eines Textes.",
+ "en": "The marquee element is difficult for users to read and is not a standard HTML element. Try to find another way to convey the importance of this text.",
+ "nl": "Het marquee-element is moeilijk te lezen voor gebruikers en is geen standaard HTML-element. Gebruik een andere manier om aan te duiden dat het belangrijke content is.",
+ "pt-br": "O elemento marquee é difícil de ler e não é um elemento HTML padrão. Tente encontrar outra maneira de transmitir a importância deste texto."
+ },
+ "guidelines": [],
+ "tags": [
+ "deprecated",
+ "content"
+ ],
+ "options": {
+ "selector": "marquee"
+ }
+ },
+ "menuNotUsedToFormatText": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "\"menu\"-Elemente sollten nicht für Formatierung genutzt werden",
+ "en": "Menu elements should not be used for formatting",
+ "nl": "Menu-elementen worden niet gebruikt voor opmaak",
+ "pt-br": "Os elementos de menu não devem ser usados para formatação"
+ },
+ "description": {
+ "de": "Der \"menu\"-Tag ist veraltet, aber wird im Doctype HTML Transitional noch immer berücksichtigt. \"menu\"-Tags dienen der Strukturierung von Dokumenten und sollten nicht für Formatierungen genutzt werden. Der \"menu\"-Tag sollte dieser nur in Listen von Verknüpfungen verwendet werden",
+ "en": "Menu is a deprecated tag, but is still honored in a transitional DTD. Menu tags are to provide structure for a document and should not be used for formatting. If a menu tag is to be used, it should only contain an ordered or unordered list of links.",
+ "nl": "Menu is een afgekeurd tag, maar wordt nog wel gebruikt om structuur aan een document te geven. Het mag niet worden gebruikt voor opmaak. Als een menu-tag wordt gebruikt, mag het alleen bulleted of genummerde lijsten bevatten.",
+ "pt-br": "Menu é uma tag obsoleta, mas ainda é homenageada em um DTD transicional. As tags de menu devem fornecer estrutura para um documento e não devem ser usadas para formatação. Se uma tag de menu deve ser usada, ela deve conter apenas uma lista ordenada ou não ordenada de links."
+ },
+ "guidelines": [],
+ "tags": [
+ "list",
+ "content"
+ ],
+ "options": {
+ "selector": "menu:not(menu li:parent(menu))"
+ }
+ },
+ "newWindowIsOpened": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Eine Verknüpfung sollte nicht in einem neuen Fenster geöffnet werden",
+ "en": "A link should not open a new window",
+ "nl": "Een link opent geen nieuw scherm",
+ "pt-br": "Um link não deve abrir uma nova janela"
+ },
+ "description": {
+ "de": "Vermeiden Sie Verwirrung durch neu öffnende Fenster, die nicht vom Benutzer angefordert wurden.",
+ "en": "Avoid confusion that may be caused by the appearance of new windows that were not requested by the user.",
+ "nl": "Voorkom verwarring die veroorzaakt wordt door het openen van nieuwe schermen die de gebruiker niet verwacht.",
+ "pt-br": "Evite confusão que pode ser causada pela aparição de novas janelas que não foram solicitadas pelo usuário."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.0.0": {
+ "techniques": [
+ "H83"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "javascript",
+ "html"
+ ],
+ "callback": "newWindowIsOpened"
+ },
+ "noembedHasEquivalentContent": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "\"Noembed\"-Elemente müssen denselben Inhalt beschreiben, wie das \"embed\"-Element",
+ "en": "Noembed elements must be the same content as their \"embed\" element",
+ "nl": "Noembed-elementen moeten dezelfde content hebben als hun \"embed\"-element",
+ "pt-br": "Elementos Noembed devem ter o mesmo conteúdo que o elemento \"embed \""
+ },
+ "description": {
+ "de": "Alle noembed-Elemente müssen eine barrierefreie Version des Inhalts des embed-Elements enthalten oder darauf verweisen",
+ "en": "All noembed elements must contain or link to an accessible version of their embed counterparts.",
+ "nl": "Alle noembed-elementen moeten een toegankelijke versie van hun embed-tegenhangers bevatten of hier naar linken.",
+ "pt-br": "Todos os elementos noembed devem conter ou vincular a uma versão acessível de suas contrapartes embed ."
+ },
+ "guidelines": [],
+ "tags": [
+ "objects",
+ "content"
+ ],
+ "options": {
+ "selector": "noembed"
+ }
+ },
+ "noframesSectionMustHaveTextEquivalent": {
+ "type": "selector",
+ "testability": 0.5,
+ "title": {
+ "de": "Alle \"noframes\"-Elemente sollten den Inhalt aller Frames enthalten",
+ "en": "All \"noframes\" elements should contain the text content from all frames",
+ "nl": "Alle \"noframes\"-elementen moeten de content van alle frames bevatten",
+ "pt-br": "Todos os elementos \"noframes\" devem conter o conteúdo de texto de todos os quadros"
+ },
+ "description": {
+ "de": "Der Inhalte in noframes sollte den sichtbaren Inhalt der Frames wiedergeben oder darauf verweisen",
+ "en": "The noframes content should either replicate or link to the content visible within the frames.",
+ "nl": "The noframes-content moet de zichtbare content binnen de frames repliceren of er naar linken.",
+ "pt-br": "O conteúdo noframes deve replicar ou vincular ao conteúdo visível dentro dos quadros."
+ },
+ "guidelines": [],
+ "tags": [
+ "deprecated",
+ "frame"
+ ],
+ "options": {
+ "selector": "frameset:not(frameset:has(noframes))"
+ }
+ },
+ "objectContentUsableWhenDisabled": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Wenn Objekte deaktiviert sind, sollte der Inhalt dennoch angezeigt werden",
+ "en": "When objects are disabled, content should still be available",
+ "nl": "Als objecten zijn uitgeschakeld, moet de content nog wel beschikbaar zijn",
+ "pt-br": "Quando os objetos estão desativados, o conteúdo ainda deve estar disponível"
+ },
+ "description": {
+ "de": "Der Inhalt in Objekten sollte dennoch angezeigt werden, auch wenn das Objekt deaktiviert ist. Dazu setzen Sie eine Verknüpfung zur \"source\" des Objekts im object-Tag.",
+ "en": "The content within objects should still be available, even if the object is disabled. To do this, place a link to the direct object source within the object tag.",
+ "nl": "Content binnen objecten moet beschikbaar blijven, ook als het object is uitgeschakeld. Plaats hiervoor een link naar de bron van het object binnen de object-tag.",
+ "pt-br": "O conteúdo dentro de objetos ainda deve estar disponível, mesmo se o objeto estiver desativado. Para fazer isso, coloque um link para a fonte de objeto direto dentro da tag object ."
+ },
+ "guidelines": [],
+ "tags": [
+ "objects",
+ "content"
+ ],
+ "options": {
+ "selector": "object"
+ }
+ },
+ "objectDoesNotFlicker": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Objekte dürfen nicht flackern",
+ "en": "Objects do not flicker",
+ "nl": "Objecten knipperen of flitsen niet",
+ "pt-br": "Objetos não piscam"
+ },
+ "description": {
+ "de": "Der Inhalt in einem object-Tag darf nicht flackern",
+ "en": "The content within an object tag must not flicker.",
+ "nl": "De content binnen een object-tag knippert of flitst niet.",
+ "pt-br": "O conteúdo dentro de uma tag object code> não deve piscar."
+ },
+ "guidelines": {
+ "508": [
+ "j"
+ ],
+ "wcag": {
+ "2.2.2": {
+ "techniques": [
+ "F7"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "objects",
+ "content"
+ ],
+ "options": {
+ "selector": "object"
+ }
+ },
+ "objectDoesNotUseColorAlone": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Objekte sollten nicht nur Farben verwenden, um Inhalte zu kommunizieren",
+ "en": "Objects must not use color to communicate alone",
+ "nl": "Objecten gebruiken meer dan alleen kleur om hun boodschap over te brengen",
+ "pt-br": "Os objetos não devem usar cor para se comunicar sozinhos"
+ },
+ "description": {
+ "de": "Objekte sollten Inhalte so darstellen, das sie ohne Farben verständlich und für farbenblinde Benutzer zugänglich sind.",
+ "en": "Objects should contain content that makes sense without color and is accessible to users who are color blind.",
+ "nl": "Objecten moeten content bevatten die duidelijk is zonder het kleurgebruik en toegankelijk is voor gebruikers met kleurenblindheid.",
+ "pt-br": "Objetos devem conter conteúdo que faz sentido sem cor e é acessível para usuários que são daltônicos."
+ },
+ "guidelines": {
+ "508": [
+ "c"
+ ]
+ },
+ "tags": [
+ "objects",
+ "content"
+ ],
+ "options": {
+ "selector": "object"
+ }
+ },
+ "objectInterfaceIsAccessible": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Jede Benutzerschnittstelle in einem Objekt muss barrierefrei sein",
+ "en": "Interfaces within objects must be accessible",
+ "nl": "Interfaces binnen objecten moeten toegankelijk zijn",
+ "pt-br": "Interfaces dentro de objetos devem ser acessíveis"
+ },
+ "description": {
+ "de": "Inhalte in Objekten sollten auf Barrierefreiheit geprüft werden.",
+ "en": "Object content should be assessed for accessibility.",
+ "nl": "Content binnen objecten moeten gecontroleerd worden op toegankelijkheid.",
+ "pt-br": "O conteúdo do objeto deve ser avaliado quanto à acessibilidade."
+ },
+ "guidelines": [],
+ "tags": [
+ "objects",
+ "content"
+ ],
+ "options": {
+ "selector": "object"
+ }
+ },
+ "objectLinkToMultimediaHasTextTranscript": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Objekte, die auf eine Multimedia-Datei verweisen, sollten auch eine Verknüpfung zu einem Transkript enthalten",
+ "en": "Objects which reference multimedia files should also provide a link to a transcript",
+ "nl": "Objecten die verwijzen naar multimediabestanden moeten ook een link aanbieden naar de transcriptie",
+ "pt-br": "Os objetos que fazem referência a arquivos multimídia também devem fornecer um link para uma transcrição"
+ },
+ "description": {
+ "de": "Auf eine Verknüpfung zu einer Multimedia-Datei in einem Objekt sollte eine Verknüpfung zu einem Transkript folgen.",
+ "en": "If an object contains a video, a link to the transcript should be provided near the object.",
+ "nl": "Als een object een video bevat, moet een link naar de transcriptie hiervan worden aangeboden bij het object.",
+ "pt-br": "Se um objeto contiver um vídeo, um link para o transcrito deve ser fornecido perto do objeto."
+ },
+ "guidelines": [],
+ "tags": [
+ "objects",
+ "content"
+ ],
+ "options": {
+ "selector": "object"
+ }
+ },
+ "objectMustContainText": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Alle Objekte sollten den Inhalt im Element des Objekts selbst enthalten",
+ "en": "Objects must contain their text equivalents",
+ "nl": "Objecten moeten hun tekstuele equivalent bevatten",
+ "pt-br": "Os objetos devem conter seus equivalentes de texto"
+ },
+ "description": {
+ "de": "Objekte sollten ihre Text-Äquivalente oder eine Beschreibung innerhalb des object code>-Tag selbst enthalten.",
+ "en": "All object elements should contain a text equivalent if the object cannot be rendered.",
+ "nl": "Alle object-elementen moeten een tekstequivalent bevatten in het geval het object niet getoond kan worden.",
+ "pt-br": "Todos os elementos object devem conter um equivalente de texto se o objeto não puder ser renderizado."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "FLASH1",
+ "H27"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "objects",
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "content": true,
+ "empty": true,
+ "selector": "object"
+ }
+ },
+ "objectMustHaveEmbed": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Jedes Objekt sollte ein \"embed\"-Element enthalten",
+ "en": "Every object should contain an \"embed\" element",
+ "nl": "Elk object moet een \"embed\"-element bevatten",
+ "pt-br": "Todo objeto deve conter um elemento \"embed\""
+ },
+ "description": {
+ "de": "Jedes object-Element muss auch ein embed-Element beinhalten",
+ "en": "Every object element must also contain an embed element.",
+ "nl": "Elk object-element moet ook een \"embed\"-element bevatten.",
+ "pt-br": "Todo elemento object code> também deve conter um elemento embed ."
+ },
+ "guidelines": [],
+ "tags": [
+ "objects",
+ "content"
+ ],
+ "options": {
+ "selector": "object:not(object:has(embed))"
+ }
+ },
+ "objectMustHaveTitle": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Objekte sollten ein \"title\"-Attribut haben",
+ "en": "Objects should have a title attribute",
+ "nl": "Objecten moeten een titelattribuut hebben",
+ "pt-br": "Objetos devem ter um atributo de título"
+ },
+ "description": {
+ "de": "Alle object-Elemente sollten ein \"title\"-Attribut haben",
+ "en": "All object elements should contain a \"title\" attribute.",
+ "nl": "Alle object-elementen moeten een \"titel\"-attribuut bevatten.",
+ "pt-br": "Todos os elementos object devem conter um atributo \"title \"."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H27"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "objects",
+ "content"
+ ],
+ "options": {
+ "selector": "object:not(object[title])"
+ }
+ },
+ "objectMustHaveValidTitle": {
+ "type": "placeholder",
+ "testability": 1,
+ "title": {
+ "de": "Objekte sollten kein leeres \"title\"-Attribut haben",
+ "en": "Objects must not have an empty title attribute",
+ "nl": "Objecten hebben geen leeg titelattribuut",
+ "pt-br": "Objetos não devem ter um atributo title vazio"
+ },
+ "description": {
+ "de": "Alle object-Elemente sollten ein \"title\"-Attribut haben, das nicht leer ist",
+ "en": "All object elements should have a \"title\" attribute which is not empty.",
+ "nl": "All object-elementen hebben een \"titel\"-attribuut dat gevuld is.",
+ "pt-br": "Todos os elementos object devem ter um atributo \"title\" que não esteja vazio."
+ },
+ "guidelines": [],
+ "tags": [
+ "objects",
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "attribute": "title",
+ "empty": true,
+ "selector": "object"
+ }
+ },
+ "objectProvidesMechanismToReturnToParent": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Alle Objekte sollten einen Weg für Tastatur-Benutzer bieten, um das Objekt zu verlassen.",
+ "en": "All objects should provide a way for keyboard users to escape",
+ "nl": "Alle objecten moeten een manier bevatten voor toetsenbordgebruikers een manier om het object te verlaten",
+ "pt-br": "Todos os objetos devem fornecer uma maneira de escape para os usuários de teclado"
+ },
+ "description": {
+ "de": "Stellen Sie sicher, dass ein Benutzer, der nur eine Tastatur als Eingabegerät besitzt, ein object code>-Element per Tastaturbefehl verlassen kann. Dies muss manuell getestet werden.",
+ "en": "Ensure that a user who has only a keyboard as an input device can escape a object element. This requires manual confirmation.",
+ "nl": "Zorg ervoor dat een gebruiker die alleen het toetsenbord als bediening gebruikt een object-element. Hiervoor is handmatige bevestiging nodig.",
+ "pt-br": "Certifique-se de que um usuário que tenha apenas um teclado como dispositivo de entrada pode escapar de um elemento object . Isso requer confirmação manual."
+ },
+ "guidelines": [],
+ "tags": [
+ "objects",
+ "content"
+ ],
+ "options": {
+ "selector": "object"
+ }
+ },
+ "objectShouldHaveLongDescription": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Ein Objekt erfordert möglicherweise eine Langbeschreibung",
+ "en": "An object might require a long description",
+ "nl": "Een object heeft soms een lange beschrijving nodig",
+ "pt-br": "Um objeto pode exigir uma descrição longa"
+ },
+ "description": {
+ "de": "Objekte erfordern möglicherweise eine Langbeschreibung, besonders wenn deren Inhalt kompliziert ist",
+ "en": "Objects might require a long description, especially if their content is complicated.",
+ "nl": "Objecten hebben soms een lange beschrijving nodig, zeker in het geval van ingewikkelde content.",
+ "pt-br": "Objetos podem exigir uma descrição longa, especialmente se o seu conteúdo é complicado."
+ },
+ "guidelines": [],
+ "tags": [
+ "objects",
+ "content"
+ ],
+ "options": {
+ "selector": "object"
+ }
+ },
+ "objectTextUpdatesWhenObjectChanges": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Die Textbeschreibung eines Objekts sollte aktualisiert werden, wenn das Objekt sich ändert",
+ "en": "The text equivalents of an object should update if the object changes",
+ "nl": "De tekstuele equivalent van een object moet bijgewerkt worden als het object verandert",
+ "pt-br": "Os equivalentes de texto de um objeto devem ser atualizados se o objeto for modificado"
+ },
+ "description": {
+ "de": "Wenn ein Objekt sich ändert, sollte die Textbeschreibung des Objektes sich ebenfalls ändern",
+ "en": "If an object changes, the text equivalent of that object should also change.",
+ "nl": "Als een object verandert, moet zijn tekstuele equivalent ook veranderen.",
+ "pt-br": "Se um objeto for alterado, o texto equivalente desse objeto também deve ser alterado."
+ },
+ "guidelines": {
+ "508": [
+ "a"
+ ]
+ },
+ "tags": [
+ "objects",
+ "content"
+ ],
+ "options": {
+ "selector": "object"
+ }
+ },
+ "objectUIMustBeAccessible": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Inhalt in einem \"object\"-Element sollte nutzbar sein, wenn das Objekt deaktiviert ist",
+ "en": "Content within an \"object\" element should be usable with objects disabled",
+ "nl": "Content binnen een \"object\"-element moet bruikbaar blijven als het object uitgeschakeld is",
+ "pt-br": "O conteúdo dentro de um elemento \"objeto\" deve ser utilizável com objetos desativados"
+ },
+ "description": {
+ "de": "Objekte, deren Inhalte mit Hilfe von Java, ActiveX oder ähnlichen Technologien aktualisiert werden, sollten den Standardtext aktualisieren, wenn ihr Inhalt geändert wird",
+ "en": "Objects who's content changes using java, ActiveX, or other similar technologies, should have their default text change when the object's content changes.",
+ "nl": "Van objecten waarvan de content java, ActiveX of vergelijkbare technologie�n gebruiken, moet de standaardtekst veranderen als de content van het object verandert.",
+ "pt-br": "Os objetos com alterações de conteúdo usando java, ActiveX ou outras tecnologias similares devem ter seu texto padrão alterado quando o conteúdo do objeto for alterado."
+ },
+ "guidelines": [],
+ "tags": [
+ "objects",
+ "content"
+ ],
+ "options": {
+ "selector": "object"
+ }
+ },
+ "objectWithClassIDHasNoText": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Objekte mit \"classid\"-Attribut sollten nicht ihren Text ändern, wenn sich der Inhalt des Objektes ändert",
+ "en": "Objects with \"classid\" attributes should change their text if the content of the object changes",
+ "nl": "Objecten met \"classid\"-attributen moeten hun tekst veranderen wanneer de content van het object verandert",
+ "pt-br": "Os objetos com \"classid\" atributos devem alterar seu texto se o conteúdo do objeto for alterado"
+ },
+ "description": {
+ "de": "Objekte mit \"classid\"-Attribut sollten nicht ihren Standardtext ändern, wenn sich der Inhalt des Objektes ändert.",
+ "en": "Objects with \"classid\" attributes, should have their default text change when the object's content changes.",
+ "nl": "Van objecten met \"classid\"-attributen moet de standaardtekst veranderen als de content van het object verandert.",
+ "pt-br": "Os objetos com atributos \"classid\" devem ter seu texto padrão alterado quando o conteúdo do objeto for alterado."
+ },
+ "guidelines": [],
+ "tags": [
+ "objects",
+ "content"
+ ],
+ "options": {
+ "selector": "object[classid]:not(object[classid]:empty)"
+ }
+ },
+ "pNotUsedAsHeader": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Paragraphen dürfen nicht für Überschriften verwendet werden",
+ "en": "Paragraphs must not be used for headers",
+ "nl": "Alinea's worden niet gebruikt als header",
+ "pt-br": "Os parágrafos não devem ser usados para cabeçalhos"
+ },
+ "description": {
+ "de": "Überschriften sind für nicht-sehende Benutzer sehr nützlich um in der Seitenstruktur zu navigieren. Einen Paragraphen nur groß oder fett zu formatieren, damit es wie eine Überschrift aussieht, macht daraus keine Überschrift.",
+ "en": "Headers are extremely useful for non-sighted users to navigate the structure of the page. Formatting a paragraph to just be big or bold, while it might visually look like a header, does not make it a header.",
+ "nl": "Headers van h1 - h6 zijn handig voor blinde en slechtziende gebruikers om door een pagina te navigeren. Maak alinea's daarom niet op zodat deze lijkt op een header. Dit werkt verwarrend.",
+ "pt-br": "Cabeçalhos são extremamente úteis para usuários sem visão para navegar na estrutura da página. Formatando um parágrafo para ser apenas grande ou negrito, enquanto ele pode visualmente se parecer com um cabeçalho, não torná-lo um cabeçalho."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "G141",
+ "H42"
+ ]
+ },
+ "2.4.10": {
+ "techniques": [
+ "G141"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "header",
+ "content"
+ ],
+ "callback": "pNotUsedAsHeader"
+ },
+ "paragraphIsWrittenClearly": {
+ "type": "custom",
+ "testability": 0.5,
+ "guidelines": {
+ "wcag": {
+ "3.1.5": {
+ "techniques": [
+ "G86"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "language",
+ "content"
+ ],
+ "components": [
+ "textStatistics"
+ ],
+ "callback": "paragraphIsWrittenClearly"
+ },
+ "passwordHasLabel": {
+ "type": "label",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"password\"-Eingabeelemente sollten ein dazugehöriges Label haben",
+ "en": "All password input elements should have a corresponding label",
+ "nl": "Alle paswoordinvoerelementen hebben een bijbehorend label",
+ "pt-br": "Todos os elementos de entrada de senha devem ter um rótulo correspondente"
+ },
+ "description": {
+ "de": "Alle input-Elemente vom Typ \"password\" sollten ein dazugehöriges label-Element haben. Bildschirmleseprogramme haben oftmals eine Formular-Modus, in dem nur Labels vorgelesen werden.",
+ "en": "All input elements with a type of \"password\"should have a corresponding label element. Screen readers often enter a \"form mode\" where only label text is read aloud to the user",
+ "nl": "Alle input-elementen van het type \"paswoord\" moeten een bijbehorend label-element hebben. Schermlezers maken vaak gebruik van een \"formuliereninstelling\" waarbij alleen de tekst van de labels hardop aan de gebruiker wordt voorgelezen.",
+ "pt-br": "Todos os elementos input com um tipo de \"senha\" devem ter um elemento label correspondente. Os leitores de tela costumam entrar em um \"modo de formulário\" onde somente o texto da etiqueta é lido em voz alta para o usuário"
+ },
+ "guidelines": {
+ "508": [
+ "n"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H44"
+ ]
+ },
+ "1.3.1": {
+ "techniques": [
+ "H44",
+ "F68"
+ ]
+ },
+ "2.1.1": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "3.3.2": {
+ "techniques": [
+ "H44"
+ ]
+ },
+ "4.1.2": {
+ "techniques": [
+ "H44",
+ "H91"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "label"
+ ],
+ "options": {
+ "selector": "input[type=password]"
+ }
+ },
+ "passwordLabelIsNearby": {
+ "type": "labelProximity",
+ "testability": 0.5,
+ "title": {
+ "de": "Alle \"password\"-Eingabeelemente sollten ein dazugehöriges Label haben",
+ "en": "All \"password\" input elements have a label that is close",
+ "nl": "Alle paswoordinvoerelementen hebben een label dat dicht bij het element staat",
+ "pt-br": "Todos os elementos de entrada de \"senha\" têm um rótulo que está próximo"
+ },
+ "description": {
+ "de": "Alle Eingabeelemente vom Typ \"password\" müssen ein dazugehöriges Label haben das in der Nähe des Eingabeelements positioniert ist. Nutzer von Bildschirmvergrößerung oder mit reduzierten räumlichen Fähigkeiten werden bei der Verwendung eines Formularelements behindert, wenn das Label für das Element weit entfernt positioniert ist.",
+ "en": "All input elements of type \"password\" must have a corresponding label that is close to the form element. Users of screen magnification or with reduced spatial skills are hampered in using a form element if the label for that element is located far away.",
+ "nl": "Alle inputelementen van het type \"paswoord\" moeten een bijbehorend label hebben dat dicht bij het formulierelement staat. Gebruikers die het scherm vergroten of met beperkte ruimtelijke vaardigheden kunnen een formulier niet gebruiken als het label van een veld te ver weg staat.",
+ "pt-br": "Todos os elementos de entrada do tipo \"senha\" devem ter um rótulo correspondente que esteja próximo ao elemento do formulário. Usuários de ampliação de tela ou com habilidades espaciais reduzidas são impedidos de usar um elemento de formulário se o rótulo para esse elemento estiver localizado longe."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "labelProximity"
+ ],
+ "options": {
+ "selector": "input[type=password]"
+ }
+ },
+ "preShouldNotBeUsedForTabularLayout": {
+ "type": "custom",
+ "testability": 0,
+ "title": {
+ "de": "Pre-Elemente sollten nicht für Tabellendaten verwendet werden",
+ "en": "Pre elements should not be used for tabular data",
+ "nl": "Pre-elementen worden niet gebruikt om data als tabel te rangschikken",
+ "pt-br": "Pré-elementos não devem ser usados para dados tabulares"
+ },
+ "description": {
+ "de": "Wenn ein pre-Element für Tabellendaten verwendet wird, ändern Sie die Daten sodass eine wohlgeformte Tabelle verwendet wird.",
+ "en": "If a pre element is used for tabular data, change the data to use a well-formed table.",
+ "nl": "Als een pre-element wordt gebruikt om data als tabel te rangschikken, verander de data dan zodat je een echte tabel kunt maken.",
+ "pt-br": "Se um elemento pre for usado para dados tabulares, altere os dados para usar uma tabela bem formada."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "F33",
+ "F34",
+ "F48"
+ ]
+ },
+ "1.3.2": {
+ "techniques": [
+ "F33",
+ "F34"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "table",
+ "content"
+ ],
+ "callback": "preShouldNotBeUsedForTabularLayout"
+ },
+ "radioHasLabel": {
+ "type": "label",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"Radio\"-Eingabeelemente müssen ein dazugehöriges Label haben",
+ "en": "All \"radio\" input elements have a corresponding label",
+ "nl": "Alle invoerelementen van het type \"radio\" hebben een bijbehorend label",
+ "pt-br": "Todos os elementos de entrada \"radio\" têm uma etiqueta correspondente"
+ },
+ "description": {
+ "de": "Alle Input-Elemente vom Typ \"radio\" sollten ein dazugehöriges label-Element haben. Bildschirmleseprogramme verwenden oft einen Formularmodus, wenn nur Label-Text vorgelesen wird.",
+ "en": "All input elements of type \"radio\" should have a corresponding label element. Screen readers often enter a \"form mode\" where only label text is read aloud to the user",
+ "nl": "Alle input-elementen van het \"radio\" moeten een bijbehorend label-element hebben. Schermlezers maken vaak gebruik van een \"formuliereninstelling\" waarbij alleen de tekst van de labels hardop aan de gebruiker wordt voorgelezen.",
+ "pt-br": "Todos os elementos input code> do tipo \"radio\" devem ter um elemento label code> correspondente. Os leitores de tela costumam entrar em um \"modo de formulário\" onde somente o texto do rótulo é lido em voz alta para o usuário"
+ },
+ "guidelines": {
+ "508": [
+ "n"
+ ],
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H44"
+ ]
+ },
+ "1.3.1": {
+ "techniques": [
+ "H44",
+ "F68"
+ ]
+ },
+ "2.1.1": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "3.3.2": {
+ "techniques": [
+ "H44"
+ ]
+ },
+ "4.1.2": {
+ "techniques": [
+ "H44",
+ "H91"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "label"
+ ],
+ "options": {
+ "selector": "input[type=radio]"
+ }
+ },
+ "radioLabelIsNearby": {
+ "type": "labelProximity",
+ "testability": 0.5,
+ "title": {
+ "de": "Alle \"radio\"-Elemente sollten ein dazugehöriges Label haben",
+ "en": "All \"radio\" input elements have a label that is close",
+ "nl": "Alle invoerelementen van het type \"radio\" hebben een label dat dicht bij het element staat",
+ "pt-br": "Todos os elementos de entrada \"radio\" têm um rótulo que está próximo"
+ },
+ "description": {
+ "de": "Alle Eingabeelemente vom Typ \"radio\" müssen ein dazugehöriges Label haben das in der Nähe des Eingabeelements positioniert ist. Nutzer von Bildschirmvergrößerung oder mit reduzierten räumlichen Fähigkeiten werden bei der Verwendung eines Formularelements behindert, wenn das Label für das Element weit entfernt positioniert ist.",
+ "en": "All input elements of type \"radio\" must have a corresponding label that is close to the form element. Users of screen magnification or with reduced spatial skills are hampered in using a form element if the label for that element is located far away.",
+ "nl": "Alle inputelementen van het type \"radio\" moeten een bijbehorend label hebben dat dicht bij het formulierelement staat. Gebruikers die het scherm vergroten of met beperkte ruimtelijke vaardigheden kunnen een formulier niet gebruiken als het label van een veld te ver weg staat.",
+ "pt-br": "Todos os elementos de entrada do tipo \"radio\" devem ter um rótulo correspondente que esteja próximo ao elemento do formulário. Usuários de ampliação de tela ou com habilidades espaciais reduzidas são impedidos de usar um elemento de formulário se o rótulo para esse elemento estiver localizado longe."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "labelProximity"
+ ],
+ "options": {
+ "selector": "input[type=radio]"
+ }
+ },
+ "radioMarkedWithFieldgroupAndLegend": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Alle Gruppen von Radio-Buttons sind mit Fieldsets und Legend-Elementen gekennzeichnet",
+ "en": "All radio button groups are marked using fieldset and legend elementsTodos os grupos de botões de rádio são marcados usando os elementos fieldset e legenda",
+ "nl": "Alle groepjes van radio buttons zijn gemarkeerd met fieldset- en legend-elementen",
+ "pt-br": "Todos os grupos de botões de radio são marcados usando os elementos fieldset e legenda"
+ },
+ "description": {
+ "de": "Formular-Elemente müssen sowohl ein Fieldset als auch Legend-Elemente beinhalten, wenn Radio-Buttons verwendet werden",
+ "en": "Form element content must contain both fieldset and legend elements if there are related radio buttons.",
+ "nl": "Content van formulierelementen moeten zowel fieldset- als legend-elementen bevatten als er gerelateerde radio buttons instaan.",
+ "pt-br": "O conteúdo do elemento de formulário deve conter elementos de campo e legenda se houver botões radio relacionados."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "H71"
+ ]
+ },
+ "3.3.2": {
+ "techniques": [
+ "H71"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "options": {
+ "selector": "input[type=radio]:not(fieldset input[type=radio])"
+ }
+ },
+ "scriptContentAccessibleWithScriptsTurnedOff": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Der Inhalt einer Seite sollte auch bei deaktivierten Scripten verfügbar sein",
+ "en": "Content on the page should still be available if scripts are disabled",
+ "nl": "Content op de pagina moet beschikbaar blijven als scripts zijn uitgeschakeld",
+ "pt-br": "O conteúdo da página ainda deve estar disponível se os scripts estiverem desativados"
+ },
+ "description": {
+ "de": "Es sollte geprüft werden, ob der Seiteninhalt immer noch verfügbar ist, wenn Skripte im Browser deaktiviert wurden",
+ "en": "All scripts should be assessed to see if, when the user is browsing with scrips turned off, the page content is still available.",
+ "nl": "Alle scripts moeten gecontroleerd worden of, wanneer een gebruiker scripts heeft uitgezet, de content van de pagina nog steeds beschikbaar is.",
+ "pt-br": "Todos os scripts devem ser avaliados para ver se, quando o usuário está navegando com scripts desligados, o conteúdo da página ainda está disponível."
+ },
+ "guidelines": [],
+ "tags": [
+ "javascript"
+ ],
+ "options": {
+ "selector": "script"
+ }
+ },
+ "scriptInBodyMustHaveNoscript": {
+ "type": "selector",
+ "testability": 0.5,
+ "title": {
+ "de": "Skripte sollten ein dazugehöriges \"noscript\"-Element haben",
+ "en": "Scripts should have a corresponding \"noscript\" element",
+ "nl": "Scripts moeten een bijbehorend \"noscript\"-element hebben",
+ "pt-br": "Os scripts devem ter um elemento \"noscript\" correspondente"
+ },
+ "description": {
+ "de": "Skripte sollten von einem noscript-Element gefolgt werden, um dem Benutzer einen alternativen Zugang zum Inhalt zu bieten",
+ "en": "Scripts should be followed by a noscripts element to guide the user to content in an alternative way.",
+ "nl": "Scripts moeten worden gevolgd door een noscripts-element om de gebruiker de weg te wijzen naar de content op een andere manier.",
+ "pt-br": "Os scripts devem ser seguidos por um elemento noscripts para orientar o usuário para o conteúdo de uma maneira alternativa."
+ },
+ "guidelines": {
+ "508": [
+ "l"
+ ]
+ },
+ "tags": [
+ "javascript"
+ ],
+ "options": {
+ "selector": "html:not(html:has(noscript)):has(script) body"
+ }
+ },
+ "scriptOnclickRequiresOnKeypress": {
+ "type": "event",
+ "testability": 1,
+ "title": {
+ "de": "Wenn ein Element ein \"onclick\"-Attribut hat sollte es auch ein \"onkeypress\"-Attribut haben",
+ "en": "If an element has an \"onclick\" attribute it should also have an \"onkeypress\" attribute",
+ "nl": "Als een element een \"onclick\"-attribuut heeft, moet het ook een \"onkeypress\"-attribuut hebben",
+ "pt-br": "Se um elemento tem um atributo \"onclick\", ele também deve ter um atributo \"onkeypress\""
+ },
+ "description": {
+ "de": "Wenn ein Element ein \"onclick\"-Attribut hat sollte es auch ein \"onkeypress\"-Attribut haben",
+ "en": "If an element has an \"onclick\" attribute it should also have an \"onkeypress\" attribute",
+ "nl": "Als een element een \"onclick\"-attribuut heeft, moet het ook een \"onkeypress\"-attribuut hebben",
+ "pt-br": "Se um elemento tem um atributo \"onclick\", ele também deve ter um atributo \"onkeypress\""
+ },
+ "guidelines": {
+ "508": [
+ "l"
+ ],
+ "wcag": {
+ "2.1.1": {
+ "techniques": [
+ "G90",
+ "SCR2",
+ "SCR20"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "G90",
+ "SCR20"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "javascript"
+ ],
+ "components": [
+ "event",
+ "hasEventListener"
+ ],
+ "options": {
+ "correspondingEvent": "onkeypress",
+ "searchEvent": "onclick"
+ }
+ },
+ "scriptOndblclickRequiresOnKeypress": {
+ "type": "event",
+ "testability": 1,
+ "title": {
+ "de": "Jedes Element mit einem \"ondblclick\"-Attribut sollte auch eine Tastatur-Aktion haben",
+ "en": "Any element with an \"ondblclick\" attribute should have a keyboard-related action as well",
+ "nl": "Elk element met een \"ondblclick\"-attribuut moet een vergelijkbare actie hebben die kan worden uitgevoerd met een toetsenbord",
+ "pt-br": "Qualquer elemento com um atributo \"ondblclick\" também deve ter uma ação relacionada ao teclado"
+ },
+ "description": {
+ "de": "Wenn ein Element ein \"ondblclick\"-Attribut hat, sollte es auch eine Tastatur-Aktion haben",
+ "en": "If an element has an \"ondblclick\" attribute, it should also have a keyboard-related action.",
+ "nl": "Als een element een \"ondblclick\"-attribuut heeft, moet het ook een actie bevatten die kan worden uitgevoerd met een toetsenbord.",
+ "pt-br": "Se um elemento tem um atributo \"ondblclick\", ele também deve ter uma ação relacionada ao teclado."
+ },
+ "guidelines": {
+ "508": [
+ "l"
+ ],
+ "wcag": {
+ "2.1.1": {
+ "techniques": [
+ "G90",
+ "SCR2",
+ "SCR20"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "G90",
+ "SCR20"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "javascript"
+ ],
+ "components": [
+ "event",
+ "hasEventListener"
+ ],
+ "options": {
+ "correspondingEvent": "onkeypress",
+ "searchEvent": "ondblclick"
+ }
+ },
+ "scriptOnmousedownRequiresOnKeypress": {
+ "type": "event",
+ "testability": 1,
+ "title": {
+ "de": "Wenn ein Element ein \"mousedown\"-Attribut hat sollte es auch ein \"onkeydown\"-Attribut haben",
+ "en": "If an element has a \"mousedown\" attribute it should also have an \"onkeydown\" attribute",
+ "nl": "Als een element een \"mousedown\"-attribuut heeft moet het ook een \"onkeydown\"-attribuut hebben",
+ "pt-br": "Se um elemento tem um atributo \"mousedown\" ele também deve ter um atributo \"onkeydown\""
+ },
+ "description": {
+ "de": "Wenn ein Element ein \"mousedown\"-Attribut hat sollte es auch ein \"onkeydown\"-Attribut haben",
+ "en": "If an element has a \"mousedown\" attribute it should also have an \"onkeydown\" attribute.",
+ "nl": "Als een element een \"mousedown\"-attribuut heeft moet het ook een \"onkeydown\"-attribuut hebben.",
+ "pt-br": "Se um elemento tem um atributo \"mousedown\" ele também deve ter um atributo \"onkeydown\""
+ },
+ "guidelines": {
+ "508": [
+ "l"
+ ],
+ "wcag": {
+ "2.1.1": {
+ "techniques": [
+ "G90",
+ "SCR2",
+ "SCR20"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "G90",
+ "SCR20"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "javascript"
+ ],
+ "components": [
+ "event",
+ "hasEventListener"
+ ],
+ "options": {
+ "correspondingEvent": "onkeydown",
+ "searchEvent": "onmousedown"
+ }
+ },
+ "scriptOnmousemove": {
+ "type": "event",
+ "testability": 1,
+ "title": {
+ "de": "Jedes Element mit einem \"onmousemove\"-Attribut sollte auch eine Tastatur-Aktion haben",
+ "en": "Any element with an \"onmousemove\" attribute should have a keyboard-related action as well",
+ "nl": "Elk element met een \"onmousemove\"-attribuut moet een vergelijkbare actie hebben die kan worden uitgevoerd met een toetsenbord",
+ "pt-br": "Qualquer elemento com um atributo \"onmousemove\" também deve ter uma ação relacionada ao teclado"
+ },
+ "description": {
+ "de": "Wenn ein Element ein \"onmousemove\"-Attribut hat, sollte es auch eine Tastatur-Aktion haben",
+ "en": "If an element has an \"onmousemove\" attribute it should have a keyboard-related action as well.",
+ "nl": "Als een element een \"onmousemove\"-attribuut heeft, moet het een vergelijkbare actie hebben die kan worden uitgevoerd met een toetsenbord.",
+ "pt-br": "Se um elemento tiver um atributo \"onmousemove\", ele também deverá ter uma ação relacionada ao teclado."
+ },
+ "guidelines": {
+ "508": [
+ "l"
+ ],
+ "wcag": {
+ "2.1.1": {
+ "techniques": [
+ "G90",
+ "SCR2",
+ "SCR20"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "G90",
+ "SCR20"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "javascript"
+ ],
+ "components": [
+ "event",
+ "hasEventListener"
+ ],
+ "options": {
+ "correspondingEvent": "onkeypress",
+ "searchEvent": "onmousemove"
+ }
+ },
+ "scriptOnmouseoutHasOnmouseblur": {
+ "type": "event",
+ "testability": 1,
+ "title": {
+ "de": "Wenn ein Element ein \"onmouseout\"-Attribut hat sollte es auch ein \"onblur\"-Attribut haben",
+ "en": "If an element has a \"onmouseout\" attribute it should also have an \"onblur\" attribute",
+ "nl": "Als een element een \"onmouseout\"-attribuut heeft, moet het ook een \"onblur\" attribuut hebben",
+ "pt-br": "Se um elemento tem um atributo \"onmouseout\", ele também deve ter um atributo \"onblur\""
+ },
+ "description": {
+ "de": "Wenn ein Element ein \"mousedown\"-Attribut hat sollte es auch ein \"onkeydown\"-Attribut haben",
+ "en": "If an element has a \"onmouseout\" attribute it should also have an \"onblur\" attribute.",
+ "nl": "Als een element een \"onmouseout\"-attribuut heeft, moet het ook een \"onblur\"-attribuut hebben.",
+ "pt-br": "Se um elemento tem um atributo \"onmouseout\", ele também deve ter um atributo \"onblur\""
+ },
+ "guidelines": {
+ "508": [
+ "l"
+ ],
+ "wcag": {
+ "2.1.1": {
+ "techniques": [
+ "G90",
+ "SCR2",
+ "SCR20"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "G90",
+ "SCR20"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "javascript"
+ ],
+ "components": [
+ "event",
+ "hasEventListener"
+ ],
+ "options": {
+ "correspondingEvent": "onblur",
+ "searchEvent": "onmouseout"
+ }
+ },
+ "scriptOnmouseoverHasOnfocus": {
+ "type": "event",
+ "testability": 1,
+ "title": {
+ "de": "Wenn ein Element ein \"onmouseover\"-Attribut hat sollte es auch ein \"onfocus\"-Attribut haben",
+ "en": "If an element has a \"onmouseover\" attribute it should also have an \"onfocus\" attribute",
+ "nl": "Als een element een \"onmouseover\"-attribuut heeft, moet het ook een \"onfocus\"-attribuut hebben",
+ "pt-br": "Se um elemento tem um atributo \"onmouseover\" ele também deve ter um atributo \"onfocus\""
+ },
+ "description": {
+ "de": "Wenn ein Element ein \"mousedown\"-Attribut hat sollte es auch ein \"onkeydown\"-Attribut haben",
+ "en": "If an element has a \"onmouseover\" attribute it should also have an \"onfocus\" attribute.",
+ "nl": "Als een element een \"onmouseover\"-attribuut heeft, moet het ook een \"onfocus\"-attribuut hebben.",
+ "pt-br": "Se um elemento tem um atributo \"onmouseover\" ele também deve ter um atributo \"onfocus\"."
+ },
+ "guidelines": {
+ "508": [
+ "l"
+ ],
+ "wcag": {
+ "2.1.1": {
+ "techniques": [
+ "G90",
+ "SCR2",
+ "SCR20"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "G90",
+ "SCR20"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "javascript"
+ ],
+ "components": [
+ "event",
+ "hasEventListener"
+ ],
+ "options": {
+ "correspondingEvent": "onfocus",
+ "searchEvent": "onmouseover"
+ }
+ },
+ "scriptOnmouseupHasOnkeyup": {
+ "type": "event",
+ "testability": 1,
+ "title": {
+ "de": "Wenn ein Element ein \"onmouseup\"-Attribut hat sollte es auch ein \"onkeyup\"-Attribut haben",
+ "en": "If an element has a \"onmouseup\" attribute it should also have an \"onkeyup\" attribute",
+ "nl": "Als een element een \"onmouseup\"-attribuut heeft, moet het ook een \"onkeyup\"-attribuut hebben",
+ "pt-br": "Se um elemento tem um atributo \"onmouseup\" ele também deve ter um atributo \"onkeyup\"."
+ },
+ "description": {
+ "de": "Wenn ein Element ein \"onmouseup\"-Attribut hat sollte es auch ein \"onkeyup\"-Attribut haben",
+ "en": "If an element has a \"onmouseup\" attribute it should also have an \"onkeyup\" attribute.",
+ "nl": "Als een element een \"onmouseup\"-attribuut heeft, moet het ook een \"onkeyup\"-attribuut hebben.",
+ "pt-br": "Se um elemento tem um atributo \"onmouseup\" ele também deve ter um atributo \"onkeyup\"."
+ },
+ "guidelines": {
+ "508": [
+ "l"
+ ],
+ "wcag": {
+ "2.1.1": {
+ "techniques": [
+ "G90",
+ "SCR2",
+ "SCR20"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "G90",
+ "SCR20"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "javascript"
+ ],
+ "components": [
+ "event",
+ "hasEventListener"
+ ],
+ "options": {
+ "correspondingEvent": "onkeyup",
+ "searchEvent": "onmouseup"
+ }
+ },
+ "scriptUIMustBeAccessible": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Die Benutzerschnittstelle von Skripten sollte barrierefrei sein",
+ "en": "The user interface for scripts should be accessible",
+ "nl": "De user interface voor scripts moet toegankelijk zijn",
+ "pt-br": "A interface de usuário para scripts deve ser acessível"
+ },
+ "description": {
+ "de": "Alle Skripte sollten dahingehend geprüft werden, ob ihre Benutzerschnittstelle barrierefrei ist",
+ "en": "All scripts should be assessed to see if their interface is accessible.",
+ "nl": "Alle scripts moeten gecontroleerd worden op toegankelijkheid van hun interface.",
+ "pt-br": "Todos os scripts devem ser avaliados para ver se sua interface é acessível."
+ },
+ "guidelines": {
+ "508": [
+ "l"
+ ]
+ },
+ "tags": [
+ "javascript"
+ ],
+ "options": {
+ "selector": "script"
+ }
+ },
+ "scriptsDoNotFlicker": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Skripte sollten kein Flackern des Bildschirms verursachen",
+ "en": "Scripts should not cause the screen to flicker",
+ "nl": "Scripts mogen het scherm niet laten knipperen of flitsen",
+ "pt-br": "Scripts não devem causar a cintilação da tela"
+ },
+ "description": {
+ "de": "Alle Skripte sollten dahingehend geprüft werden, dass ihre Benutzerschnittstelle nicht flackert",
+ "en": "All scripts should be assessed to see if their interface does not flicker.",
+ "nl": "Alle scripts moeten gecontroleerd worden om te zien of zij de interface niet laten knipperen of flitsen.",
+ "pt-br": "Todos os scripts devem ser avaliados para que se sua interface não pisque."
+ },
+ "guidelines": {
+ "508": [
+ "j"
+ ],
+ "wcag": {
+ "2.2.2": {
+ "techniques": [
+ "F7"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "javascript"
+ ],
+ "options": {
+ "selector": "script"
+ }
+ },
+ "scriptsDoNotUseColorAlone": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Die Benutzerschnittstelle von Skripten sollte nicht nur Farben verwenden, um Inhalte zu kommunizieren",
+ "en": "The interface in scripts should not use color alone",
+ "nl": "De interface in scripts gebruikt niet alleen maar kleur",
+ "pt-br": "A interface em scripts não deve usar cor sozinha"
+ },
+ "description": {
+ "de": "Alle Skripte sollten dahingehend geprüft werden, dass es für ihre Benutzerschnittstelle nicht nötig ist zwischen Farben unterscheiden zu können",
+ "en": "All scripts should be assessed to see if their interface does not have an interface which requires distinguishing between colors alone.",
+ "nl": "Alle scripts moeten gecontroleerd worden om te zien of hun interface geen interface heeft die alleen op kleur kan worden onderscheiden.",
+ "pt-br": "Todos os scripts devem ser avaliados para ver se não possuem uma interface que exige distinção entre cores sozinhas."
+ },
+ "guidelines": {
+ "508": [
+ "c"
+ ]
+ },
+ "tags": [
+ "javascript",
+ "color"
+ ],
+ "options": {
+ "selector": "script"
+ }
+ },
+ "selectDoesNotChangeContext": {
+ "type": "event",
+ "testability": 1,
+ "title": {
+ "de": "\"select\"-Elemente dürfen kein \"onchange\"-Attribut haben",
+ "en": "\"Select\" elements must not contain an \"onchange\" attribute",
+ "nl": "\"Select\" elements bevatten geen \"onchange\" attribute",
+ "pt-br": "Os elementos \"Select\" não devem conter um atributo \"onchange\""
+ },
+ "description": {
+ "de": "Aktionen wie \"onchange\" entziehen dem Benutzer die Kontrolle beim Versuch auf der Seite zu navigieren. \"onchange\"-Attribute für Dinge wie Auswahl-Listenmenüs sollten durch Drop-Downs und eine Schaltfläche zur Initiierung der Aktion ersetzt werden.",
+ "en": "Actions like \"onchange\" can take control away from users who are trying to navigate the page. Using an \"onchange\" attribute for things like select-list menus should instead be replaced with a drop-down and a button which initiates the action.",
+ "nl": "Acties als \"onchange\" kunnen de controle ontnemen van gebruikers die op een pagina proberen te navigeren. Het gebruik van een \"onchange\"-attribuut voor zaken zoals select-list menu's moet vervangen worden door een drop-down en een knop waarmee je de actie start.",
+ "pt-br": "Ações como \"onchange\" podem tirar o controle dos usuários que estão tentando navegar na página. O uso de um atributo \"onchange\" para coisas como menus de lista de seleção deve ser substituído por um drop-down e um botão que inicia a ação."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "event",
+ "hasEventListener"
+ ],
+ "options": {
+ "searchEvent": "onchange",
+ "selector": "select"
+ }
+ },
+ "selectHasAssociatedLabel": {
+ "type": "label",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"select\"-Elemente haben explizit assoziierte Labels",
+ "en": "All select elements have an explicitly associated label",
+ "nl": "Alle select-elementen hebben een expliciet bijbehorend label",
+ "pt-br": "Todos os elementos selecionados têm um rótulo associado explicitamente"
+ },
+ "description": {
+ "de": "Alle select-Elemente sollten ein dazugehöriges label-Element haben. Bildschirmleseprogramme haben oftmals eine Formular-Modus, in dem nur Labels vorgelesen werden.",
+ "en": "All select elements should have a corresponding label element. Screen readers often enter a \"form mode\" where only label text is read aloud to the user",
+ "nl": "Alle select-elementen moeten een bijbehorend label-element hebben. Schermlezers maken vaak gebruik van een \"formuliereninstelling\" waarbij alleen de tekst van de labels hardop aan de gebruiker wordt voorgelezen.",
+ "pt-br": "Todos os elementos select code> devem ter um elemento label code> correspondente. Os leitores de tela costumam entrar em um \"modo de formulário\" onde somente o texto do rótulo é lido em voz alta para o usuário"
+ },
+ "guidelines": {
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H44"
+ ]
+ },
+ "1.3.1": {
+ "techniques": [
+ "H44",
+ "F68"
+ ]
+ },
+ "2.1.1": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "3.3.2": {
+ "techniques": [
+ "H44"
+ ]
+ },
+ "4.1.2": {
+ "techniques": [
+ "H44",
+ "H91"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "label"
+ ],
+ "options": {
+ "selector": "select"
+ }
+ },
+ "selectJumpMenu": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Sprungmenüs sollten die Weiterleitung durch Betätigen einer Schaltfläche ausführen, nicht auf einen Statuswechsel des Menüs",
+ "en": "Select jump menus should jump on button press, not on state change",
+ "nl": "Select jump menu's moeten springen wanneer de knop wordt gebruikt, niet bij statusverandering",
+ "pt-br": "Menus de salto devem realizar o encaminhamento ao pressionar um botão, não uma mudança no status do menu"
+ },
+ "description": {
+ "de": "Wenn Sie ein Sprungmenü verwenden wollen, welches den Benutzer nach Auswahl eines Menüpunktes weiterleitet, sollte die Weiterleitung durch das Betätigen einer Schaltfläche geschehen, nicht durch die Auswahl eines Menüelements",
+ "en": "If you wish to use a 'Jump' menu with a select item that then redirects users to another page, the jump should occur on the user pressing a button, rather than on the change event of that select element.",
+ "nl": "Als je een 'Jump'-menu wilt gebruiken met een select item dat gebruikers naar een andere pagina verwijst, moet de verwijzing plaatsvinden als de gebruiker een knop gebruikt en niet op het moment dat het select element verandert.",
+ "pt-br": "Se você deseja usar um menu de salto com um item de seleção que, em seguida, redireciona os usuários para outra página, o salto deve ocorrer no usuário pressionando um botão, em vez de no evento de alteração desse elemento de seleção."
+ },
+ "guidelines": {
+ "wcag": {
+ "3.2.2": {
+ "techniques": [
+ "F37"
+ ]
+ },
+ "3.2.5": {
+ "techniques": [
+ "F9"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "hasEventListener"
+ ],
+ "callback": "selectJumpMenu"
+ },
+ "selectWithOptionsHasOptgroup": {
+ "type": "selector",
+ "testability": 0.5,
+ "title": {
+ "de": "Auswahlelemente in Formularen sollten \"optgroups\" für lange Auswahlen verwenden",
+ "en": "Form select elements should use optgroups for long selections",
+ "nl": "Formulier select-elementen moeten optgroups gebruiken voor lange selecties",
+ "pt-br": "Os elementos de seleção de formulário devem usar optgroup para seleções longas"
+ },
+ "description": {
+ "de": "Wenn ein Auswahlelement viele Optionen hat, sollten \"optgroups\" zur Unterstützung der Navigation verwendet werden",
+ "en": "If a select element has many options, use optgroups to help ease navigation.",
+ "nl": "Als een select-element veel opties heeft, gebruik dan optgroups om navigatie makkelijker te maken.",
+ "pt-br": "Se um elemento select tiver muitas opções, use optgroups para facilitar a navegação."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "H85"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "options": {
+ "selector": "select:not(select:has(optgroup)) option:nth-child(5)"
+ }
+ },
+ "siteMap": {
+ "type": "custom",
+ "testability": 0,
+ "title": {
+ "de": "Webseiten müssen eine Sitemap haben",
+ "en": "Websites must have a site map",
+ "nl": "Websites moeten een sitemap hebben",
+ "pt-br": "Websites devem ter um mapa do site"
+ },
+ "description": {
+ "de": "Jede Webseite sollte eine Seite haben, die eine Sitemap oder eine andere Methode zur Navigation zu den wichtigsten Seiten anbietet, um den Benutzern von Assistenztechnologien Zeit zu sparen",
+ "en": "Every web site should have a page which provides a site map or another method to navigate most of the site from a single page to save time for users of assistive devices.",
+ "nl": "Elke website moet een pagina hebben waarop een sitemap staat of een andere methode om op de site te navigeren vanaf een pagina. Dit spaart gebruikers die hulpmiddelen gebruiken tijd.",
+ "pt-br": "Cada site deve ter uma página que fornece um mapa do site ou outro método para navegar a maior parte do site a partir de uma única página para economizar tempo para os usuários de dispositivos assistivos."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.5": {
+ "techniques": [
+ "G63"
+ ]
+ },
+ "2.4.8": {
+ "techniques": [
+ "G63"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "document"
+ ],
+ "strings": [
+ "siteMap"
+ ],
+ "callback": "siteMap"
+ },
+ "skipToContentLinkProvided": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Eine \"Weiter zum Inhalt\"-Verknüpfung sollte auf der Seite eine der ersten Verknüpfungen sein",
+ "en": "A \"skip to content\" link should exist as one of the first links on the page",
+ "nl": "Er moet een \"skip to content\"-link zijn als een van de eerste links op de pagina",
+ "pt-br": "Um link \"pular para o conteúdo\" deve existir como um dos primeiros links na página"
+ },
+ "description": {
+ "de": "Eine \"Weiter zum Inhalt\"-Verknüpfung sollte auf der Seite eine der ersten Verknüpfungen sein",
+ "en": "A link reading \"skip to content\" should be the first link on a page.",
+ "nl": "Er moet een link zijn om naar de content te navigeren als een van de eerste links op de pagina.",
+ "pt-br": "Um link de leitura \"pular para conteúdo\" deve ser o primeiro link em uma página."
+ },
+ "guidelines": {
+ "508": [
+ "o"
+ ],
+ "wcag": {
+ "2.4.1": {
+ "techniques": [
+ "G1"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "document"
+ ],
+ "strings": [
+ "skipContent"
+ ],
+ "callback": "skipToContentLinkProvided"
+ },
+ "svgContainsTitle": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Inline-SVG sollte \"title\"-Elemente haben",
+ "en": "Inline SVG should use Title elements",
+ "nl": "Inline SVG moet titelelementen gebruiken",
+ "pt-br": "O SVG inline deve usar elementos de título"
+ },
+ "description": {
+ "de": "Jede inline SVG-Grafik sollte ein eingebettetes title-Element haben",
+ "en": "Any inline SVG image should have an embedded title element.",
+ "nl": "Elke inline SVG-afbeelding moet een ingebed title-element hebben.",
+ "pt-br": "Qualquer imagem SVG in-line deve ter um elemento title incorporado."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "F65"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "image",
+ "svg",
+ "content"
+ ],
+ "options": {
+ "selector": "svg:not(svg:has(title))"
+ }
+ },
+ "tableAxisHasCorrespondingId": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "\"axis\"-Attribute sollten dazugehörige IDs haben",
+ "en": "Axis attribute should have corresponding IDs",
+ "nl": "Axis-attributen moeten bijbehorende IDs hebben",
+ "pt-br": "O atributo Axis deve ter IDs correspondentes"
+ },
+ "description": {
+ "de": "Wenn ein \"axis\"-Attribut verwendet wird, um Zellen zu gruppieren, sollte sichergestellt sein, dass das Ziel-Element mit derselben ID vorhanden ist",
+ "en": "When using the axis attribute to group cells together, ensure they have a target element with the same ID.",
+ "nl": "Wanneer er axis-attributen gebruikt worden om cellen te groeperen, zorg er dan voor dat hun doelelement hetzelfde ID heeft.",
+ "pt-br": "Ao usar o atributo de eixo para agrupar células em conjunto, certifique-se de que eles tenham um elemento de destino com o mesmo ID."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "F17"
+ ]
+ },
+ "4.1.1": {
+ "techniques": [
+ "F17"
+ ]
+ }
+ }
+ },
+ "callback": "tableAxisHasCorrespondingId"
+ },
+ "tabIndexFollowsLogicalOrder": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Die Tabulatorreihenfolge eines Dokumentes ist logisch",
+ "en": "The tab order of a document is logical",
+ "nl": "De tabvolgorde van een document is logisch",
+ "pt-br": "A ordem de tabulação de um documento é lógica"
+ },
+ "description": {
+ "de": "Prüfen Sie, ob die Tabulatorreihenfolge der Seite logisch ist",
+ "en": "Check that the tab order of a page is logical.",
+ "nl": "Controleer of de tabvolgorde van een pagina logisch is.",
+ "pt-br": "Verifique se a ordem de tabulação de uma página é lógica."
+ },
+ "guidelines": {
+ "wcag": {
+ "2.4.3": {
+ "techniques": [
+ "H4"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "document"
+ ],
+ "callback": "tabIndexFollowsLogicalOrder"
+ },
+ "tableCaptionIdentifiesTable": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Überschriften sollten ihre Tabelle identifizieren",
+ "en": "Captions should identify their table",
+ "nl": "Beschrijvingen moeten hun tabellen identificeren",
+ "pt-br": "As legendas devem identificar as suas tabelas"
+ },
+ "description": {
+ "de": "Stellen Sie sicher, dass eine Tabellenüberschrift die Tabelle mit Name, Figurennummer etc. identifiziert",
+ "en": "Check to make sure that a table's caption identifies the table with a name, figure number, etc.",
+ "nl": "Controleer of de beschrijving van een tabel de tabel identificeert met een naam, nummer en dergelijke.",
+ "pt-br": "Verifique se a legenda de uma tabela identifica a tabela com um nome, número da figura, etc."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "H39"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "table",
+ "content"
+ ],
+ "options": {
+ "selector": "caption"
+ }
+ },
+ "tableComplexHasSummary": {
+ "type": "selector",
+ "testability": 0.5,
+ "title": {
+ "de": "Komplexe Tabellen sollten eine Zusammenfassung haben",
+ "en": "Complex tables should have a summary",
+ "nl": "Complexe tabellen moeten een samenvatting hebben",
+ "pt-br": "As tabelas complexas devem ter um resumo"
+ },
+ "description": {
+ "de": "Wenn eine Tabelle komplex ist (z.B. Zellen mit \"colspan\"-Attributen hat), sollte die Tabelle eine Zusammenfassung haben",
+ "en": "If a table is complex (for example, has some cells with \"colspan\" attributes, the table should have a summary.",
+ "nl": "Als een tabel complex is (bijvoorbeeld, als er cellen zijn met \"colspan\"-attributen, moet de tabel een samenvatting hebben.",
+ "pt-br": "Se uma tabela é complexa (por exemplo, tem algumas células com atributos \"colspan\", esta deve ter um resumo."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "H39"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "table",
+ "content"
+ ],
+ "options": {
+ "selector": "table:not(table[summary], table:has(caption))"
+ }
+ },
+ "tableDataShouldHaveTh": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Datentabellen sollten eine Überschrift haben",
+ "en": "Data tables should contain a header",
+ "nl": "Datatabellen moeten \"th\"-elementen bevatten",
+ "pt-br": "As tabelas de dados devem conter um cabeçalho"
+ },
+ "description": {
+ "de": "Tabellen die Daten beinhalten (anders als Layout-Tabellen), sollten korrekte \"header\"-Elemente haben, um sie für Bildschirmleseprogramme hervorzuheben und die Struktur des Dokumentes zu verbessern",
+ "en": "Tables which contain data (as opposed to layout tables) should contain proper table header elements to mark them for screen readers and enhance the structure of the document.",
+ "nl": "Tabellen die data bevatten (in tegenstelling tot lay-out tabellen) moeten th-elementen bevatten om koppen te markeren voor schermlezers en om de structuur van het document te verbeteren.",
+ "pt-br": "Tabelas que contêm dados (em oposição a tabelas de layout) devem conter elementos de cabeçalho de tabela adequada para marcá-los para leitores de tela e aprimorar a estrutura do documento."
+ },
+ "guidelines": {
+ "508": [
+ "g"
+ ],
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "F91"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "table",
+ "content"
+ ],
+ "options": {
+ "selector": "table:not(table:has(th))"
+ }
+ },
+ "tableHeaderLabelMustBeTerse": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Tabellenüberschriften müssen kurz sein",
+ "en": "Table header lables must be terse",
+ "nl": "Tabelkoppen moeten bondig zijn",
+ "pt-br": "As etiquetas de cabeçalho da tabela devem ser concisas"
+ },
+ "description": {
+ "de": "Das \"abbr\"-Attribut für Tabellenüberschriften muss kurz sein (max. 20 Zeichen)",
+ "en": "The \"abbr\" attribute for table headers must be terse (less than 20 characters long).",
+ "nl": "Het \"abbr\"-attribuut voor tabelkoppen moet bondig zijn (minder dan 20 tekens lang).",
+ "pt-br": "O atributo \"abbr\" para cabeçalhos de tabela deve ser conciso (menos de 20 caracteres)."
+ },
+ "guidelines": [],
+ "tags": [
+ "table",
+ "content"
+ ],
+ "callback": "tableHeaderLabelMustBeTerse"
+ },
+ "tableIsGrouped": {
+ "type": "selector",
+ "testability": 0.5,
+ "title": {
+ "de": "Kennzeichnen Sie die Bereiche einer Tabelle mit \"thead\" und \"tbody\"",
+ "en": "Mark up the areas of tables using thead and tbody",
+ "nl": "Gebruik thead en tbody voor tabellen",
+ "pt-br": "Marcar as áreas das tabelas usando thead e tbody"
+ },
+ "description": {
+ "de": "Kennzeichnen Sie die Bereiche einer Tabelle mit \"thead\" und \"tbody\"",
+ "en": "Mark up the areas of tables using thead and tbody.",
+ "nl": "Gebruik thead en tbody voor tabellen.",
+ "pt-br": "Marcar as áreas das tabelas usando thead e tbody"
+ },
+ "guidelines": [],
+ "tags": [
+ "table",
+ "content"
+ ],
+ "options": {
+ "selector": "table:not(table:has(thead), table:has(tfoot))"
+ }
+ },
+ "tableLayoutDataShouldNotHaveTh": {
+ "type": "custom",
+ "testability": 0,
+ "title": {
+ "de": "Layout-Tabellen sollten keine \"th\"-Elemente beinhalten",
+ "en": "Layout tables should not contain \"th\" elements",
+ "nl": "Lay-out tabellen bevatten geen \"th\"-elementen",
+ "pt-br": "Tabelas de layout não devem conter \"th\" elementos"
+ },
+ "description": {
+ "de": "Tabellen, die nur für das Layout verwendet werden (im Gegesatz zu Datentabellen), should not contain th-Elemente, welche die Tabelle als Datentabelle erscheinen lassen",
+ "en": "Tables which are used purely for layout (as opposed to data tables), should not contain th elements, which would make the table appear to be a data table.",
+ "nl": "Tabellen die alleen voor lay-out worden gebruikt (in tegenstelling tot datatabellen), moeten geen th-elementen bevatten, omdat deze de indruk wekken dat het een datatabel betreft.",
+ "pt-br": "As tabelas que são usadas puramente para o layout (em oposição às tabelas de dados), não devem conter elementos th , o que tornaria a tabela aparente ser uma tabela de dados."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "F46"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "table",
+ "layout",
+ "content"
+ ],
+ "callback": "tableLayoutDataShouldNotHaveTh"
+ },
+ "tableLayoutHasNoCaption": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Alle Layout-Tabellen haben kein \"caption\"-Element",
+ "en": "All tables used for layout have no \"caption\" element",
+ "nl": "Alle tabellen die alleen voor lay-out worden gebruikt hebben geen \"caption\"-element",
+ "pt-br": "Todas as tabelas usadas para o layout não têm elemento \"caption\""
+ },
+ "description": {
+ "de": "Wenn eine Tabelle keine Daten beinhaltet und nur für das Layout verwendet wird, sollte sie kein caption-Element beinhalten",
+ "en": "If a table contains no data, and is used simply for layout, then it should not contain a caption element.",
+ "nl": "Als een tabel geen data bevat en alle voor lay-out wordt gebruikt, moet hij geen caption-element krijgen.",
+ "pt-br": "Se uma tabela não contém dados e é usada apenas para layout, ela não deve conter um elemento caption ."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "F46"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "table",
+ "layout",
+ "content"
+ ],
+ "callback": "tableLayoutHasNoCaption"
+ },
+ "tableLayoutHasNoSummary": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Alle Layout-Tabellen haben keine oder eine leere Zusammenfassung",
+ "en": "All tables used for layout have no summary or an empty summary",
+ "nl": "Alle tabellen die alleen voor lay-out worden gebruikt hebben geen samenvatting",
+ "pt-br": "Todas as tabelas utilizadas para layout não têm resumo ou um resumo vazio"
+ },
+ "description": {
+ "de": "Wenn eine Tabelle keine Daten beinhaltet, sondern nur für das Layout verwendet wird, sollte sie kein \"summary\"-Attribut haben",
+ "en": "If a table contains no data, and is used simply for layout, then it should not have a \"summary\" attribute.",
+ "nl": "Als een tabel geen data bevat en alleen voor lay-out wordt gebruikt, moet hij geen \"summary\"-attribuut krijgen.",
+ "pt-br": "Se uma tabela não contém dados e é usada simplesmente para layout, ela não deve ter um atributo \"summary\"."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "F46"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "table",
+ "layout",
+ "content"
+ ],
+ "callback": "tableLayoutHasNoSummary"
+ },
+ "tableLayoutMakesSenseLinearized": {
+ "type": "custom",
+ "testability": 0,
+ "title": {
+ "de": "Alle Layout-Tabellen sollten entfernt werden können und die Seite ist dennoch sinnvoll",
+ "en": "All tables used for layout should make sense when removed",
+ "nl": "Als tabellen voor lay-out worden gebruikt moet de pagina nog duidelijk blijven als de tabel wordt verwijderd",
+ "pt-br": "Todas as tabelas usadas para layout devem fazer sentido quando removidas"
+ },
+ "description": {
+ "de": "Wenn ein table-Element nur für Layoutzwecke verwendet wird, sollte der Inhalt der Tabelle sinnvoll sein, auch wenn die Tabelle entfernt wird",
+ "en": "If a table element is used for layout purposes only, then the content of the table should make sense if the table is linearized.",
+ "nl": "Als een table-element alleen voor lay-out-doeleinden wordt gebruikt, moet de inhoud van de tabel nog steeds duidelijk zijn als de tabel wordt verwijderd.",
+ "pt-br": "Se um elemento table for usado somente para fins de layout, o conteúdo da tabela deve fazer sentido se a tabela for linearizada."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.2": {
+ "techniques": [
+ "G57"
+ ]
+ },
+ "4.1.1": {
+ "techniques": [
+ "F49"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "table",
+ "layout",
+ "content"
+ ],
+ "callback": "tableLayoutMakesSenseLinearized"
+ },
+ "tableNotUsedForLayout": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Tabellen sollte nicht für Layouts verwendet werden",
+ "en": "Tables should not be used for layout",
+ "nl": "Tabellen moet niet worden gebruikt voor lay-out",
+ "pt-br": "Tabelas não devem ser usadas para layout"
+ },
+ "description": {
+ "de": "Tabellen dienen der Darstellung von Daten, nicht für die Umsetzung von Layouts. Verwenden Sie stattdessen HTML und CSS.",
+ "en": "Tables are for data, not for creating a page layout. Consider using standard HTML and CSS techniques instead.",
+ "nl": "Tabellen zijn voor data, niet om een pagina op te maken. Gebruik hiervoor HTML en CSS.",
+ "pt-br": "As tabelas são para dados, não para criar um layout de página. Considere usar técnicas HTML e CSS padrão."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.2": {
+ "techniques": [
+ "F49"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "table",
+ "layout",
+ "content"
+ ],
+ "callback": "tableNotUsedForLayout"
+ },
+ "tableShouldUseHeaderIDs": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Tabellenzellen verwenden IDs um Überschriften zu identifizieren",
+ "en": "Table cells use IDs to identify headers",
+ "nl": "Tabelcellen gebruiken IDs om koppen te identificeren",
+ "pt-br": "As células da tabela usam IDs para identificar cabeçalhos"
+ },
+ "description": {
+ "de": "Wenn eine Tabelle nicht für das Layout verwendet wird, sollte es IDs und Überschriften-Attribute verwenden, um Tabellenüberschriften zu identifizieren",
+ "en": "If a table is not being used for layout, it should use IDs and header attributes to identify table headers.",
+ "nl": "Een tabel moet IDs en header-attributen gebruiken om tabelkoppen te identificeren.",
+ "pt-br": "Se uma tabela não estiver sendo usada para layout, ela deve usar IDs e atributos de cabeçalho para identificar cabeçalhos de tabela."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "H43"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "table",
+ "content"
+ ],
+ "callback": "tableShouldUseHeaderIDs"
+ },
+ "tableSummaryDescribesTable": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Tabellenzusammenfassungen sollten die Navigation und Struktur der Tabelle beschreiben",
+ "en": "Table summaries should describe the navigation and structure of the table",
+ "nl": "Tabelsamenvattingen moeten de navigatie en structuur van de tabel beschrijven",
+ "pt-br": "Os resumos das tabelas devem descrever a navegação ea estrutura da tabela"
+ },
+ "description": {
+ "de": "summary-Elemente von Tabellen sollten die Navgation und Struktur der Tabelle erläutern und einen Überblick über den Inhalt der Tabelle bieten",
+ "en": "Table summary elements should describe the navigation tools and structure of the table, as well as provide an overview of what the table describes.",
+ "nl": "Tabel \"summary\"-elementen moeten de navigatie en structuur van de tabel beschrijven, en een overzicht bieden van wat er in de tabel staat.",
+ "pt-br": "Os elementos da tabela summary devem descrever as ferramentas de navegação ea estrutura da tabela, bem como fornecer uma visão geral do que a tabela descreve."
+ },
+ "guidelines": [],
+ "tags": [
+ "table",
+ "content"
+ ],
+ "options": {
+ "selector": "table[summary]"
+ }
+ },
+ "tableSummaryDoesNotDuplicateCaption": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "\"summary\"-Elemente von Tabellen sollten nicht den Inhalt des \"caption\"-Elements wiederholen",
+ "en": "Table \"summary\" elements should not duplicate the \"caption\" element",
+ "nl": "Tabel \"summary\"-elementen mogen niet hetzelfde zijn als het \"caption\"-element",
+ "pt-br": "Tabela \"resumo\" elementos não devem duplicar o elemento \"legenda\""
+ },
+ "description": {
+ "de": "Die Zusammenfassung und die Überschrift einer Tabelle müssen sich unterscheiden, da beide unterschiedliche Informationen liefern. Ein caption-ELement identifiziert die Tabelle, während ein \"summary\"-Attribut den Tabelleninhalt beschreibt",
+ "en": "The summary and the caption must be different, as both provide different information. A caption. /code element identifies the table, while the \"summary\" attribute describes the table contents.",
+ "nl": "De samenvatting en beschrijving van een tabel moeten verschillen, want ze bieden verschillende informatie. Een caption-element identificeert welke tabel het betreft en het \"summary\"-attribuut beschrijft de inhoud van de tabel.",
+ "pt-br": "O resumo ea legenda devem ser diferentes, pois ambos fornecem informações diferentes. Uma legenda code>. / Code identifica a tabela, enquanto o atributo \"summary\" descreve o conteúdo da tabela."
+ },
+ "guidelines": [],
+ "tags": [
+ "table",
+ "content"
+ ],
+ "callback": "tableSummaryDoesNotDuplicateCaption"
+ },
+ "tableSummaryIsEmpty": {
+ "type": "placeholder",
+ "testability": 0.5,
+ "title": {
+ "de": "Alle Datentabellen sollten eine Zusammenfassung haben",
+ "en": "All data tables should have a summary",
+ "nl": "Alle datatabellen moeten een samenvatting hebben",
+ "pt-br": "Todas as tabelas de dados devem ter um resumo"
+ },
+ "description": {
+ "de": "Wenn eine Tabelle Daten enthält, sollte sie ein \"summary\"-Attribut haben",
+ "en": "If a table contains data, it should have a \"summary\" attribute.",
+ "nl": "Als een tabel data bevat, moet hij een \"summary\"-attribuut hebben.",
+ "pt-br": "Se uma tabela contiver dados, ele deve ter um atributo \"summary\"."
+ },
+ "guidelines": [],
+ "tags": [
+ "table",
+ "content"
+ ],
+ "components": [
+ "placeholder"
+ ],
+ "options": {
+ "attribute": "summary",
+ "empty": true,
+ "selector": "table[summary]"
+ }
+ },
+ "tableSummaryIsNotTooLong": {
+ "type": "custom",
+ "testability": 0,
+ "guidelines": [],
+ "tags": [
+ "table",
+ "content"
+ ],
+ "callback": "tableSummaryIsNotTooLong"
+ },
+ "tableSummaryIsSufficient": {
+ "type": "selector",
+ "testability": 0,
+ "title": {
+ "de": "Alle Datentabellen sollten eine adäquate Zusammenfassung haben",
+ "en": "All data tables should have an adequate summary",
+ "nl": "Alle datatabellen moeten een toepasselijke samenvatting hebben",
+ "pt-br": "Todas as tabelas de dados devem ter um resumo"
+ },
+ "description": {
+ "de": "Wenn eine Tabelle Daten beinhaltet, sollte es ein \"summary\"-Attribut haben, das den Sinn und Zweck der Tabelle komplett beschreibt",
+ "en": "If a table contains data, it should have a \"summary\" attribute that completely communicates the function and use of the table.",
+ "nl": "Als een tabel data bevat, moet er een \"summary\"-attribuut zijn dat de functie en het doel van de tabel duidelijk maakt.",
+ "pt-br": "Se uma tabela contiver dados, ele deve ter um atributo \"summary\" que comunique completamente a função eo uso da tabela."
+ },
+ "guidelines": [],
+ "tags": [
+ "table",
+ "content"
+ ],
+ "options": {
+ "selector": "table[summary]"
+ }
+ },
+ "tableUseColGroup": {
+ "type": "custom",
+ "testability": 0,
+ "title": {
+ "de": "Gruppieren Sie Spalten mit \"colgroup\"-Elementen oder \"col\"-Elementen",
+ "en": "Group columns using \"colgroup\" or \"col\" elements",
+ "nl": "Groepeer kolommen met \"colgroup\"- of \"col\"-elementen",
+ "pt-br": "Colunas de grupo usando elementos \"colgroup\" ou \"col\""
+ },
+ "description": {
+ "de": "Um komplexe Tabellenüberschriften sinnvoll zu gestalten, verwenden Sie colgroup oder col um sie zu gruppieren",
+ "en": "To help complex table headers make sense, use colgroup or col to group them together.",
+ "nl": "Maak complexe tabelkoppen duidelijker door \"colgroup\"- of \"col\"-elementen te gebruiken om ze te groeperen.",
+ "pt-br": "Para ajudar os cabeçalhos de tabela complexos fazer sentido, use colgroup ou col para agrupá-los."
+ },
+ "guidelines": [],
+ "tags": [
+ "table",
+ "content"
+ ],
+ "callback": "tableUseColGroup"
+ },
+ "tableUsesAbbreviationForHeader": {
+ "type": "custom",
+ "testability": 0,
+ "title": {
+ "de": "Tabellenüberschriften über 20 Zeichen sollten ein \"abbr\"-Attribut haben",
+ "en": "Table headers over 20 characters should provide an \"abbr\" attribute",
+ "nl": "Tabelkoppen met meer dan 20 tekens moeten een \"abbr\"-attribuut hebben",
+ "pt-br": "Cabeçalhos de tabela com mais de 20 caracteres devem fornecer um atributo \"abbr\""
+ },
+ "description": {
+ "de": "Für lange Tabellenüberschriften verwenden Sie ein \"abbr\"-Attribut das kürzer ist (max. 20 Zeichen).",
+ "en": "For long table headers, use an \"abbr\" attribute that is less than short (less than 20 characters long).",
+ "nl": "Gebruik een \"abbr\"-attribuut korter dan 20 tekens voor lange tabelkoppen.",
+ "pt-br": "Para cabeçalhos de tabelas longas, use um atributo \"abbr\" que seja menos do que curto (menos de 20 caracteres)."
+ },
+ "guidelines": [],
+ "tags": [
+ "table",
+ "content"
+ ],
+ "callback": "tableUsesAbbreviationForHeader"
+ },
+ "tableUsesCaption": {
+ "type": "selector",
+ "testability": 1,
+ "title": {
+ "de": "Datentabellen sollten ein \"caption\"-Element haben, wenn sie nicht anderweitig beschrieben sind",
+ "en": "Data tables should contain a \"caption\" element if not described elsewhere",
+ "nl": "Datatabellen moeten een \"caption\"-element hebben als ze nergens anders beschreven worden",
+ "pt-br": "As tabelas de dados devem conter um elemento \"caption\" se não for descrito em outro lugar"
+ },
+ "description": {
+ "de": "Wenn Tabellen nicht anderweitig im Dokument beschrieben sind, sollten sie ein caption-Element zu beschreibung beinhalten",
+ "en": "Unless otherwise described in the document, tables should contain caption elements to describe the purpose of the table.",
+ "nl": "Tenzij elders in het document beschreven, moeten tabellen een \"caption\"-element hebben om het doel van de tabel te beschrijven.",
+ "pt-br": "As tabelas devem conter elementos caption para descrever o propósito da tabela."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "H39"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "table",
+ "content"
+ ],
+ "options": {
+ "selector": "table:not(table:has(caption))"
+ }
+ },
+ "tableUsesScopeForRow": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Datentabellen sollten Überschrift mit \"scope\"-Attribut verwenden, wenn Zeilenüberschriften benötigt werden",
+ "en": "Data tables should use scoped headers for rows with headers",
+ "nl": "Datatabellen moeten het \"scope\"-attribuut gebruiken voor rijen met koppen",
+ "pt-br": "As tabelas de dados devem usar cabeçalhos com escopo para linhas com cabeçalhos"
+ },
+ "description": {
+ "de": "Wenn Tabellenüberschriften für Zeilen und Spalten benötigt werden, sollte das \"scope\"-Attribut verwendet werden, um die Überschriften den richtigen Zellen zuzuordnen. Dieser Test prüft die erste und letzte Zelle in jeder Zeile und prüft, ob sie sich im Layout oder der Gewichtung der Schriftart unterscheiden.",
+ "en": "Where there are table headers for both rows and columns, use the \"scope\" attribute to help relate those headers with their appropriate cells. This test looks for the first and last cells in each row and sees if they differ in layout or font weight.",
+ "nl": "Als er tabelkoppen zijn voor zowel rijen als kolommen, gebruik dan het \"scope\"-attribuut om het juiste verband te leggen tussen de koppen en bijbehorende cellen.",
+ "pt-br": "Onde houver cabeçalhos de tabela para linhas e colunas, use o atributo \"scope\" para ajudar a relacionar esses cabeçalhos com suas células apropriadas. Este teste procura a primeira e última células em cada linha e vê se eles diferem no layout ou peso da fonte."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "H63"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "table",
+ "content"
+ ],
+ "callback": "tableUsesScopeForRow"
+ },
+ "tableWithBothHeadersUseScope": {
+ "type": "selector",
+ "testability": 0.5,
+ "title": {
+ "de": "Datentabellen mit mehreren Überschriften sollten das \"scope\"-Attribut verwenden",
+ "en": "Data tables with multiple headers should use the \"scope\" attribute",
+ "nl": "Datatabellen met meerdere headers moeten het \"scope\"-attribuut gebruiken",
+ "pt-br": "As tabelas de dados com vários cabeçalhos devem usar o atributo \"scope\""
+ },
+ "description": {
+ "de": "Wenn Tabellenüberschriften für Zeilen und Spalten verwendet werden, nutzen Sie das \"scope\"-Attribut, um die Überschriften den richtigen Zellen zuzuordnen",
+ "en": "Where there are table headers for both rows and columns, use the \"scope\" attribute to help relate those headers with their appropriate cells.",
+ "nl": "Als er tabelkoppen zijn voor zowel rijen als kolommen, gebruik dan het \"scope\"-attribuut om het juiste verband te leggen tussen de koppen en bijbehorende cellen.",
+ "pt-br": "Onde houver cabeçalhos de tabela para linhas e colunas, use o atributo \"scope\" para ajudar a relacionar esses cabeçalhos com suas células apropriadas."
+ },
+ "guidelines": {
+ "508": [
+ "h"
+ ],
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "F91"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "table",
+ "content"
+ ],
+ "options": {
+ "selector": "table:has(tr:not(table tr:first) th:not(th[scope]))"
+ }
+ },
+ "tableWithMoreHeadersUseID": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Komplexe Datentabellen sollten \"id\"-Attribute für Überschriften bereitstellen",
+ "en": "Complex data tables should provide \"id\" attributes to headers",
+ "nl": "Complexe datatabellen moeten \"id\"-attributen aan headers koppelen",
+ "pt-br": "Tabelas de dados complexas devem fornecer \"id\" atributos para cabeçalhos"
+ },
+ "description": {
+ "de": "Komplexe Datentabellen sollten \"id\"-Attribute für Überschriften und \"header\"-Attribute für Datenzellen verwenden.",
+ "en": "Complex data tables should provide \"id\" attributes to headers and \"headers\" attributes for data cells.",
+ "nl": "Complexe datatabellen moeten \"id\"-attributen aan headers koppelen en \"headers\"-attributen aan datacellen.",
+ "pt-br": "Tabelas de dados complexas devem fornecer \"id\" atributos para cabeçalhos e atributos \"headers\" para células de dados."
+ },
+ "guidelines": [],
+ "tags": [
+ "table",
+ "content"
+ ],
+ "callback": "tableWithMoreHeadersUseID"
+ },
+ "tagsAreNestedCorrectly": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Alle Tags sollten korrekt verschachtelt werden",
+ "en": "All tags should be nested correctly",
+ "nl": "Alle tags moeten juist genest worden",
+ "pt-br": "Todas as tags devem ser aninhadas corretamente"
+ },
+ "description": {
+ "de": "",
+ "en": "",
+ "nl": "",
+ "pt-br": ""
+ },
+ "guidelines": {
+ "wcag": {
+ "4.1.1": {
+ "techniques": [
+ "H74"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "html"
+ ],
+ "components": [
+ "htmlSource"
+ ],
+ "callback": "tagsAreNestedCorrectly"
+ },
+ "tabularDataIsInTable": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Alle tabellarischen Informationen sollten in Tabellen dargestellt werden",
+ "en": "All tabular information should use a table",
+ "nl": "Alle tabelinformatie moet ook daadwerkelijk in een tabel staan",
+ "pt-br": "Todas as informações tabulares devem usar uma tabela"
+ },
+ "description": {
+ "de": "Tabellen sollten verwendet werden, um tabellarische Informationen darzustellen",
+ "en": "Tables should be used when displaying tabular information.",
+ "nl": "Gebruik een echte tabel wanneer je tabelinformatie wilt tonen.",
+ "pt-br": "As tabelas devem ser usadas ao exibir informações tabulares."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.1": {
+ "techniques": [
+ "F33",
+ "F34",
+ "F48"
+ ]
+ },
+ "1.3.2": {
+ "techniques": [
+ "F33",
+ "F34"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "table",
+ "content"
+ ],
+ "callback": "tabularDataIsInTable"
+ },
+ "textIsNotSmall": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Die Schriftgröße sollte nicht kleiner als 9px in der Höhe sein",
+ "en": "The text size is not less than 9 pixels high",
+ "nl": "De grootte van de tekst is meer dan 8 pixels hoog",
+ "pt-br": "O tamanho do texto não é inferior a 9 pixels de altura"
+ },
+ "description": {
+ "de": "Um Benutzern zu helfen, die Schwierigkeiten haben kleinen Text zu lesen, sollte die Schriftgröße nicht kleiner als 9px in der Höhe sein",
+ "en": "To help users with difficulty reading small text, ensure text size is no less than 9 pixels high.",
+ "nl": "Help gebruikers die moeite hebben met het lezen van kleine letters, door ervoor te zorgen dat tekst groter is dan 8 pixels hoog.",
+ "pt-br": "Para ajudar os usuários com dificuldade em ler texto pequeno, certifique-se de que o tamanho do texto não seja inferior a 9 pixels."
+ },
+ "guidelines": [],
+ "tags": [
+ "textsize",
+ "content"
+ ],
+ "components": [
+ "convertToPx"
+ ],
+ "callback": "textIsNotSmall"
+ },
+ "textareaHasAssociatedLabel": {
+ "type": "label",
+ "testability": 1,
+ "title": {
+ "de": "Alle \"textareas\" sollten ein dazugehöriges Label haben",
+ "en": "All textareas should have a corresponding label",
+ "nl": "Alle \"textarea\"-elementen moeten een bijbehorend label hebben",
+ "pt-br": "Todas as textareas devem ter um rótulo correspondente"
+ },
+ "description": {
+ "de": "Alle textarea-Elemente sollten ein dazugehöriges label-Element haben. Bildschirmleseprogramme haben oftmals eine Formular-Modus, in dem nur Labels vorgelesen werden.",
+ "en": "All textarea elements should have a corresponding label element. Screen readers often enter a \"form mode\" where only label text is read aloud to the user",
+ "nl": "Alle \"textarea\"-elementen moeten een bijbehorend label hebben. Schermlezers maken vaak gebruik van een \"formuliereninstelling\" waarbij alleen de tekst van de labels hardop aan de gebruiker wordt voorgelezen.",
+ "pt-br": "Todos os elementos textarea devem ter um elemento label correspondente. Os leitores de tela costumam entrar em um \"modo de formulário\" onde somente o texto do rótulo é lido em voz alta para o usuário"
+ },
+ "guidelines": {
+ "wcag": {
+ "1.1.1": {
+ "techniques": [
+ "H44"
+ ]
+ },
+ "1.3.1": {
+ "techniques": [
+ "H44",
+ "F68"
+ ]
+ },
+ "2.1.1": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "2.1.3": {
+ "techniques": [
+ "H91"
+ ]
+ },
+ "3.3.2": {
+ "techniques": [
+ "H44"
+ ]
+ },
+ "4.1.2": {
+ "techniques": [
+ "H44",
+ "H91"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "label"
+ ],
+ "options": {
+ "selector": "textarea"
+ }
+ },
+ "textareaLabelPositionedClose": {
+ "type": "labelProximity",
+ "testability": 0.5,
+ "title": {
+ "de": "Alle \"textarea\"-Elemente sollten ein dazugehöriges Label haben",
+ "en": "All textareas should have a label that is close to it",
+ "nl": "Alle \"textarea\"-elementen moeten een label hebben dat dicht bij het element staat",
+ "pt-br": "Todas as textareas devem ter um rótulo que está próximo a ele"
+ },
+ "description": {
+ "de": "Alle textarea-Elemente sollten ein dazugehöriges label-Element haben, das in der Nähe positioniert ist.",
+ "en": "All textarea elements should have a corresponding label element that is close in proximity.",
+ "nl": "Alle \"textarea\"-elementen moeten een bijbehorend label hebben dat dicht bij het element staat.",
+ "pt-br": "Todos os elementos textarea devem ter um elemento label correspondente próximo à proximidade."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "labelProximity"
+ ],
+ "options": {
+ "selector": "textarea"
+ }
+ },
+ "videoProvidesCaptions": {
+ "type": "selector",
+ "testability": 0.5,
+ "title": {
+ "de": "Alle Video-Tags sollten Untertitel bereitstellen",
+ "en": "All video tags must provide captions",
+ "nl": "Alle video tags moeten bijschriften bieden",
+ "pt-br": "Todas as tags de vídeo devem fornecer legendas"
+ },
+ "description": {
+ "de": "Alle HTML5-Video-Tags müssen Untertitel bereitstellen",
+ "en": "All HTML5 video tags must provide captions.",
+ "nl": "Alle HTML5 video tags moeten bijschriften bieden.",
+ "pt-br": "Todas as tags de vídeo HTML5 devem fornecer legendas."
+ },
+ "guidelines": {
+ "508": [
+ "b",
+ "b"
+ ],
+ "wcag": {
+ "1.2.2": {
+ "techniques": [
+ "G87"
+ ]
+ },
+ "1.2.4": {
+ "techniques": [
+ "G87"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "media",
+ "content"
+ ],
+ "options": {
+ "selector": "video"
+ }
+ },
+ "videosEmbeddedOrLinkedNeedCaptions": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Alle verknüpften oder eingebettenen Videos benötigen Untertitel",
+ "en": "All linked or embedded videos need captions",
+ "nl": "Alle gekoppelde of ingebedde video's moeten bijschriften hebben",
+ "pt-br": "Todos os vídeos vinculados ou incorporados precisam de legendas"
+ },
+ "description": {
+ "de": "Jedes gehostete, verknüpfte oder eingebettete Video muss Untertitel haben",
+ "en": "Any video hosted or otherwise which is linked or embedded must have a caption.",
+ "nl": "Elke video die is gekoppeld of ingebed in content moet een bijschrift hebben.",
+ "pt-br": "Qualquer vídeo hospedado ou de outra forma que esteja ligado ou incorporado deve ter uma legenda."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.2.2": {
+ "techniques": [
+ "G87"
+ ]
+ },
+ "1.2.4": {
+ "techniques": [
+ "G87"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "media",
+ "content"
+ ],
+ "components": [
+ "video",
+ "language"
+ ],
+ "callback": "videosEmbeddedOrLinkedNeedCaptions"
+ },
+ "whiteSpaceInWord": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Leerzeichen sollten nicht innerhalb eines Wortes verwendet werden.",
+ "en": "Whitespace should not be used between characters in a word",
+ "nl": "Zet geen witruimte tussen letters in een woord",
+ "pt-br": "Espaço em branco não deve ser usado entre caracteres em uma palavra"
+ },
+ "description": {
+ "de": "Die Verwendung von zusätzlichen Leerzeichen in einem Word verursacht für Bildschirmleseprogrammen Probleme bei der Interpretation des Wortes. Verwenden Sie stattdessen die CSS-Eigenschaft \"letter-spacing\".",
+ "en": "Using extra whitespace between letters in a word causes screen readers to not interpret the word correctly, use the letter-spacing CSS property instead.",
+ "nl": "Het gebruik van witruimte tussen de letters van een woord, zorgen dat schermlezers het woord niet volledig kunnen lezen. Gebruik in plaats hiervan css om de ruimte tussen letters te bepalen.",
+ "pt-br": "Usando espaço em branco extra entre as letras em uma palavra faz com que os leitores de tela não interpretem a palavra corretamente, use a propriedade CSS \"letter-spacing\" em vez disso."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.2": {
+ "techniques": [
+ "F32",
+ "C8"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "content"
+ ],
+ "callback": "whiteSpaceInWord"
+ },
+ "whiteSpaceNotUsedForFormatting": {
+ "type": "custom",
+ "testability": 0.5,
+ "title": {
+ "de": "Leerzeichen sollten nicht für die Informationsvermittlung verwendet werden",
+ "en": "Whitespace should not be used for conveying information",
+ "nl": "Gebruik geen witruimte om informatie over te brengen",
+ "pt-br": "Espaço em branco não deve ser usado para transmitir informações"
+ },
+ "description": {
+ "de": "Leerzeichen oder Tabulatoren werden von Assistenztechnologien nicht vorgelesen und sollten daher nicht zur Vermittlung von Informationen genutzt werden",
+ "en": "Spaces or tabs are not read by assistive technology and should not be used to convey meaning.",
+ "nl": "Spaties of tabs worden niet voorgelezen door hulpprogramma's en moeten niet worden gebruikt om betekenis over te dragen.",
+ "pt-br": "Espaços ou abas não são lidos por tecnologia assistiva e não devem ser usados para transmitir significado."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.2": {
+ "techniques": [
+ "G57"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "content"
+ ],
+ "callback": "whiteSpaceNotUsedForFormatting"
+ },
+ "doNotUseGraphicalSymbolToConveyInformation": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Verwendung von grafischen Symoblen zur Vermittlung von Informationen",
+ "en": "Using a graphical symbol alone to convey information",
+ "nl": "Gebruik van alleen een grafisch symbool om informatie over te brengen",
+ "pt-br": "Usando apenas um símbolo gráfico para transmitir informações"
+ },
+ "description": {
+ "de": "Das Ziel dieser Technik ist es zu zeigen, wie grafische Symbole die Vermittlung von Informationen erschweren. Ein grafisches Symbol kann eine Grafik oder ein Piktorgram oder eine Glyphe sein, das Informationen nonverbal vermittelt. Beispiele dafür sind Symbole bestehende aus einem durchgestrichenen Kreis, ein Smiley oder ein Häkchen oder Pfeil. Benutzer von Assistenztechnologien haben ggf. Schwierigkeiten die Bedeutung des Symbols zu erkennen. Wenn ein graphisches Symbol verwendet wird, um Informationen zu übermitteln , stellen eine alternative Technologie oder einen anderen Mechanismus bereit, um die Bedeutung darzustellen. Verwenden Sie zum Beispiel ein Bild mit einem Alternativetext anstelle der Glyphe.",
+ "en": "The objective of this technique is to show how using a graphical symbol to convey information can make content difficult to comprehend. A graphical symbol may be an image, an image of text or a pictorial or decorative character symbol (glyph) which imparts information nonverbally. Examples of graphical symbols include an image of a red circle with a line through it, a smiley face, or a glyph which represents a check mark, arrow, or other symbol but is not the character with that meaning. Assistive technology users may have difficulty determining the meaning of the graphical symbol. If a graphical symbol is used to convey information, provide an alternative using features of the technology or use a different mechanism that can be marked with an alternative to represent the graphical symbol. For example, an image with a text alternative can be used instead of the glyph.",
+ "nl": "Het doel van deze techniek is te laten zien dat content moeilijker begrepen kan worden wanneer een grafisch symbool wordt gebruikt om informatie over te brengen. Een grafisch symbool kan een afbeelding, een afbeelding van tekst of een pictogram of decoratief teken zijn (glyph) dat non-verbaal informatie overbrengt. Voorbeelden hiervan zijn een rode cirkel met een lijn erdoorheen, een smiley of een vinkje, pijl of ander symbool dat niet noodzakelijkerwijs een duidelijke betekenis heeft. Gebruikers van hulpprogramma's hebben vaak moeite om de bedoeling van een grafisch symbool te duiden. Als een grafisch symbool gebruikt wordt om informatie over te brengen, biedt dan ook een (tekstueel) alternatief.",
+ "pt-br": "O objetivo desta técnica é mostrar como usar um símbolo gráfico para transmitir informações. Um símbolo gráfico pode ser uma imagem, uma imagem de texto ou um símbolo de carácter pictórico ou decorativo (glifo) que transmite informação não verbalmente. Exemplos de símbolos gráficos incluem uma imagem de um círculo vermelho com uma linha através dele, um rosto sorridente ou um glifo que representa uma marca de seleção, seta ou outro símbolo, mas não é o personagem com esse significado. Os usuários de tecnologia assistiva podem ter dificuldade em determinar o significado do símbolo gráfico. Se um símbolo gráfico é usado para transmitir informações, fornecer uma alternativa usando recursos da tecnologia ou usar um mecanismo diferente que pode ser marcado com uma alternativa para representar o símbolo gráfico. Por exemplo, uma imagem com uma alternativa de texto pode ser usada em vez do glifo."
+ },
+ "guidelines": {
+ "wcag": {
+ "1.3.3": {
+ "techniques": [
+ "F26"
+ ]
+ }
+ }
+ },
+ "tags": [
+ "link",
+ "content"
+ ],
+ "callback": "doNotUseGraphicalSymbolToConveyInformation"
+ },
+ "linkDoesNotChangeContextOnFocus": {
+ "type": "event",
+ "testability": 1,
+ "title": {
+ "de": "Verknüpfungen dürfen das \"onfocus\"-Attribut nicht verwenden",
+ "en": "Link elements must not contain an \"onfocus\" attribute",
+ "nl": "Link-elementen bevatten geen \"onfocus\"-attribuut",
+ "pt-br": "Os elementos de link não devem conter um atributo \"onfocus\""
+ },
+ "description": {
+ "de": "Aktionen wie \"onfocus\" entziehen dem Benutzer die Kontrolle beim Versuch auf der Seite zu navigieren. \"onfocus\"-Attribute für Dinge wie Auswahl-Listenmenüs sollten durch Drop-Downs und eine Schaltfläche zur Initiierung der Aktion ersetzt werden.",
+ "en": "Actions like \"onfocus\" can take control away from users who are trying to navigate the page. Using an \"onfocus\" attribute for things like links should be replaced with css.",
+ "nl": "Acties zoals \"onfocus\" kunnen de controle ontnemen van gebruikers die op een pagina proberen te navigeren. Het gebruik van een \"onfocus\"-attribuut voor zaken als links moet worden vervangen door middel van css.",
+ "pt-br": "Ações como \"onfocus\" podem tirar o controle dos usuários que estão tentando navegar na página. Usando um atributo \"onfocus\" para coisas como links deve ser substituído por css."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "event",
+ "hasEventListener"
+ ],
+ "options": {
+ "searchEvent": "onfocus",
+ "selector": "a"
+ }
+ },
+ "buttonDoesNotChangeContextOnFocus": {
+ "type": "event",
+ "testability": 1,
+ "title": {
+ "de": "Schaltflächen dürfen das \"onfocus\"-Attribut nicht verwenden",
+ "en": "Buttons must not contain an \"onfocus\" attribute",
+ "nl": "Knoppen bevatten geen \"onfocus\"-attribuut",
+ "pt-br": "Os botões não devem conter um atributo \"onfocus\""
+ },
+ "description": {
+ "de": "Aktionen wie \"onfocus\" entziehen dem Benutzer die Kontrolle beim Versuch auf der Seite zu navigieren. \"onfocus\"-Attribute für Dinge wie Auswahl-Listenmenüs sollten durch Drop-Downs und eine Schaltfläche zur Initiierung der Aktion ersetzt werden.",
+ "en": "Actions like \"onfocus\" can take control away from users who are trying to navigate the page. Using an \"onfocus\" attribute for things like buttons should be replaced with css.",
+ "nl": "Acties zoals \"onfocus\" kunnen de controle ontnemen van gebruikers die op een pagina proberen te navigeren. Het gebruik van een \"onfocus\"-attribuut voor zaken als knoppen moet worden vervangen door middel van css.",
+ "pt-br": "Ações como \"onfocus\" podem tirar o controle dos usuários que estão tentando navegar na página. Usando um atributo \"onfocus\" para coisas como botões deve ser substituído por css."
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "content"
+ ],
+ "components": [
+ "event",
+ "hasEventListener"
+ ],
+ "options": {
+ "searchEvent": "onfocus",
+ "selector": "input[type=checkbox],input[type=text],button"
+ }
+ },
+ "KINGStrongList": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Verwenden Sie strong nur in Listen",
+ "en": "Use strong in lists only",
+ "nl": "",
+ "pt-br": "Use strong apenas nas listas"
+ },
+ "description": {
+ "de": "strong ist nur in li-Elementen erlaubt",
+ "en": "STRONG only allowed when parent element is LI.",
+ "nl": "",
+ "pt-br": " strong é permitida apenas em elementos li code>"
+ },
+ "guidelines": [],
+ "tags": [
+ "KING"
+ ],
+ "callback": "KINGStrongList"
+ },
+ "KINGUseLongDateFormat": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Verwenden Sie lange Datumsformate",
+ "en": "Use a long date format",
+ "nl": "",
+ "pt-br": "Use um formato de data longo"
+ },
+ "description": {
+ "de": "Kurze Datumsformate können Benutzer verwirren. Benutzen Sie immer Monatsnamen, bspw. 14 März 2020",
+ "en": "Short date formats might confuse users, Always use the month name: 20 May 2014.",
+ "nl": "",
+ "pt-br": "Os formatos de data curtos podem confundir os usuários, Usar sempre o nome do mês: 20 de maio de 2014."
+ },
+ "guidelines": [],
+ "tags": [
+ "KING"
+ ],
+ "callback": "KINGUseLongDateFormat"
+ },
+ "KINGUsePercentageWithSymbol": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Verwenden Sie ein Symbol in einem Prozentsatz",
+ "en": "Use a symbol within a percentage",
+ "nl": "",
+ "pt-br": "Use um símbolo dentro de uma porcentagem"
+ },
+ "description": {
+ "de": "",
+ "en": "",
+ "nl": "",
+ "pt-br": ""
+ },
+ "guidelines": [],
+ "tags": [
+ "KING"
+ ],
+ "callback": "KINGUsePercentageWithSymbol"
+ },
+ "KINGUseCurrencyAsSymbol": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Verwenden Sie ein Symbol für Währungen",
+ "en": "Use a symbol for a currency",
+ "nl": "",
+ "pt-br": "Use um símbolo para moedas"
+ },
+ "description": {
+ "de": "Verwenden Sie nur Symbol und Währungsnamen anstelle von allgemeinen Namen wie € oder EUR.",
+ "en": "Only use symbol and currency name instead of common name such as € or EUR.",
+ "nl": "",
+ "pt-br": "Use apenas símbolo e nome de moeda em vez de nome comum, como € ou EUR."
+ },
+ "guidelines": [],
+ "tags": [
+ "KING"
+ ],
+ "callback": "KINGUseCurrencyAsSymbol"
+ },
+ "videoMayBePresent": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Video oder Object verwendet eine Verknüpfung die auf eine Datei mit einer Video-Dateiendung zeigt",
+ "en": "Video or object uses a link that points to a file with a video extension",
+ "nl": "Video of object met een link naar een bestand met een video extensie",
+ "pt-br": "Vídeo ou objeto usa um link que aponta para um arquivo com uma extensão de vídeo"
+ },
+ "description": {
+ "de": "",
+ "en": "",
+ "nl": "",
+ "pt-br": ""
+ },
+ "guidelines": [],
+ "tags": [
+ "link",
+ "video"
+ ],
+ "callback": "videoMayBePresent"
+ },
+ "audioMayBePresent": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Audio oder Object verwendet eine Verknüpfung die auf eine Datei mit einer Video-Dateiendung zeigt",
+ "en": "Audio or object uses a link that points to a file with a video extension",
+ "nl": "Audio of object met een link naar een bestand met een video extensie",
+ "pt-br": "Áudio ou objetos usam um link que aponta para um arquivo com uma extensão de vídeo"
+ },
+ "description": {
+ "de": "",
+ "en": "",
+ "nl": "",
+ "pt-br": ""
+ },
+ "guidelines": [],
+ "tags": [
+ "link",
+ "audio"
+ ],
+ "callback": "audioMayBePresent"
+ },
+ "animatedGifMayBePresent": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Prüfen Sie, ob GIF-Dateien in der Seite verwendet werden. Prüfen Sie, ob die GIF-Dateien mehr als einen Frame enthalten",
+ "en": "Test if a .gif is used on the page. Test if the .gif contains more then one frame",
+ "nl": "Test of een .gif afbeelding gebruikt is op de pagina. Test of het .gif bestand uit meer dan één frame bestaat",
+ "pt-br": "Teste se um .gif é usado na página. Teste se o .gif contém mais de um quadro"
+ },
+ "description": {
+ "de": "",
+ "en": "",
+ "nl": "",
+ "pt-br": ""
+ },
+ "guidelines": [],
+ "tags": [
+ "link",
+ "gif"
+ ],
+ "callback": "animatedGifMayBePresent"
+ },
+ "userInputMayBeRequired": {
+ "type": "custom",
+ "testability": 1,
+ "title": {
+ "de": "Prüfen Sie, ob eine Benutzereingabe notwendig ist",
+ "en": "Test if user input is required",
+ "nl": "Test of er invoervelden zijn",
+ "pt-br": "Teste se a entrada do usuário é obrigatória"
+ },
+ "description": {
+ "de": "",
+ "en": "",
+ "nl": "",
+ "pt-br": ""
+ },
+ "guidelines": [],
+ "tags": [
+ "form",
+ "input"
+ ],
+ "callback": "userInputMayBeRequired"
+ }
+}
diff --git a/plugins/ckeditor/a11ychecker/libs/quail/tests.min.json b/plugins/ckeditor/a11ychecker/libs/quail/tests.min.json
new file mode 100644
index 0000000..19cca04
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/libs/quail/tests.min.json
@@ -0,0 +1 @@
+{"aAdjacentWithSameResourceShouldBeCombined":{"type":"custom","testability":1,"title":{"en":"Adjacent links that point to the same location should be merged","nl":"Voeg naast elkaar gelegen links die naar dezelfde locatie verwijzen samen"},"description":{"en":"Because many users of screen readers use links to navigate the page, providing two links right next to each other that point to the same location can be confusing. Try combining the links.","nl":"Veel gebruikers van schermlezers gebruiken links om op de pagina te navigeren. Voor hen zijn naast elkaar gelegen links die naar dezelfde locatie verwijzen verwarrend. Probeer de links samen te voegen."},"guidelines":{"wcag":{"2.4.4":{"techniques":["H2","F89"]},"2.4.9":{"techniques":["F89"]},"4.1.2":{"techniques":["F89"]}}},"tags":["link","content"],"callback":"aAdjacentWithSameResourceShouldBeCombined"},"aImgAltNotRepetitive":{"type":"custom","testability":1,"title":{"en":"Alternative text for image in a link should not repeat the text in the link","nl":"Als een link een afbeelding bevat, moet het \"alt\"-attribuut niet dezelfde tekst bevatten als de linktekst"},"description":{"en":"Images within a link should not have an alt attribute that simply repeats the text found in the link. This will cause screen readers to simply repeat the text twice.","nl":"Als een link een afbeelding bevat, moet deze afbeelding een andere tekst in het alt-attribuut hebben dan de tekst in de link. Hiermee voorkom je dat een schermlezer dezelfde tekst twee keer voorleest."},"guidelines":{"wcag":{"1.1.1":{"techniques":["H30"]},"2.4.4":{"techniques":["H30"]},"2.4.9":{"techniques":["H30"]}}},"tags":["link","content"],"callback":"aImgAltNotRepetitive"},"aInPHasADistinctStyle":{"type":"custom","testability":1,"title":{"en":"Links should be have a distinct style inside a p tag","nl":"Links moeten een afwijkende stijl hebben binnen een paragraaf"},"description":{"en":"","nl":""},"guidelines":[],"tags":["link","content"],"callback":"aInPHasADistinctStyle"},"aLinkTextDoesNotBeginWithRedundantWord":{"type":"custom","testability":0,"title":{"en":"Link text should not begin with redundant text","nl":"Laat linkteksten niet beginnen met overbodige tekst"},"description":{"en":"Link text should not begin with redundant words or phrases like \"link\".","nl":"Laat linkteksten niet beginnen met overbodige woorden of woordcombinaties als \"link\" of \"klik hier\"."},"guidelines":{"wcag":{"2.4.9":{"techniques":["F84"]}}},"tags":["link","content"],"strings":["redundant.link"],"callback":"aLinkTextDoesNotBeginWithRedundantWord"},"aLinksAreSeparatedByPrintableCharacters":{"type":"custom","testability":1,"title":{"en":"Lists of links should be seperated by printable characters","nl":"Lijsten met links moeten gescheiden worden door afdrukbare tekens"},"description":{"en":"If a list of links is provided within the same element, those links should be seperated by a non-linked, printable character. Structures like lists are not included in this.","nl":"Als een rij met links binnen eenzelfde element staat, moeten de links gescheiden zijn door een niet-gelinkt, afdrukbaar teken. Dit geldt niet voor een gestructureerde lijst."},"guidelines":[],"tags":["link","content"],"callback":"aLinksAreSeparatedByPrintableCharacters"},"aLinksDontOpenNewWindow":{"type":"custom","testability":1,"title":{"en":"Links should not open a new window without warning","nl":"Met links open je geen nieuw scherm zonder melding"},"description":{"en":"Links which open a new window using the \"target\" attribute should warn users.","nl":"Voordat links door middel van het \"target\"-attribuut een nieuw scherm openen moet de gebruiker een melding hiervan krijgen."},"guidelines":{"wcag":{"3.2.5":{"techniques":["H83","SCR24"]}}},"tags":["link","content"],"strings":["newWindow"],"callback":"aLinksDontOpenNewWindow"},"aLinksNotSeparatedBySymbols":{"type":"custom","testability":1,"title":{"en":"Links should not be separated by symbols alone","nl":"Links mogen niet alleen door symbolen gescheidn worden"},"description":{"en":"Since symbols are either not read, or can be confusing when using a screen reader, do not separate links with un-readable symbols.","nl":"Symbolen worden niet voorgelezen of zijn verwarrend bij het gebruik van een schermlezer. Gebruik geen onleesbare symbolen om links van elkaar te scheiden."},"guidelines":[],"tags":["link","content"],"callback":"aLinksNotSeparatedBySymbols"},"aLinksToMultiMediaRequireTranscript":{"type":"selector","testability":0,"title":{"en":"Any links to a multimedia file should also include a link to a transcript","nl":"Elke link naar een multimediabestand moet ook een link bevatten naar een transcriptie"},"description":{"en":"Links to a multimedia file should be followed by a link to a transcript of the file.","nl":"Links naar een multimediabestand moeten worden gevolgd door een link naar de transcriptie van dit bestand."},"guidelines":{"508":["c"],"wcag":{"1.1.1":{"techniques":["G74"]}}},"tags":["link","media","content"],"options":{"selector":"a[href$='.wmv'], a[href$='.mpg'], a[href$='.mov'], a[href$='.ram'], a[href$='.aif']"}},"aLinksToSoundFilesNeedTranscripts":{"type":"selector","testability":0,"title":{"en":"Any links to a sound file should also include a link to a transcript","nl":"Elke link naar een geluidsbestand moet ook een link bevatten naar een transcriptie"},"description":{"en":"Links to a sound file should be followed by a link to a transcript of the file.","nl":"Links naar een geluidsbestand moeten worden gevolgd door een link naar de transcriptie van dit bestand."},"guidelines":{"508":["c"],"wcag":{"1.1.1":{"techniques":["G74"]}}},"tags":["link","media","content"],"options":{"selector":"a[href$='.wav'], a[href$='.snd'], a[href$='.mp3'], a[href$='.iff'], a[href$='.svx'], a[href$='.sam'], a[href$='.smp'], a[href$='.vce'], a[href$='.vox'], a[href$='.pcm'], a[href$='.aif']"}},"aLinkWithNonText":{"type":"custom","title":{"en":"Links with only non-text content should be readable","nl":"Links zonder tekstuele content moeten leesbaar zijn"},"description":{"en":"If a link contains only non-text content like an image, that content must be readable by assistive technology.","nl":"Als een link alleen maar niet-tekstuele content bevat zoals een afbeelding, moet deze content leesbaar worden gemaakt door middel van daarvoor geschikte technologie."},"guidelines":{"wcag":{"2.4.4":{"techniques":["H2","F89"]},"2.4.9":{"techniques":["F89"]},"4.1.2":{"techniques":["F89"]}}},"tags":["link","content"],"callback":"aLinkWithNonText"},"aMultimediaTextAlternative":{"type":"selector","testability":0,"guidelines":[],"tags":["link","media","content"],"options":{"selector":"a[href$='.wmv'], a[href$='.wav'], a[href$='.mpg'], a[href$='.mov'], a[href$='.ram'], a[href$='.aif']"}},"aMustContainText":{"type":"custom","testability":1,"title":{"en":"Links should contain text","nl":"Links moeten tekst bevatten"},"description":{"en":"Because many users of screen-readers use links to navigate the page, providing links with no text (or with images that have empty \"alt\" attributes and no other readable text) hinders these users.","nl":"Veel gebruikers van schermlezers gebruiken links om op de pagina te navigeren. Links zonder tekst (of met afbeeldingen die een leeg \"alt\"-attribuut hebben en geen andere leesbare tekst) hinderen deze gebruikers."},"guidelines":{"wcag":{"1.1.1":{"techniques":["H30"]},"2.4.4":{"techniques":["H30"]},"2.4.9":{"techniques":["H30"]},"4.1.2":{"techniques":["H91"]}}},"tags":["link","content"],"callback":"aMustContainText"},"aMustHaveTitle":{"type":"selector","testability":1,"title":{"en":"All links must have a \"title\" attribute","nl":"Alle links moeten een \"title\"-attribuut hebben"},"description":{"en":"Every link must have a \"title\" attribute.","nl":"Zorg ervoor dat elke link is voorzien van een \"title\"-attribuut."},"guidelines":[],"tags":["link","content"],"options":{"selector":"a:not(a[title])"}},"aMustNotHaveJavascriptHref":{"type":"selector","testability":1,"title":{"en":"Links should not use \"javascript\" in their location","nl":"Links moeten geen \"javascript\" in hun locatie hebben"},"description":{"en":"Anchor (a. elements may not use the \"javascript\" protocol in their \"href\" attributes.","nl":"Anchor(a.-elementen mogen geen \"javascript\"protocol in hun \"href\"-attributen hebben staan."},"guidelines":[],"tags":["link","content"],"options":{"selector":"a[href^='javascript:']"}},"aSuspiciousLinkText":{"type":"custom","testability":1,"title":{"en":"Link text should be useful","nl":"Linkteksten moeten bruikbaar en betekenisvol zijn"},"description":{"en":"Because many users of screen-readers use links to navigate the page, providing links with text that simply read \"click here\" gives no hint of the function of the link.","nl":"Veel gebruikers van schermlezers gebruiken links om op de pagina te navigeren. Links met de tekst \"klik hier\" zijn voor deze gebruikers niet betekenisvol en niet bruikbaar."},"guidelines":{"wcag":{"1.1.1":{"techniques":["H30"]},"2.4.4":{"techniques":["H30"]},"2.4.9":{"techniques":["H30"]}}},"tags":["link","content"],"strings":["suspiciousLinks"],"callback":"aSuspiciousLinkText"},"aTitleDescribesDestination":{"type":"selector","testability":0,"title":{"en":"The title attribute of all source a (anchor) elements describes the link destination.","nl":"Het titel-attribuut van alle source a (anchor)-elementen beschrijven de bestemming van de link"},"description":{"en":"Every link must have a \"title\" attribute which describes the purpose or destination of the link.","nl":"Elke link moet een \"title\"-attribuut hebben waarin het doel of de bestemming van de link wordt beschreven."},"guidelines":{"wcag":{"2.4.9":{"techniques":["H33","H25"]}}},"tags":["link","content"],"options":{"selector":"a[title]"}},"addressForAuthor":{"type":"selector","testability":1,"title":{"en":"The document should contain an address for the author","nl":"Het document moet een adres voor de auteur bevatten"},"description":{"en":"Documents should provide a valid email address within an address element.","nl":"Documenten moeten een e-mailadres bevatten binnen het address-element."},"guidelines":[],"tags":["document"],"options":{"selector":"body:not(body:has(address))"}},"addressForAuthorMustBeValid":{"type":"selector","testability":0.5,"title":{"en":"The document should contain a valid email address for the author","nl":"Het document moet een geldig e-mailadres bevatten voor de auteur"},"description":{"en":"Documents should provide a valid email address within an address element.","nl":"Documenten moeten een geldig e-mailadres bevatten binnen het address element."},"guidelines":[],"tags":["document"],"options":{"selector":"address"}},"appletContainsTextEquivalent":{"type":"custom","testability":1,"title":{"en":"All applets should contain the same content within the body of the applet","nl":"Alle applets moeten dezelfde content bevatten in de body van de applet"},"description":{"en":"Applets should contain their text equivalents or description within the applet tag itself.","nl":"Applets moeten hun tekstuele equivalent of beschrijving bevatten in de applet tag."},"guidelines":{"508":["m"],"wcag":{"1.1.1":{"techniques":["G74","H35"]}}},"tags":["objects","applet","content"],"callback":"appletContainsTextEquivalent"},"appletContainsTextEquivalentInAlt":{"type":"placeholder","testability":0.5,"title":{"en":"All applets should contain a text equivalent in the \"alt\" attribute","nl":"Alle applets moeten een tekstuele equivalent bevatten in het \"alt\"-attribuut"},"description":{"en":"Applets should contain their text equivalents or description in an \"alt\" attribute.","nl":"Applets moeten hun tekstuele equivalent of beschrijving bevatten in een \"alt\"-attribuut."},"guidelines":{"508":["m"],"wcag":{"1.1.1":{"techniques":["G74","H35"]}}},"tags":["objects","applet","content"],"components":["placeholder"],"options":{"attribute":"alt","empty":true,"selector":"applet"}},"appletProvidesMechanismToReturnToParent":{"type":"selector","testability":0,"title":{"en":"All applets should provide a way for keyboard users to escape","nl":"Alle applets moeten door toetsenbordgebruikers kunnen worden verlaten"},"description":{"en":"Ensure that a user who has only a keyboard as an input device can escape an applet element. This requires manual confirmation.","nl":"Zorg ervoor dat gebruikers die alleen het toetsenbord gebruiken als bediening een applet-element kunnen verlaten. Hiervoor is handmatige bevestiging nodig."},"guidelines":[],"tags":["objects","applet","content"],"options":{"selector":"applet"}},"appletTextEquivalentsGetUpdated":{"type":"selector","testability":0,"guidelines":{"508":["m"],"wcag":{"1.1.1":{"techniques":["G74","H35"]}}},"tags":["objects","applet","content"],"options":{"selector":"applet"}},"appletUIMustBeAccessible":{"type":"selector","testability":0,"title":{"en":"Any user interface in an applet must be accessible","nl":"Elke user interface in een applet moet toegankelijk zijn"},"description":{"en":"Applet content should be assessed for accessibility.","nl":"Content in een applet moet getoetst worden op toegankelijkheid."},"guidelines":{"508":["m"],"wcag":{"1.1.1":{"techniques":["G74","H35"]}}},"tags":["objects","applet","content"],"options":{"selector":"applet"}},"appletsDoNotFlicker":{"type":"selector","testability":0,"title":{"en":"All applets do not flicker","nl":"Applets knipperen of flitsen niet"},"description":{"en":"Applets should not flicker.","nl":"Geen enkele applet mag knipperen of flitsen."},"guidelines":{"508":["j"],"wcag":{"2.2.2":{"techniques":["F7"]}}},"tags":["objects","applet","content"],"options":{"selector":"applet"}},"appletsDonotUseColorAlone":{"type":"selector","testability":0,"title":{"en":"Applets should not use color alone to communicate content","nl":"Applets mogen niet alleen kleur gebruiken om een boodschap over te brengen"},"description":{"en":"Applets should contain content that makes sense without color and is accessible to users who are color blind.","nl":"Applets moeten content bevatten die ook bruikbaar is zonder kleur en die toegankelijk is voor gebruikers met kleurenblindheid."},"guidelines":{"508":["c"]},"tags":["objects","applet","content"],"options":{"selector":"applet"}},"areaAltIdentifiesDestination":{"type":"selector","testability":0,"title":{"en":"All \"area\" elements must have an \"alt\" attribute which describes the link destination","nl":"Alle \"area\"-elementen moeten een \"alt\"-attribuut hebben die de bestemming van de link beschrijft"},"description":{"en":"All area elements within a map must have an \"alt\" attribute","nl":"Alle area-elementen binnen een map moeten een \"alt\"-attribuut hebben."},"guidelines":{"wcag":{"1.1.1":{"techniques":["G74"]}}},"tags":["objects","applet","content"],"options":{"selector":"area[alt]"}},"areaAltRefersToText":{"type":"selector","testability":0,"title":{"en":"Alt text for \"area\" elements should replicate the text found in the image","nl":"Alt-tekst voor \"area\"-elementen moeten de tekst bevatten zoals die ook in de afbeelding staat"},"description":{"en":"If an image is being used as a map, and an area encompasses text within the image, then the \"alt\" attribute of that area element should be the same as the text found in the image.","nl":"Als een afbeelding als kaart wordt gebruikt, en een area bevat tekst binnen de afbeelding, dan moet het \"alt\"-attribuut van dat area-element hetzelfde zijn als de tekst die in de afbeelding staat."},"guidelines":[],"tags":["imagemap","content"],"options":{"selector":"area"}},"areaDontOpenNewWindow":{"type":"selector","testability":1,"title":{"en":"No \"area\" elements should open a new window without warning","nl":"\"area\"-elementen mogen geen nieuw scherm openen zonder melding"},"description":{"en":"No area elements should open a new window without warning.","nl":"area-elementen mogen geen nieuw scherm openen zonder dat de gebruiker hiervan een melding krijgt."},"guidelines":[],"tags":["imagemap","content"],"options":{"selector":"area[target='new window'], area[target=_new], area[target=_blank], area[target=_blank]"}},"areaHasAltValue":{"type":"selector","testability":1,"title":{"en":"All \"area\" elements must have an \"alt\" attribute","nl":"Alle \"area\"-elementen moeten een \"alt\"-attribuut hebben"},"description":{"en":"All area elements within a map must have an \"alt\" attribute.","nl":"Alle area-elementen binnen een map moeten een \"alt\"-attribuut hebben."},"guidelines":{"wcag":{"1.1.1":{"techniques":["F65","G74","H24"]},"1.4.3":{"techniques":["G145"]}}},"tags":["imagemap","content"],"options":{"selector":"area","test":":not(area[alt])"}},"areaLinksToSoundFile":{"type":"selector","testability":1,"title":{"en":"All \"area\" elements which link to a sound file should also provide a link to a transcript","nl":"Alle \"area\"-elementen met een link naar een geluidsbestand moeten ook een link bevatten naar een transcriptie"},"description":{"en":"All area elements which link to a sound file should have a text transcript.","nl":"Alle \"area\"-elementen met een link naar een geluidsbestand moeten een transcriptie hebben in tekst."},"guidelines":{"wcag":{"1.1.1":{"techniques":["G74"]}}},"tags":["imagemap","media","content"],"options":{"selector":"area[href$=wav], area[href$=snd], area[href$=mp3], area[href$=iff], area[href$=svx], area[href$=sam], area[href$=smp], area[href$=vce], area[href$=vox], area[href$=pcm], area[href$=aif]"}},"ariaOrphanedContent":{"type":"custom","testability":1,"title":{"en":"Pages using ARIA roles should not have orphaned content","nl":"Pagina's die ARIA-rollen gebruiken mogen geen verweesde content hebben"},"description":{"en":"If a page makes use of ARIA roles, then there should not be any content on the page which is not within an element that exposes a role, as it could cause that content to be rendreed inaccessible to users with screen readers.","nl":"Als een pagina gebruik maakt van ARIA-rollen, mag er geen content op de pagina staan buiten een element dat een rol vertegenwoordigt. In dat geval kan het zijn dat deze content niet toegankelijk is voor gebruikers van schermlezers."},"guidelines":[],"tags":["aria","content"],"callback":"ariaOrphanedContent"},"basefontIsNotUsed":{"type":"selector","testability":1,"title":{"en":"Basefont should not be used","nl":"Basefont moet niet worden gebruikt"},"description":{"en":"The basefont tag is deprecated and should not be used. Investigate using stylesheets instead.","nl":"The basefont-tag is afgekeurd en moet niet worden gebruikt. Gebruik in plaats hiervan stylesheets."},"guidelines":[],"tags":["document","deprecated"],"options":{"selector":"basefont"}},"blinkIsNotUsed":{"type":"selector","testability":1,"title":{"en":"The \"blink\" tag should not be used","nl":"De \"blink\"-tag moet niet worden gebruikt"},"description":{"en":"The blink tag should not be used. Ever.","nl":"Het is nooit toegestaan om de \"blink\"-tag te gebruiken."},"guidelines":{"wcag":{"2.2.2":{"techniques":["F47"]}}},"tags":["deprecated","content"],"options":{"selector":"blink"}},"blockquoteNotUsedForIndentation":{"type":"selector","testability":0.5,"title":{"en":"The block quote should not be used just for indentation","nl":"De \"blockquote\"-tag mag niet gebruikt worden om in te springen"},"description":{"en":"Blockquote tags are for longer quotes, and should not be used to indent text.","nl":"Blockquotes zijn bedoeld voor lange stukken geciteerde tekst, en niet om tekst te laten inspringen."},"guidelines":{"wcag":{"1.3.1":{"techniques":["H49"]}}},"tags":["blockquote","content"],"options":{"selector":"blockquote:not(blockquote[cite])"}},"blockquoteUseForQuotations":{"type":"custom","testability":0.5,"title":{"en":"If long quotes are in the document, use the \"blockquote\" element to mark them","nl":"Gebruik voor lange citaten in het document het \"blockquote\"-element"},"description":{"en":"If there is a paragraph or more of a quote, use the blockquote element to mark it as such.","nl":"Als er een hele alinea of meer alinea's zijn van geciteerde tekst, gebruik dan blockquote om deze als zodanig te markeren."},"guidelines":{"wcag":{"1.3.1":{"techniques":["H49"]}}},"tags":["blockquote","content"],"callback":"blockquoteUseForQuotations"},"boldIsNotUsed":{"type":"selector","testability":1,"title":{"en":"The \"b\" (bold) element is not used","nl":"Het \"b\"-element (bold) wordt niet gebruikt"},"description":{"en":"The b (bold) element provides no emphasis for non-sighted readers. Use the strong tag instead.","nl":"Het b-element voorziet niet in nadruk voor blinde en slechtziende gebruikers. Gebruik de strong-tag instead."},"guidelines":[],"tags":["semantics","content"],"options":{"selector":"bold"}},"buttonHasName":{"type":"placeholder","testability":1,"title":{"en":"Button should contain text","nl":"Een knop moet tekst bevatten"},"description":{"en":"Buttons should contain a text value within the element, or have a value attribute.","nl":"Knoppen moeten een tekstwaarde binnen het element hebben, of een waarde-attribuut."},"guidelines":{"wcag":{"2.1.1":{"techniques":["H91"]},"2.1.3":{"techniques":["H91"]},"4.1.2":{"techniques":["H91"]}}},"tags":["content"],"components":["placeholder"],"options":{"content":true,"empty":true,"attribute":"title","selector":"button"}},"checkboxHasLabel":{"type":"label","testability":1,"title":{"en":"All checkboxes must have a corresponding label","nl":"Alle keuzevakjes moeten een bijbehorend label hebben"},"description":{"en":"All input elements with a type of \"checkbox\" should have a corresponding label element. Screen readers often enter a \"form mode\" where only label text is read aloud to the user","nl":"Alle input-elementen met een \"keuzevakje\" moeten een bijbehorend label-element hebben. Schermlezers maken vaak gebruik van een \"formuliereninstelling\" waarbij alleen de tekst van de labels hardop aan de gebruiker wordt voorgelezen."},"guidelines":{"508":["c"],"wcag":{"1.1.1":{"techniques":["H44"]},"1.3.1":{"techniques":["H44","F68"]},"2.1.1":{"techniques":["H91"]},"2.1.3":{"techniques":["H91"]},"3.3.2":{"techniques":["H44"]},"4.1.2":{"techniques":["H44","H91"]}}},"tags":["form","content"],"components":["label"],"options":{"selector":"input[type=checkbox]"}},"checkboxLabelIsNearby":{"type":"labelProximity","testability":0.5,"title":{"en":"All \"checkbox\" input elements have a label that is close","nl":"Van alle \"keuzevakjes\" invoerelementen staat het label in de buurt"},"description":{"en":"All input elements of type \"checkbox\" must have a corresponding label that is close to the form element. Users of screen magnification or with reduced spatial skills are hampered in using a form element if the label for that element is located far away.","nl":"Alle inputelementen van het type \"keuzevakje\" moeten een bijbehorend label hebben dat dicht bij het formulierelement staat. Gebruikers die het scherm vergroten of met beperkte ruimtelijke vaardigheden kunnen een formulier niet gebruiken als het label van een veld te ver weg staat."},"guidelines":[],"tags":["form","content"],"components":["labelProximity"],"options":{"selector":"input[type=checkbox]"}},"closingTagsAreUsed":{"type":"custom","testability":1,"title":{"en":"All tags that require closing tags have closing tags","nl":"Alle tags die een afsluitende tag behoeven, hebben een afsluitende tag"},"description":{"en":"When using tags such as p, ul, or li, there must be a closing tag.","nl":"Gebruik voor tags als p, ul, of li altijd een afsluitende tag, dus /p, /ul, /li."},"guidelines":{"wcag":{"4.1.1":{"techniques":["H74"]}}},"tags":["html"],"components":["htmlSource"],"callback":"closingTagsAreUsed"},"contentPositioningShouldNotChangeMeaning":{"type":"custom","testability":0.5,"title":{"en":"Meaning should not be created through positioning","nl":"Cre�er geen betekenis door positionering"},"description":{"en":"Positioning should not be used to change the meaning of an element.","nl":"Positionering moet niet worden gebruikt om de betekenis van een element te veranderen."},"guidelines":{"wcag":{"1.3.2":{"techniques":["C6","F1","G57"]},"1.4.5":{"techniques":["C6"]},"1.4.9":{"techniques":["C6"]},"2.4.1":{"techniques":["C6"]}}},"tags":["content","structure"],"callback":"contentPositioningShouldNotChangeMeaning"},"cssDocumentMakesSenseStyleTurnedOff":{"type":"selector","testability":0,"title":{"en":"The document must be readable with styles turned off","nl":"Het document moet leesbaar zijn met stijlen uit"},"description":{"en":"With all the styles for a page turned off, the content of the page should still make sense. Try to turn styles off in the browser and see if the page content is readable and clear.","nl":"Als alle stijlen voor een pagina zijn uitgezet, moet de content van de pagina nog steeds betekenisvol zijn. Zet stijlen uit in de browser en controleer of de content op de pagina nog steeds leesbaar en duidelijk is."},"guidelines":{"wcag":{"1.3.1":{"techniques":["G140"]},"1.4.5":{"techniques":["G140"]},"1.4.9":{"techniques":["G140"]}}},"tags":["color"],"options":{"selector":"link[rel=stylesheet], stylesheet, *[style]"}},"colorFontContrast":{"type":"custom","testability":1,"title":{"en":"All elements should have appropriate color contrast","nl":"Alle elementen moeten een toepasselijk kleurcontract hebben"},"description":{"en":"For users who have color blindness, all text or other elements should have a color contrast of 5:1.","nl":"Voor gebruikers met kleurenblindheid moeten alle tekst- en andere elementen een kleurcontrast hebben van 5:1."},"guidelines":{"wcag":{"1.4.3":{"techniques":["G18"]}}},"tags":["color"],"callback":["colorFontContrast"],"options":{"algorithm":"wcag","selector":"*","gradientSampleMultiplier":3}},"colorElementBehindContrast":{"type":"custom","testability":1,"title":{"en":"All elements should have appropriate color contrast","nl":"Alle elementen moeten een toepasselijk kleurcontract hebben"},"description":{"en":"For users who have color blindness, all text or other elements should have a color contrast of 5:1.","nl":"Voor gebruikers met kleurenblindheid moeten alle tekst- en andere elementen een kleurcontrast hebben van 5:1."},"guidelines":{"wcag":{"1.4.3":{"techniques":["G18"]}}},"tags":["color"],"callback":["colorElementBehindContrast"],"options":{"algorithm":"wcag","selector":"*","gradientSampleMultiplier":3}},"colorBackgroundImageContrast":{"type":"custom","testability":1,"title":{"en":"All elements should have appropriate color contrast","nl":"Alle elementen moeten een toepasselijk kleurcontract hebben"},"description":{"en":"For users who have color blindness, all text or other elements should have a color contrast of 5:1.","nl":"Voor gebruikers met kleurenblindheid moeten alle tekst- en andere elementen een kleurcontrast hebben van 5:1."},"guidelines":{"wcag":{"1.4.3":{"techniques":["G18"]}}},"tags":["color"],"callback":["colorBackgroundImageContrast"],"options":{"algorithm":"wcag","selector":"*","gradientSampleMultiplier":3}},"colorElementBehindBackgroundImageContrast":{"type":"custom","testability":1,"title":{"en":"All elements should have appropriate color contrast","nl":"Alle elementen moeten een toepasselijk kleurcontract hebben"},"description":{"en":"For users who have color blindness, all text or other elements should have a color contrast of 5:1.","nl":"Voor gebruikers met kleurenblindheid moeten alle tekst- en andere elementen een kleurcontrast hebben van 5:1."},"guidelines":{"wcag":{"1.4.3":{"techniques":["G18"]}}},"tags":["color"],"callback":["colorElementBehindBackgroundImageContrast"],"options":{"algorithm":"wcag","selector":"*","gradientSampleMultiplier":3}},"colorBackgroundGradientContrast":{"type":"custom","testability":1,"title":{"en":"All elements should have appropriate color contrast","nl":"Alle elementen moeten een toepasselijk kleurcontract hebben"},"description":{"en":"For users who have color blindness, all text or other elements should have a color contrast of 5:1.","nl":"Voor gebruikers met kleurenblindheid moeten alle tekst- en andere elementen een kleurcontrast hebben van 5:1."},"guidelines":{"wcag":{"1.4.3":{"techniques":["G18"]}}},"tags":["color"],"callback":["colorBackgroundGradientContrast"],"options":{"algorithm":"wcag","selector":"*","gradientSampleMultiplier":3}},"colorElementBehindBackgroundGradientContrast":{"type":"custom","testability":1,"title":{"en":"All elements should have appropriate color contrast","nl":"Alle elementen moeten een toepasselijk kleurcontract hebben"},"description":{"en":"For users who have color blindness, all text or other elements should have a color contrast of 5:1.","nl":"Voor gebruikers met kleurenblindheid moeten alle tekst- en andere elementen een kleurcontrast hebben van 5:1."},"guidelines":{"wcag":{"1.4.3":{"techniques":["G18"]}}},"tags":["color"],"callback":["colorElementBehindBackgroundGradientContrast"],"options":{"algorithm":"wcag","selector":"*","gradientSampleMultiplier":3}},"definitionListsAreUsed":{"type":"custom","testability":0.5,"title":{"en":"Use a definition list for defining terms","nl":"Gebruik een definition list voor definities"},"description":{"en":"When providing a list of terms or definitions, use a definition list.","nl":"Wanneer er gebruik wordt gemaakt van een lijst termen of definities, gebruik hiervoor dan een definition list."},"guidelines":{"wcag":{"1.3.1":{"techniques":["H48"]}}},"tags":["structure"],"callback":"definitionListsAreUsed"},"doctypeProvided":{"type":"custom","testability":1,"title":{"en":"The document should contain a valid \"doctype\" declaration","nl":"Het document moet een geldige \"doctype\"-verklaring hebben"},"description":{"en":"Each document must contain a valid doctype declaration.","nl":"Ieder document moet een geldige doctype-verklaring hebben."},"guidelines":[],"tags":["doctype"],"callback":"doctypeProvided"},"documentAbbrIsUsed":{"type":"custom","testability":0.5,"title":{"en":"Abbreviations must be marked with an \"abbr\" element","nl":"Afkortingen moeten worden gemarkeerd met een \"abbr\"-element"},"description":{"en":"Abbreviations should be marked with an abbr element, at least once on the page for each abbreviation.","nl":"Afkortingen moeten worden gemarkeerd door middel van het abbr-element. Doe dit ten minste een keer per pagina voor elke afkorting."},"guidelines":{"wcag":{"3.1.4":{"techniques":["H28"]}}},"tags":["acronym","content"],"components":["acronym"],"callback":"documentAbbrIsUsed"},"documentAcronymsHaveElement":{"type":"custom","testability":0.5,"title":{"en":"Acronyms must be marked with an \"acronym\" element","nl":"Acroniemen moeten worden gemarkeerd met een \"acronym\"-element"},"description":{"en":"Acronyms should be marked with an acronym element, at least once on the page for each acronym.","nl":"Acroniemen moeten worden gemarkeerd door middel van het acronym-element. Doe dit ten minste een keer per pagina voor elke acroniem."},"guidelines":{"wcag":{"3.1.4":{"techniques":["H28"]}}},"tags":["acronym","content"],"components":["acronym"],"callback":"documentAcronymsHaveElement"},"documentAutoRedirectNotUsed":{"type":"selector","testability":1,"title":{"en":"Auto-redirect with \"meta\" elements must not be used","nl":"Auto-redirect met \"meta\"-elementen moeten niet worden gebruikt"},"description":{"en":"Because different users have different speeds and abilities when it comes to parsing the content of a page, a \"meta-refresh\" method to redirect users can prevent users from fully understanding the document before being redirected.","nl":"Omdat verschillende gebruikers verschillende snelheden en vaardigheden hebben met het scannen van content op een pagina, kan een \"meta-refresh\"-methode om gebruikers door te sturen hen verhinderen het document volledig te begrijpen voor ze worden doorgestuurd."},"guidelines":[],"tags":["document"],"options":{"selector":"meta[http-equiv=refresh]"}},"documentContentReadableWithoutStylesheets":{"type":"selector","testability":0,"title":{"en":"Content should be readable without style sheets","nl":"Content moet zonder stylesheets leesbaar zijn"},"description":{"en":"With all the styles for a page turned off, the content of the page should still make sense. Try to turn styles off in the browser and see if the page content is readable and clear.","nl":"Ook als alle stijlen voor een pagina zijn uitgezet, moet de content van de pagina nog steeds betekenisvol zijn. Zet de stylesheets uit in de browser en controleer of de content nog steeds leesbaar en duidelijk is."},"guidelines":{"508":["d"],"wcag":{"1.3.1":{"techniques":["G140"]},"1.4.5":{"techniques":["G140"]},"1.4.9":{"techniques":["G140"]}}},"tags":["document","color"],"options":{"selector":"html:has(link[rel=stylesheet], style) body, body:has(*[style])"}},"documentHasTitleElement":{"type":"selector","testability":1,"title":{"en":"The document should have a title element","nl":"Het document moet een titelelement hebben"},"description":{"en":"The document should have a title element.","nl":"Het document moet een titelelement hebben."},"guidelines":{"wcag":{"2.4.2":{"techniques":["H25"]}}},"tags":["document","head"],"options":{"selector":"html:not(html:has(title))"}},"documentIDsMustBeUnique":{"type":"custom","testability":1,"title":{"en":"All element \"id\" attributes must be unique","nl":"Alle element \"id\"-attributen moeten uniek zijn"},"description":{"en":"Element \"id\" attributes must be unique.","nl":"Element \"id\"-attributen moeten uniek zijn."},"guidelines":{"wcag":{"4.1.1":{"techniques":["F77","H93"]}}},"tags":["document","semantics"],"callback":"documentIDsMustBeUnique"},"documentIsWrittenClearly":{"type":"custom","testability":0.5,"title":{"en":"The document should be written to the target audience and read clearly","nl":"Het document moet geschreven zijn op het niveau van de doelgroep"},"description":{"en":"If a document is beyond a 10th grade level, then a summary or other guide should also be provided to guide the user through the content.","nl":"Als de inhoud van een document moeilijker is dan het vastgestelde taalniveau, moet een samenvatting of andere begeleiding worden toegevoegd om de gebruiker te helpen met de content."},"guidelines":{"wcag":{"3.1.5":{"techniques":["G86"]}}},"tags":["language","content"],"components":["textStatistics"],"callback":"documentIsWrittenClearly"},"documentLangIsISO639Standard":{"type":"custom","testability":1,"title":{"en":"The document's language attribute should be a standard code","nl":"Het language-attribuut van het document moet een standaard code zijn"},"description":{"en":"The document should have a default langauge, and that language should use the valid 2 or 3 letter language code according to ISO specification 639.","nl":"Het document moet een standaardtaal hebben en die taal moet de geldige 2- of 3-letterige taalcode hebben volgens de ISO-specificatie 639."},"guidelines":{"wcag":{"3.1.1":{"techniques":["H57"]}}},"tags":["document","language"],"strings":["languageCodes"],"callback":"documentLangIsISO639Standard"},"documentLangNotIdentified":{"type":"selector","testability":1,"title":{"en":"The document must have a \"lang\" attribute","nl":"Het document moet een \"lang\"-attribuut hebben"},"description":{"en":"The document should have a default langauge, by setting the \"lang\" attribute in the html element.","nl":"Het document moet een standaardtaal hebben, vastgelegd in het \"lang\"-attribuut in het html-element."},"guidelines":[],"tags":["document","language"],"options":{"selector":"html:not(html[lang])"}},"documentMetaNotUsedWithTimeout":{"type":"selector","testability":1,"title":{"en":"Meta elements must not be used to refresh the content of a page","nl":"Meta-elementen mogen niet worden gebruikt om content op een pagina te verversen"},"description":{"en":"Because different users have different speeds and abilities when it comes to parsing the content of a page, a \"meta-refresh\" method to reload the content of the page can prevent users from having full access to the content. Try to use a \"refresh this\" link instead.","nl":"Omdat verschillende gebruikers verschillende snelheden en vaardigheden hebben met het scannen van content op een pagina, kan een \"meta-refresh\"-methode om de pagina te herladen gebruikers hinderen in toegang tot de content. Gebruik een \"refresh this\" link hiervoor."},"guidelines":{"wcag":{"2.2.1":{"techniques":["F40","F41"]},"2.2.4":{"techniques":["F40","F41"]},"3.2.5":{"techniques":["F41"]}}},"tags":["document"],"options":{"selector":"meta[http-equiv=refresh]"}},"documentReadingDirection":{"type":"selector","testability":0.5,"title":{"en":"Reading direction of text is correctly marked","nl":"De leesrichting van de tekst staat juist aangegeven"},"description":{"en":"Where required, the reading direction of the document (for language that read in different directions), or portions of the text, must be declared.","nl":"Voor talen die een andere leesrichting hebben, moet de leesrichting van (een deel van) de tekst in een document worden opgenomen."},"guidelines":{"wcag":{"1.3.2":{"techniques":["H34"]}}},"tags":["document","language"],"options":{"selector":"*[lang=he]:not(*[dir=rtl]), *[lang=ar]:not(*[dir=rtl])"}},"documentStrictDocType":{"type":"custom","testability":1,"title":{"en":"The page uses a strict doctype","nl":"De pagina gebruikt een strikt doctype"},"description":{"en":"The doctype of the page or document should be either an HTML or XHTML strict doctype.","nl":"Het doctype van een pagina of document moet een HTML of XHTML strikt doctype zijn."},"guidelines":[],"tags":["document","doctype"],"callback":"documentStrictDocType"},"documentTitleDescribesDocument":{"type":"selector","testability":0,"title":{"en":"The title describes the document","nl":"De titel beschrijft het document"},"description":{"en":"The document title should actually describe the page. Often, screen readers use the title to navigate from one window to another.","nl":"De documenttitel moet een beschrijving zijn van de pagina. Schermlezen gebruiken de titels van pagina's om van het ene naar het andere scherm te navigeren."},"guidelines":{"wcag":{"2.4.2":{"techniques":["F25","G88"]}}},"tags":["document","head"],"options":{"selector":"head title:first"}},"documentTitleIsNotPlaceholder":{"type":"placeholder","testability":1,"title":{"en":"The document title should not be placeholder text","nl":"De documenttitle moet geen placeholder tekst zijn"},"description":{"en":"The document title should not be wasted placeholder text which does not describe the page.","nl":"De documenttitel moet geen placeholder tekst zijn die geen goede beschrijving van de pagina is."},"guidelines":{"wcag":{"2.4.2":{"techniques":["F25","G88"]}}},"tags":["document","head"],"components":["placeholder"],"options":{"content":true,"selector":"head title:first"}},"documentTitleIsShort":{"type":"custom","testability":0.5,"title":{"en":"The document title should be short","nl":"De documenttitel moet kort zijn"},"description":{"en":"The document title should be short and succinct. This test fails at 150 characters, but authors should consider this to be a suggestion.","nl":"De documenttitel moet kort en beknopt zijn. Probeer bij een titel langer dan 150 tekense de titel in te korten waar mogelijk."},"guidelines":[],"tags":["document","head"],"callback":"documentTitleIsShort"},"documentTitleNotEmpty":{"type":"placeholder","testability":1,"title":{"en":"The document should not have an empty title","nl":"Het document mag geen lege titel hebben"},"description":{"en":"The document should have a title element that is not white space.","nl":"Het document moet een titelelement hebben dat is ingevuld."},"guidelines":{"wcag":{"2.4.2":{"techniques":["F25","H25"]}}},"tags":["document","head"],"components":["placeholder"],"options":{"content":true,"empty":true,"selector":"head title"}},"documentValidatesToDocType":{"type":"custom","testability":1,"title":{"en":"Document must validate to the doctype","nl":"Het document moet valideren met het doctype"},"description":{"en":"The document must validate to the declared doctype.","nl":"Het document moet valideren met het vastgestelde doctype."},"guidelines":{"wcag":{"4.1.1":{"techniques":["G134"]}}},"tags":["document","doctype"],"callback":"documentValidatesToDocType"},"documentVisualListsAreMarkedUp":{"type":"custom","testability":1,"title":{"en":"Lists of items should be marked using list markup","nl":"Lijsten moeten gemarkeerd worden als ordered of unordered lists"},"description":{"en":"Use the ordered or unordered (bulleted) list elements to mark lists instead of using new lines that start with numbers or other characters to create a visual list.","nl":"Gebruik ordered (ol) of unordered (ul) elementen voor lijsten, in plaats van een nieuwe regel per item aan te maken die je laat beginnen met een nummer of teken om een visuele lijst te maken."},"guidelines":{"wcag":{"1.3.1":{"techniques":["H28","H48","T2"]}}},"tags":["list","semantics","content"],"strings":["symbols"],"callback":"documentVisualListsAreMarkedUp"},"domOrderMatchesVisualOrder":{"type":"selector","testability":0.5,"title":{"en":"Ensure that the visual order of the page matches the DOM","nl":"Zorg ervoor dat de visuele ordening van de pagina overeenkomt met de DOM"},"description":{"en":"When using positioning techniques, make sure that the visual order of the page matches the DOM.","nl":"Wanneer je gebruik maakt van positioneringstechnieken, zorg er dan voor dat de visuele ordening van de pagina overeenkomt met de DOM."},"guidelines":{"wcag":{"1.3.2":{"techniques":["C27"]},"2.4.3":{"techniques":["C27"]}}},"tags":["content"],"options":{"selector":"*:quailCss(position=absolute), *:quailCss(position=fixed), *:quailCss(float=right), *:quailCss(float=left)"}},"elementAttributesAreValid":{"type":"custom","testability":1,"title":{"en":"Attributes should have spaces between them and be wrapped in quotes","nl":"Attributen moeten gescheiden zijn door spaties en ze moeten tussen aanhalingstekens"},"description":{"en":"Attributes should have spaces between them and be wrapped in quotes.","nl":"Tussen attributen moeten spaties staan en ze moeten tussen aanhalingstekens staan."},"guidelines":{"4.1.1":{"techniques":["F70"]}},"callback":"elementAttributesAreValid"},"embedHasAssociatedNoEmbed":{"type":"custom","testability":1,"title":{"en":"All \"embed\" elements have an associated \"noembed\" element","nl":"Alle \"embed\" elementen moeten een bijbehorend \"noembed\"-element hebben"},"description":{"en":"Because some users cannot use the embed element, provide alternative content in a noembed element.","nl":"Sommige gebruikers kunnen het embed-element niet gebruiken. Biedt hiervoor alternatieve content aan in een noembed-element."},"guidelines":[],"tags":["object","embed","content"],"callback":"embedHasAssociatedNoEmbed"},"elementsDoNotHaveDuplicateAttributes":{"type":"custom","testability":1,"title":{"en":"Elements should not have duplicate attributes","nl":"Elementen mogen geen dubbele attributen hebben"},"description":{"en":"Elements should only have one type of any attribute. For example, there should not be two 'class' attributes.","nl":"Elementen mogen maar een type attribuut hebben. Er mogen bijvoorbeeld niet twee 'class'-attributen zijn."},"guidelines":[],"tags":["content"],"components":["htmlSource"],"libraries":["node-htmlparser/lib/htmlparser.js"],"callback":"elementsDoNotHaveDuplicateAttributes"},"embedMustHaveAltAttribute":{"type":"selector","testability":1,"title":{"en":"\"Embed\" elements must have an \"alt\" attribute","nl":"\"Embed\"-elementen moeten een \"alt\"-attribuut hebben"},"description":{"en":"All embed elements must have an \"alt\" attribute.","nl":"Alle embed-elementen moeten een \"alt\"-attribuut hebben."},"guidelines":[],"tags":["object","embed","content"],"options":{"selector":"embed:not([alt])"}},"embedMustNotHaveEmptyAlt":{"type":"selector","testability":1,"title":{"en":"\"Embed\" elements cannot have an empty \"alt\" attribute","nl":"\"Embed\"-elementen mogen geen leeg \"alt\"-attribuut hebben"},"description":{"en":"All embed elements must have an \"alt\" attribute that is not empty.","nl":"Alle embed-elementen moeten een gevuld \"alt\"-attribuut hebben."},"guidelines":[],"tags":["object","embed","content"],"options":{"selector":"embed[alt=]"}},"embedProvidesMechanismToReturnToParent":{"type":"selector","testability":0,"title":{"en":"All embed elements should provide a way for keyboard users to escape","nl":"Alle embed-elementen moeten een manier bieden voor toetsenbordgebruikers om het element te verlaten"},"description":{"en":"Ensure that a user who has only a keyboard as an input device can escape an embed element. This requires manual confirmation.","nl":"Zorg ervoor dat een gebruiker die alleen het toetsenbord gebruikt voor bediening een embed-element kan verlaten. Hiervoor is handmatige bevestiging nodig."},"guidelines":{"wcag":{"2.1.2":{"techniques":["G21"]}}},"tags":["object","embed","content"],"options":{"selector":"embed"}},"emoticonsExcessiveUse":{"type":"custom","testability":0.5,"title":{"en":"Emoticons should not be used excessively","nl":"Gebruik emoticons spaarzaam"},"description":{"en":"Emoticons should not be used excessively to communicate feelings or content. Try to rewrite the document to have more textual meaning, or wrapping the emoticons in an abbr element as outlined below. Emoticons are not read by screen-readers, and are often used to communicate feelings or other things which are relevant to the content of the document.","nl":"Gebruik emoticons spaarzaam om gevoel of content over te brengen. Probeer het document te herschrijven in tekst, of geef de emoticons een abbr-element. Emoticons worden niet voorgelezen door schermlezers, maar bevatten wel vaak informatie die relevant is voor de content van het document."},"guidelines":{"wcag":{"1.1.1":{"techniques":["H86"]}}},"tags":["language","emoticons","content"],"callback":"emoticonsExcessiveUse"},"emoticonsMissingAbbr":{"type":"custom","testability":1,"title":{"en":"Emoticons should have abbreviations","nl":"Emoticons moeten afkortingen hebben"},"description":{"en":"Emoticons are not read by screen-readers, and are often used to communicate feelings or other things which are relevant to the content of the document. If this emoticon is important content, mark it up with an \"abbr\" or \"acronym\" tag.","nl":"Emoticons worden niet voorgelezen door schermlezers, maar bevatten wel vaak informatie die relevant is voor de content van het document. Als een emoticon belangrijke content is, gebruik dan een \"abbr\" or \"acronym\" tag om het te markeren."},"guidelines":{"wcag":{"1.1.1":{"techniques":["H86"]}}},"tags":["language","emoticons","content"],"callback":"emoticonsMissingAbbr"},"fieldsetHasLabel":{"type":"selector","testability":1,"title":{"en":"Fieldsets require a label element","nl":"Fieldsets behoeven een label-element"},"description":{"en":"Fieldsets used to group similar form elements like checkboxes should have a label that describes the group of elements.","nl":"Fieldsets die een groep gelijkwaardige elementen bevatten moeten een label hebben die deze groep elementen beschrijft."},"guidelines":{"wcag":{"2.1.1":{"techniques":["H91"]},"2.1.3":{"techniques":["H91"]},"4.1.2":{"techniques":["H91"]}}},"tags":["form","content"],"options":{"selector":"fieldset:not(fieldset:has(legend))"}},"fileHasLabel":{"type":"label","testability":1,"title":{"en":"All \"file\" input elements have a corresponding label","nl":"Alle \"file\"-invoerelementen hebben een bijbehorend label"},"description":{"en":"All input elements of type \"file\" should have a corresponding label element. Screen readers often enter a \"form mode\" where only label text is read aloud to the user.","nl":"Alle input-elementen van het type \"file\" moeten een bijbehorend label-element hebben. Schermlezers maken vaak gebruik van een \"formuliereninstelling\" waarbij alleen de tekst van de labels hardop aan de gebruiker wordt voorgelezen."},"guidelines":{"508":["n"],"wcag":{"1.1.1":{"techniques":["H44"]},"1.3.1":{"techniques":["H44","F68"]},"3.3.2":{"techniques":["H44"]},"4.1.2":{"techniques":["H44"]}}},"tags":["form","content"],"components":["label"],"options":{"selector":"input[type=file]"}},"fileLabelIsNearby":{"type":"labelProximity","testability":0.5,"title":{"en":"All \"file\" input elements have a label that is close","nl":"Van alle \"file\"-invoerelementen staat het label in de buurt"},"description":{"en":"All input elements of type \"file\" must have a corresponding label that is close to the form element. Users of screen magnification or with reduced spatial skills are hampered in using a form element if the label for that element is located far away.","nl":"Alle inputelementen van het type \"file\" moeten een bijbehorend label hebben dat dicht bij het formulierelement staat. Gebruikers die het scherm vergroten of met beperkte ruimtelijke vaardigheden kunnen een formulier niet gebruiken als het label van een veld te ver weg staat."},"guidelines":[],"tags":["form","content"],"components":["labelProximity"],"options":{"selector":"input[type=file]"}},"focusIndicatorVisible":{"type":"custom","title":{"en":"Focus indicators have high visibility","nl":"Focus indicators moeten goed zichtbaar zijn"},"description":{"en":"When a focus indicator is used, it should have enough contrast with the background and big enough to be highly visible.","nl":"Wanneer je een focus indicator gebruikt, moet het contrast tussen de indicator en de achtergrond groot genoeg zijn in verband met de zichtbaarheid."},"guidelines":{"wcag":{"2.4.7":{"techniques":["C15","G165","G195"]}}},"tags":["focus","content"],"components":["color","convertToPx"],"callback":"focusIndicatorVisible"},"fontIsNotUsed":{"type":"selector","testability":1,"title":{"en":"Font elements should not be used","nl":"Het font element moet niet worden gebruikt"},"description":{"en":"The basefont tag is deprecated and should not be used. Investigate using stylesheets instead.","nl":"De basefont-tag is afgekeurd en moet niet worden gebruikt. Gebruik in plaats hiervan stylesheets."},"guidelines":[],"tags":["deprecated","content"],"options":{"selector":"font"}},"formAllowsCheckIfIrreversable":{"type":"selector","testability":0,"guidelines":[],"tags":["form","content"],"options":{"selector":"form"}},"formButtonsHaveValue":{"type":"selector","testability":1,"title":{"en":"Input elements for button, submit, or reset must have a value attribute","nl":"Invoerelementen voor knoppen, indienen of resetten moeten een waarde-attribuut hebben"},"description":{"en":"Any form element that is rendered as a button has to have a readable value attribute.","nl":"Elk invoerelement dat eruit ziet als een knop moet een leesbaar waarde-attribuut hebben."},"guidelines":{"wcag":{"2.1.1":{"techniques":["H91"]},"2.1.3":{"techniques":["H91"]},"4.1.2":{"techniques":["H91"]}}},"tags":["form","content"],"options":{"selector":"input[type=button], input[type=submit], input[type=reset]","test":":not([value])"}},"formDeleteIsReversable":{"type":"selector","testability":0,"title":{"en":"Deleting items using a form should be reversable","nl":"De verwijdering van een item in een formulier moet ongedaan gemaakt kunnen worden"},"description":{"en":"Check that, if a form has the option to delete an item, that the user has a chance to either reverse the delete process, or is asked for confirmation before the item is deleted. This is not something that can be checked through automated testing and requires manual confirmation.","nl":"Controleer of een gebruiker de verwijdering van een invoer in een formulier ongedaan kan maken wanneer het mogelijk is om een invoer te verwijderen. Dit kan niet met een automatische test en moet handmatig gecontroleerd en bevestigd worden."},"guidelines":[],"tags":["form","content"],"options":{"selector":"form"}},"formErrorMessageHelpsUser":{"type":"selector","testability":0,"title":{"en":"Forms offer the user a way to check the results of their form before performing an irrevocable action","nl":"Formulieren bieden gebruikers de gelegenheid om hun formulier te controleren voor ze een onomkeerbare actie uitvoeren"},"description":{"en":"If the form allows users to perform some irrevocable action, like ordreing a product, ensure that users have the ability to review the contents of the form they submitted first. This is not something that can be checked through automated testing and requires manual confirmation.","nl":"Als een formulier een gebruiker toestaat om een onomkeerbare actie uit te voeren, zoals het bestellen van een product, zorg er dan voor dat ze eerst het formulier kunnen controleren. Dit kan niet met een automatische test en moet handmatig gecontroleerd en bevestigd worden."},"guidelines":[],"tags":["form","content"],"options":{"selector":"form"}},"formHasGoodErrorMessage":{"type":"selector","testability":0,"title":{"en":"Form error messages should assist in solving errors","nl":"Foutmeldingen in formulieren moeten fouten helpen oplossen"},"description":{"en":"If the form has some required fields or other ways in which the user can commit an error, check that the reply is accessible. Use the words \"required\" or \"error\" within the label element of input items where the errors happened.","nl":"Als het formulier verplichte velden heeft of op andere manier verkeerd ingevuld kan worden, controleer dan of de bijbehorende foutmelding begrijpelijk is. Gebruik de woorden \"required\" of \"error\" in het label-element of in de invoeritems waar de fout is opgetredenitems where the errors happened."},"guidelines":[],"tags":["form","content"],"options":{"selector":"form"}},"formHasSubmitButton":{"type":"selector","testability":1,"title":{"en":"Form should have a submit button","nl":"Formulieren moeten een indienknop hebben"},"description":{"en":"Forms should have a button that allows the user to select when they want to submit the form.","nl":"Formulieren moeten een knop hebben waarmee de gebruiker kan bepalen wanneer zij een formulieren willen versturen."},"guidelines":{"wcag":{"3.2.2":{"techniques":["H32","G80"]}}},"tags":["form","content"],"options":{"selector":"form:not(form:has(input[type=image], input[type=submit], button[type=submit]))"}},"formWithRequiredLabel":{"type":"custom","testability":0,"title":{"en":"Input items which are required are marked as so in the label element","nl":"Invoervelden die verplicht zijn, zijn zo gemarkeerd in het label-element"},"description":{"en":"If a form element is required, it should be marked as so. This should not be a mere red asterisk, but instead either a 'required' image with alt text of \"required\" or the actual text \"required\". The indicator that an item is required should be included in the input element's label element.","nl":"Als een formulierveld verplicht is, moet het ook zichtbaar zijn. Doe dit niet alleen met een asterisk achter het veld, maar met bijvoorbeeld een afbeelding met als alttekst \"required\" of de tekst \"required\". De indicatie dat een veld verplicht is moet opgenomen zijn in het label-element van het invoerveld."},"guidelines":{"wcag":{"1.3.1":{"techniques":["ARIA2"]},"1.4.1":{"techniques":["F81"]},"3.3.2":{"techniques":["ARIA2","H90"]},"3.3.3":{"techniques":["ARIA2"]}}},"tags":["form","content"],"callback":"formWithRequiredLabel"},"frameIsNotUsed":{"type":"selector","testability":1,"title":{"en":"Frames are not used","nl":"Gebruik geen frames"},"description":{"en":"Frames should not be used to organize a page.","nl":"Gebruik geen frames om een pagina te organiseren."},"guidelines":[],"tags":["deprecated","frame"],"options":{"selector":"frame"}},"frameRelationshipsMustBeDescribed":{"type":"selector","testability":0.5,"title":{"en":"Complex framesets should contain a \"longdesc\" attribute","nl":"Complexe framesets moeten een \"longdesc\"-attribuut bevatten"},"description":{"en":"If a frameset contains three or more frames, use a \"longdesc\" attribute to help describe the purpose of the frames.","nl":"Als een frameset drie of meer frames bevat, gebruik dan een \"longdesc\"-attribuut om het doel van de frames te beschrijven."},"guidelines":[],"tags":["deprecated","frame"],"options":{"selector":"frameset:not(frameset[longdesc])"}},"framesAreUsedToGroupContent":{"type":"selector","testability":0.5,"title":{"en":"Use frame elements to group repeated materials","nl":"Gebruik frame-elementen om herhaalde content te groeperen"},"description":{"en":"When blocks of repeated content are used on a site, use frames to group content that is the same across pages.","nl":"Wanneer blokken content op een site herhaald worden, gebruik dan frames om content die op verschillende pagina's voorkomt te groeperen."},"guidelines":{"wcag":{"2.4.1":{"techniques":["H70"]}}},"tags":["deprecated","frame"],"options":{"selector":"body:not(body:has(frameset))"}},"frameSrcIsAccessible":{"type":"selector","testability":0,"title":{"en":"The source for each frame is accessible content.","nl":"De bron van elk frame is toegankelijke content."},"description":{"en":"Each frame should contain accessible content, and contain content accessible to screen readers, like HTML as opposed to an image.","nl":"Elk frame moet toegankelijke content bevatten, en content die toegankelijk is voor schermlezers, zoals HTML in tegenstelling tot een afbeelding."},"guidelines":[],"tags":["deprecated","frame"],"options":{"selector":"frame"}},"frameTitlesDescribeFunction":{"type":"placeholder","testability":0,"title":{"en":"All \"frame\" elements should have a \"title\" attribute that describes the purpose of the frame","nl":"Alle \"frame\" elementen moeten een \"title\"-attribuut hebben dat het doel van het frame beschrijft"},"description":{"en":"Each frame elements should have a \"title\" attribute which describes the purpose or function of the frame.","nl":"Elk frame-element moet een \"title\"-attribuut hebben dat het doel of de functie van het frame beschrijft."},"guidelines":{"wcag":{"2.4.1":{"techniques":["H64"]}}},"tags":["deprecated","frame"],"components":["placeholder"],"options":{"attribute":"title","empty":true,"selector":"frame[title], iframe[title]"}},"frameTitlesNotEmpty":{"type":"selector","testability":1,"title":{"en":"Frames cannot have empty \"title\" attributes","nl":"Frames mogen geen leeg \"title\"-attribuut hebben"},"description":{"en":"All frame elements must have a valid \"title\" attribute.","nl":"Alle frame-elementen moeten een geldig \"title\"-attribuut hebben."},"guidelines":{"wcag":{"2.4.1":{"techniques":["H64"]},"4.1.2":{"techniques":["H64"]}}},"tags":["deprecated","frame"],"options":{"selector":"frame:not(frame[title]), frame[title=''], iframe:not(iframe[title]), iframe[title='']"}},"frameTitlesNotPlaceholder":{"type":"placeholder","testability":1,"title":{"en":"Frames cannot have \"title\" attributes that are just placeholder text","nl":"Frames mogen geen \"title\"-attribuut hebben met placeholdertekst"},"description":{"en":"Frame \"title\" attributes should not be simple placeholder text like \"frame\".","nl":"Frame \"title\"-attributen mogen geen placeholdertekst bevatten zoals \"frame\"."},"guidelines":{"wcag":{"2.4.1":{"techniques":["H64"]},"4.1.2":{"techniques":["H64"]}}},"tags":["deprecated","frame"],"components":["placeholder"],"options":{"attribute":"title","selector":"frame, iframe"}},"framesHaveATitle":{"type":"selector","testability":1,"title":{"en":"All \"frame\" elements should have a \"title\" attribute","nl":"Alle \"frame\"-elementen moeten een \"title\"-attribuut hebben"},"description":{"en":"Each frame elements should have a \"title\" attribute.","nl":"Elk frame-elementen moeten een \"title\"-attribuut hebben."},"guidelines":{"wcag":{"2.4.1":{"techniques":["H64"]},"4.1.2":{"techniques":["H64"]}}},"tags":["deprecated","frame"],"options":{"selector":"frame:visible, iframe:visible","test":":not([title])"}},"framesetIsNotUsed":{"type":"selector","testability":1,"title":{"en":"The \"frameset\" element should not be used","nl":"Het \"frameset\"-element wordt niet gebruikt"},"description":{"en":"Frames and framesets should not be used to organize content.","nl":"Frames en framesets moeten niet gebruikt worden om content te organiseren."},"guidelines":[],"tags":["deprecated","frame"],"options":{"selector":"frameset"}},"framesetMustHaveNoFramesSection":{"type":"selector","testability":0.5,"title":{"en":"All framesets should contain a noframes section","nl":"Alle framesets moeten een noframes-sectie bevatten"},"description":{"en":"If a frameset contains three or more frames, use a \"longdesc\" attribute to help describe the purpose of the frames.","nl":"Als een frameset drie of meer frames bevat, gebruik dan een \"longdesc\"-attribuut om het doel van de frames te beschrijven."},"guidelines":[],"tags":["deprecated","frame"],"options":{"selector":"frameset:not(frameset:has(noframes))"}},"headersAttrRefersToATableCell":{"type":"custom","testability":1,"title":{"en":"Table cell headers attrtibutes must within the same table have an associated data cell with the same id","nl":"Tabel cellen met een headers attribuut moeten binnen dezelfde tabel een overeenkomende data cel hebben in het id attribuut dezelfde waarde"},"description":{"en":"","nl":""},"guidelines":[],"tags":["headers","td","th"],"callback":"headersAttrRefersToATableCell"},"headerH1":{"type":"headingLevel","testability":0,"title":{"en":"Header level 1 can only be followed by level 2","nl":"De header die volgt op een h1 is niet h3 tot h6"},"description":{"en":"Header order should not skip a level. Do not follow a header level 1 with a level 3, 4, 5, or 6.","nl":"Headers mogen geen niveau overslaan. Laat een h1-header niet volgen door een h3, h4, h5, of h6."},"guidelines":{"wcag":{"2.4.6":{"techniques":["G130"]}}},"tags":["header","content"],"components":["headingLevel"],"options":{"headingLevel":1}},"headerH1Format":{"type":"selector","testability":0,"title":{"en":"All h1 elements are not used for formatting","nl":"H1-elementen worden niet gebruikt voor formatting"},"description":{"en":"An h1 element may not be used purely for formatting.","nl":"Een h1-element mag niet alleen gebruikt worden voor formatting."},"guidelines":{"wcag":{"1.3.1":{"techniques":["T3"]}}},"tags":["header","content"],"components":["header"],"options":{"selector":"h1"}},"headerH2":{"type":"headingLevel","testability":0,"title":{"en":"Header level 2 can not be followed by levels from 4 to 6","nl":"De header volgend op een h2 is geen h4, h5, of h6"},"description":{"en":"Header order should not skip a level. Do not follow a header level 2 with a level 4, 5, or 6.","nl":"Headers mogen geen niveau overslaan. Laat een h2-header niet volgen door een h4, h5, of h6."},"guidelines":{"wcag":{"2.4.6":{"techniques":["G130"]}}},"tags":["header","content"],"components":["headingLevel"],"options":{"headingLevel":2}},"headerH2Format":{"type":"selector","testability":0,"title":{"en":"All h2 elements are not used for formatting","nl":"H2-elementen worden niet gebruikt voor formatting"},"description":{"en":"An h2 element may not be used purely for formatting.","nl":"Een h2-element mag niet alleen gebruikt worden voor formatting."},"guidelines":{"wcag":{"1.3.1":{"techniques":["T3"]}}},"tags":["header","content"],"components":["header"],"options":{"selector":"h2"}},"headerH3":{"type":"headingLevel","testability":0,"title":{"en":"Header level 3 can not be followed by levels 5 and 6","nl":"De header volgend op een h3 is geen h5, of h6"},"description":{"en":"Header order should not skip a level. Do not follow a header level 3 with a level 5 or 6.","nl":"Headers mogen geen niveau overslaan. Laat een h3-header niet volgen door een h5, of h6."},"guidelines":{"wcag":{"2.4.6":{"techniques":["G130"]}}},"tags":["header","content"],"components":["headingLevel"],"options":{"headingLevel":3}},"headerH3Format":{"type":"selector","testability":0,"title":{"en":"All h3 elements are not used for formatting","nl":"H3-elementen worden niet gebruikt voor formatting"},"description":{"en":"An h3 element may not be used purely for formatting.","nl":"Een h3-element mag niet alleen gebruikt worden voor formatting."},"guidelines":{"wcag":{"1.3.1":{"techniques":["T3"]}}},"tags":["header","content"],"components":["header"],"options":{"selector":"h3"}},"headerH4":{"type":"headingLevel","testability":0,"title":{"en":"Header level 4 can not be followed by level 6","nl":"De header volgend op een h4 is geen h6"},"description":{"en":"Header order should not skip a level. Do not follow a header level 4 with level 6 header.","nl":"Headers mogen geen niveau overslaan. Laat een h4/code> header niet volgen door een h6."},"guidelines":{"wcag":{"2.4.6":{"techniques":["G130"]}}},"tags":["header","content"],"components":["headingLevel"],"options":{"headingLevel":4}},"headerH4Format":{"type":"selector","testability":0,"title":{"en":"All h4 elements are not used for formatting","nl":"H4-elementen worden niet gebruikt voor formatting"},"description":{"en":"An h4 element may not be used purely for formatting.","nl":"Een h4-element mag niet alleen gebruikt worden voor formatting."},"guidelines":{"wcag":{"1.3.1":{"techniques":["T3"]}}},"tags":["header","content"],"components":["header"],"options":{"selector":"h4"}},"headerH5Format":{"type":"selector","testability":0,"title":{"en":"All h5 elements are not used for formatting","nl":"H5-elementen worden niet gebruikt voor formatting"},"description":{"en":"An h5 element may not be used purely for formatting.","nl":"Een h5-element mag niet alleen gebruikt worden voor formatting."},"guidelines":{"wcag":{"1.3.1":{"techniques":["T3"]}}},"tags":["header","content"],"options":{"selector":"h5"}},"headerH6Format":{"type":"selector","testability":0,"title":{"en":"All h6 elements are not used for formatting","nl":"H6-elementen worden niet gebruikt voor formatting"},"description":{"en":"An h6 element may not be used purely for formatting.","nl":"Een h6-element mag niet alleen gebruikt worden voor formatting."},"guidelines":{"wcag":{"1.3.1":{"techniques":["T3"]}}},"tags":["header","content"],"options":{"selector":"h6"}},"headerTextIsTooLong":{"type":"custom","testability":1,"title":{"en":"Header text is too long","nl":"-- missing translation --"},"description":{"en":"Headers should not contain too long text as they're designed to show document structure. Users will often skim document only by its headings.","nl":"-- missing translation --"},"guidelines":{"wcag":{"1.3.1":{"techniques":["H42"]}}},"tags":["content"],"callback":"headerTextIsTooLong"},"headersHaveText":{"type":"placeholder","testability":1,"title":{"en":"All headers should contain readable text","nl":"Alle headers moeten leesbare tekst bevatten"},"description":{"en":"Users with screen readers use headings (e.g. h1 elements), just like the tabs to navigate the structure of a page. All headings should contain either text, or images with appropriate alternative text.","nl":"Gebruikers van schermlezers gebruiken headers om via de structuur van een pagina te navigeren. Alle headers moeten daarom tekst bevatten of afbeeldingen met toepasselijk alt-attributen."},"guidelines":{"wcag":{"1.3.1":{"techniques":["G141"]},"2.4.10":{"techniques":["G141"]}}},"tags":["header","content"],"components":["placeholder"],"options":{"content":true,"empty":true,"selector":"h1, h2, h3, h4, h5, h6"}},"headersUsedToIndicateMainContent":{"type":"custom","testability":0.5,"title":{"en":"Use header to indicate start of main content","nl":"Gebruik headers om de start van belangrijke content aan te geven"},"description":{"en":"For every main content area, indicate the beginning of the main content using a header.","nl":"Geef het begin van de belangrijkste content in elk contentvlak aan door middel van een header."},"guidelines":{"wcag":{"2.4.1":{"techniques":["H69"]}}},"tags":["header","content"],"callback":"headersUsedToIndicateMainContent"},"headersUseToMarkSections":{"type":"custom","testability":0.5,"title":{"en":"Use headers to mark the beginning of each section","nl":"Gebruik headers om de start van elke sectie aan te geven."},"description":{"en":"Check that each logical section of the page is broken or introduced with a header (h1-h6) element.","nl":"Controleer dat elke logische sectie van een pagina wordt onderbroken door of start met een header-element (h1-h6)."},"guidelines":{"wcag":{"1.3.1":{"techniques":["G141"]},"2.4.1":{"techniques":["G141","H69"]}}},"tags":["header","content"],"callback":"headersUseToMarkSections"},"idRefHasCorrespondingId":{"type":"custom","testability":1,"title":{"en":"Elements with an idref type attribute must correspond to an element with an ID","nl":"Elementen met een idref type attribuut moeten corresponderen met een element met een ID"},"description":{"en":"When using an idref type attribute, the target element with the ID must exist on the page.","nl":"Wanneer je een idref type attibuut gebruikt, moet het doelelement met dit ID ook bestaan op de pagina."},"guidelines":{"wcag":{"1.3.1":{"techniques":["F17"]},"4.1.1":{"techniques":["F17"]}}},"callback":"idRefHasCorrespondingId"},"idrefsHasCorrespondingId":{"type":"custom","testability":1,"title":{"en":"Elements with an idref attribute must correspond to an element with an ID","nl":"Elementen met een idref-attribuut moeten corresponderen met een element met een ID"},"description":{"en":"","nl":""},"guidelines":{"wcag":{"1.3.1":{"techniques":["F17"]},"4.1.1":{"techniques":["F17"]}}},"callback":"idrefsHasCorrespondingId"},"iIsNotUsed":{"type":"selector","testability":1,"title":{"en":"The \"i\" (italic) element is not used","nl":"Het \"i\"-element (cursief) wordt niet gebruikt"},"description":{"en":"The i (italic) element provides no emphasis for non-sighted readers. Use the em tag instead.","nl":"Het i-element biedt geen nadruk voor slechtziende en blinde lezers. Gebruik in plaats daarvan de em-tag."},"guidelines":[],"tags":["deprecated","content"],"options":{"selector":"i"}},"iframeMustNotHaveLongdesc":{"type":"selector","testability":1,"title":{"en":"Inline frames (\"iframes\") should not have a \"longdesc\" attribute","nl":"Inline frames (\"iframes\") krijgen geen \"longdesc\"-attribuut"},"description":{"en":"Inline frames (iframe) should not have a \"longdesc\" attribute.","nl":"Inline frames (\"iframes\") krijgen geen \"longdesc\"-attribuut."},"guidelines":[],"tags":["objects","iframe","content"],"options":{"selector":"iframe[longdesc]"}},"imageMapServerSide":{"type":"selector","testability":1,"title":{"en":"All links in a server-side map should have duplicate links available in the document","nl":"Alle links in een server-side map moeten elders in het document terugkeren"},"description":{"en":"Any image with an \"usemap\" attribute for a server-side image map should have the available links duplicated elsewhere.","nl":"Elke afbeelding met een \"usemap\"-attribuut voor een server-side map moet de beschikbare links ook elders hebben."},"guidelines":[],"tags":["objects","iframe","content"],"options":{"selector":"img[ismap]"}},"imgAltEmptyForDecorativeImages":{"type":"selector","testability":0,"title":{"en":"If an image is purely decorative, the \"alt\" text must be empty","nl":"Als een afbeelding alleen ter decoratie is, moet de \"alt\"-tekst leeg zijn"},"description":{"en":"Any image that is only decorative (serves no function or adds to the purpose of the page content) should have an empty \"alt\" attribute.","nl":"Elke afbeelding die alleen ter decoratie is (en die dus geen functie heeft of bijdraagt aan het doel van een contentpagina) moet een leeg \"alt\"-attirbuut hebben."},"guidelines":{"wcag":{"1.3.3":{"techniques":["F26"]}}},"tags":["image","content"],"options":{"selector":"img[alt]"}},"imgAltIdentifiesLinkDestination":{"type":"selector","testability":0,"title":{"en":"Any image within a link must have \"alt\" text the describes the link destination","nl":"Elke afbeelding binnen een link moet een \"alt\"-tekst hebben die de bestemming van de link beschrijft"},"description":{"en":"Any image that is within a link should have an \"alt\" attribute which identifies the destination or purpose of the link.","nl":"Elke afbeelding binnen link moet een \"alt\"-tekst hebben die de bestemming of het doel van de link beschrijft."},"guidelines":[],"tags":["image","content"],"options":{"selector":"a img[alt]:first"}},"imgAltIsDifferent":{"type":"custom","testability":0.5,"title":{"en":"Image alternative text should not be the same as the file name","nl":"\"Alt\"-attributen van afbeeldingen moeten niet hetzelfde zijn als de bestandsnaam"},"description":{"en":"All images should have a meaningful alternative text. The file name is rarely meaningful and does not always reflect information presented by the image.","nl":"Alle img-elementen moeten een \"alt\"-attribuut hebben dat anders is dan de bestandsnaam van de afbeelding."},"guidelines":{"508":["a"],"wcag":{"1.1.1":{"techniques":["H37"]}}},"tags":["image","content"],"callback":"imgAltIsDifferent"},"imgAltIsSameInText":{"type":"selector","testability":0,"title":{"en":"Check that any text within an image is also in the \"alt\" attribute","nl":"Controleer dat tekst in een afbeelding ook is opgenomen in het \"alt\"-attribuut"},"description":{"en":"If an image has text within it, that text should be repeated in the \"alt\" attribute","nl":"Als een afbeelding tekst bevat, moet deze tekst herhaald worden in het \"alt\"-attribuut."},"guidelines":{"508":["a"],"wcag":{"1.1.1":{"techniques":["G74","H37"]}}},"tags":["image","content"],"options":{"selector":"img"}},"imgAltIsTooLong":{"type":"custom","testability":1,"title":{"en":"Image alternative text is too long","nl":"Altteksten voor een afbeelding zijn kort"},"description":{"en":"Image alternative text should be clear and concise. Alternative text longer than 100 characters should be reviewed to see if it can be shortened.","nl":"Alle \"alt\"-attributen voor img-elementen moeten duidelijk en bondig zijn. Verifieer \"alt\"-attributen langer dan 100 tekens en kort ze in waar mogelijk."},"guidelines":{"508":["a"],"wcag":{"1.1.1":{"techniques":["H37"]}}},"tags":["image","content"],"callback":"imgAltIsTooLong"},"imgAltNotEmptyInAnchor":{"type":"custom","testability":1,"title":{"en":"An image within a link cannot have an empty alternative text if there is no other text within the link","nl":"Een afbeelding binnen een link mag geen leeg \"alt\"-attribuut hebben als er geen andere tekst is in de link"},"description":{"en":"Any image that is within a link that has no other text cannot have an empty or missing alternative text.","nl":"Elke afbeelding binnen een link (een a-element) die geen andere tekst heeft, mag geen leeg of ontbrekend \"alt\"-attribuut hebben."},"guidelines":{"508":["a"],"wcag":{"2.4.4":{"techniques":["H30"]}}},"tags":["image","content"],"callback":"imgAltNotEmptyInAnchor"},"imgAltNotPlaceHolder":{"type":"placeholder","testability":1,"title":{"en":"Images should not have a simple placeholder text as an \"alt\" attribute","nl":"Afbeeldingen mogen geen placeholdertkest als \"alt\"-attribuut hebben"},"description":{"en":"Any image that is not used decorativey or which is purely for layout purposes cannot have an \"alt\" attribute that consists solely of placeholders.","nl":"Elke afbeelding die niet ter decoratie is of die alleen voor lay-out doeleinden is bedoeld, mag geen \"alt\"-attribuut hebben met daarin placeholdertekst."},"guidelines":{"508":["a"],"wcag":{"1.1.1":{"techniques":["F30","F39"]},"1.2.1":{"techniques":["F30"]}}},"tags":["image","content"],"components":["placeholder"],"options":{"attribute":"alt","selector":"img"}},"imgAltTextNotRedundant":{"type":"custom","testability":1,"title":{"en":"Unless the image files are the same, no image should contain redundant alt text","nl":"Tenzij afbeeldingen hetzelfde zijn, mag geen enkele afbeelding dezelfde alttekst hebben"},"description":{"en":"Every distinct image on a page should have it's own alt text which is different than all the others on the page to avoid redundancy and confusion.","nl":"Elke unieke afbeelding op een pagina moet zijn eigen alttekst hebben die anders is dan die van andere afbeeldingen op de pagina om dubbeling en verwarring te voorkomen."},"guidelines":[],"tags":["image","content"],"callback":"imgAltTextNotRedundant"},"imgGifNoFlicker":{"type":"custom","testability":1,"title":{"en":"Any animated GIF should not flicker","nl":"Geen enkele animated GIF mag knipperen of flitsen"},"description":{"en":"Animated GIF files should not flicker with a frequency over 2 Hz and lower than 55 Hz. You can check the flicker rate of this GIF using an online tool.","nl":"Animated GIF-bestanden mogen niet knipperen of flitsen met een frequentie hoger dan 2 Hz en lager dan 55 Hz. Controleer de frequentie van deze GIF met een online tool."},"guidelines":{"508":["j"],"wcag":{"2.2.2":{"techniques":["G152"]}}},"tags":["image","content"],"callback":"imgGifNoFlicker"},"imgHasAlt":{"type":"selector","testability":1,"title":{"en":"Images must provide alternative text","nl":"Afbeeldingselementen moeten een \"alt\"-attribuut hebben"},"description":{"en":"Alternative text needs to convey the same information as the image. This text will be used when the browser has disabled images, the image was not found on the server, or by non-sighted visitors who use screen readers.","nl":"Alle img-elementen moeten een \"alt\"-attribuut hebben."},"guidelines":{"508":["a"],"wcag":{"1.1.1":{"techniques":["F65","H37"]}}},"tags":["image","content"],"options":{"selector":"img:not(img[alt])"}},"imgHasLongDesc":{"type":"custom","testability":1,"title":{"en":"A \"longdesc\" attribute is required for any image where additional information not in the \"alt\" attribute is required","nl":"Een \"longdesc\"-attribuut is verplicht voor elke afbeelding waar aanvullende informatie niet benodigd is in het \"alt\"-attribuut"},"description":{"en":"Any image that has an \"alt\" attribute that does not fully convey the meaning of the image must have a \"longdesc\" attribute.","nl":"Elke afbeelding die een \"alt\"-attribuut heeft dat de volledige betekenis van de afbeelding bevat, moet een \"longdesc\"-attribuut hebben."},"guidelines":{"wcag":{"2.4.4":{"techniques":["G91"]},"2.4.9":{"techniques":["G91"]}}},"tags":["image","content"],"callback":"imgHasLongDesc"},"imgImportantNoSpacerAlt":{"type":"custom","testability":0.5,"title":{"en":"Images that are important should not have a purely white-space \"alt\" attribute","nl":"Afbeeldingen die belangrijk zijn mogen geen leeg \"alt\"-attribuut hebben"},"description":{"en":"Any image that is not used decorativey or which is purely for layout purposes cannot have an \"alt\" attribute that consists solely of white space (i.e. a space).","nl":"Elke afbeelding die niet ter decoratie is of die alleen voor lay-out doeleinden is bedoeld, mag geen leeg \"alt\"-attribuut hebben (bijvoorbeeld alleen een spatie)."},"guidelines":[],"tags":["image","content"],"callback":"imgImportantNoSpacerAlt"},"imgMapAreasHaveDuplicateLink":{"type":"custom","testability":1,"title":{"en":"All links within a client-side image are duplicated elsewhere in the document","nl":"Alle links met een client-side afbeelding moeten elders in het document terugkeren"},"description":{"en":"Any image that has a \"usemap\" attribute must have links replicated somewhere else in the document.","nl":"Elke afbeelding met een \"usemap\"-attribuut moet een link elders in het document hebben."},"guidelines":{"508":["ef","ef"]},"tags":["image","imagemap"],"callback":"imgMapAreasHaveDuplicateLink"},"imgNonDecorativeHasAlt":{"type":"custom","testability":0.5,"title":{"en":"Any non-decorative images should have a non-empty \"alt\" attribute","nl":"Elke niet-decoratieve afbeelding moet een gevuld \"alt\"-attribuut hebben"},"description":{"en":"Any image that is not used decorativey or which is purely for layout purposes cannot have an empty \"alt\" attribute.","nl":"Elke afbeelding die niet ter decoratie is of voor lay-out doeleinden wordt gebruikt, moet een gevuld \"alt\"-attribuut hebben."},"guidelines":{"508":["a"],"wcag":{"1.1.1":{"techniques":["F38"]}}},"tags":["image","content"],"callback":"imgNonDecorativeHasAlt"},"imgNotReferredToByColorAlone":{"type":"selector","testability":0,"title":{"en":"For any image, the \"alt\" text cannot refer to color alone","nl":"Voor elke afbeelding geldt dat de \"alt\"-tekst niet alleen aan kleur mag refereren"},"description":{"en":"The \"alt\" text or content text for any image should not refer to the image by color alone. This is often fixed by changing the \"alt\" text to the meaning of the image","nl":"De \"alt\"-tekst of content voor elke afbeelding mag niet alleen maar een kleur bevatten. Neem in de \"alt\"-tekst de betekenis van de afbeelding op."},"guidelines":{"508":["c"],"wcag":{"1.1.1":{"techniques":["F13"]},"1.4.1":{"techniques":["F13"]}}},"tags":["image","color","content"],"options":{"selector":"img"}},"imgServerSideMapNotUsed":{"type":"selector","testability":1,"title":{"en":"Server-side image maps should not be used","nl":"Server-side image maps moeten niet worden gebruikt"},"description":{"en":"Server-side image maps should not be used.","nl":"Server-side image maps mogen niet worden gebruikt."},"guidelines":[],"tags":["image","imagemap","content"],"options":{"selector":"img[ismap]"}},"imgShouldNotHaveTitle":{"type":"selector","testability":1,"title":{"en":"Images should not have a \"title\" attribute","nl":"Afbeeldingen moeten geen \"title\"-attribuut hebben"},"description":{"en":"Images should not contain a \"title\" attribute.","nl":"Afbeeldingen zouden geen \"title\"-attribuut moeten bevatten."},"guidelines":[],"tags":["image","content"],"options":{"selector":"img[title]"}},"imgWithEmptyAlt":{"type":"selector","testability":0,"title":{"en":"Use empty alternative text only for decorative images","nl":""},"description":{"en":"Empty alternative text can only be used if the image serves purely decoration purposes. If the image is supposed to convey any information whatsoever, you need to set a proper alternative text for it.","nl":""},"guidelines":[],"tags":["image","content"],"options":{"selector":"img[alt=\"\"]"}},"imgWithMapHasUseMap":{"type":"selector","testability":1,"title":{"en":"Any image with an \"ismap\" attribute have a valid \"usemap\" attribute","nl":"Elke afbeelding met een \"ismap\"-attribuut heeft een geldig \"usemap\"-attribuut"},"description":{"en":"If an image has an \"ismap\" attribute it must have a valid \"usemap\" attribute.","nl":"Als een afbeelding een \"ismap\"-attribuut heeft, moet het ook een geldig \"usemap\"-attribuut hebben"},"guidelines":{"508":["ef","ef"]},"tags":["image","imagemap","content"],"options":{"selector":"img[ismap]:not(img[usemap])"}},"imgWithMathShouldHaveMathEquivalent":{"type":"custom","testability":0,"title":{"en":"Images which contain math equations should provide equivalent MathML","nl":"Afbeeldingen met wiskundige vergelijking moeten een equivalent in MathML bieden"},"description":{"en":"Images which contain math equations should be accompanied or link to a document with the equivalent equation marked up with MathML.","nl":"Afbeeldingen die wiskundige vergelijkingen bevatten moeten vergezeld zijn van of linken naar een document met daarin een equivalent van de vergelijking in MathML."},"guidelines":[],"tags":["image","content"],"callback":"imgWithMathShouldHaveMathEquivalent"},"inputCheckboxHasTabIndex":{"type":"placeholder","testability":1,"title":{"en":"All \"checkbox\" input elements require a valid \"tabindex\" attribute","nl":"Alle \"checkbox\"-invoerelementen moeten een geldig \"tabindex\"-attribuut hebben"},"description":{"en":"All input elements of type \"checkbox\" should have a \"tabindex\" attribute to help navigate the form with a keyboard alone.","nl":"Alle invoerelementen van het type \"checkbox\" moeten \"tabindex\"-attribuut hebben dat ervoor zorgt dat je door een formulier kunt navigeren met het toetsenbord."},"guidelines":[],"tags":["form","content"],"components":["placeholder"],"options":{"attribute":"tabindex","empty":true,"selector":"input[type=checkbox]"}},"inputCheckboxRequiresFieldset":{"type":"custom","testability":1,"title":{"en":"Logical groups of check boxes should be grouped with a fieldset","nl":"Logische groepen van keuzevakjes moeten gegroepeerd zijn in een fieldset"},"description":{"en":"Related \"checkbox\" input fields should be grouped together using a fieldset.","nl":"Gerelateerde \"keuzevakjes\"-invoervelden moeten bij elkaar staan in een fieldset."},"guidelines":{"wcag":{"3.3.2":{"techniques":["H71"]}}},"tags":["form","content"],"callback":"inputCheckboxRequiresFieldset"},"inputDoesNotUseColorAlone":{"type":"selector","testability":0,"title":{"en":"An \"input\" element should not use color alone","nl":"Een invoerveld mag niet alleen maar kleur gebruiken"},"description":{"en":"All input elements should not refer to content by color alone.","nl":"Elk invoerveld moet naar content verwijzen door middel van meer dan alleen kleur."},"guidelines":{"508":["c"]},"tags":["form","color","content"],"options":{"selector":"input:not(input[type=hidden])"}},"inputElementsDontHaveAlt":{"type":"selector","testability":1,"title":{"en":"Input elements which are not images should not have an \"alt\" attribute","nl":"Invoervelden die geen afbeelding zijn, moeten geen \"alt\"-attribuut hebben"},"description":{"en":"Input elements which are not images should not have an \"alt\" attribute, because of inconsistencies in how user agents use the \"alt\" attribute.","nl":"Invoervelden die geen afbeelding zijn, moeten geen \"alt\"-attribuut hebben, omdat user agents het \"alt\"-attribuut niet consistent gebruiken."},"guidelines":[],"tags":["form","content"],"options":{"selector":"input[type!=image][alt]"}},"inputFileHasTabIndex":{"type":"placeholder","testability":1,"title":{"en":"All \"file\" input elements require a valid \"tabindex\" attribute","nl":"Alle \"document\"-invoerelementen moeten een geldig \"tabindex\"-attribuut hebben"},"description":{"en":"All input elements of type \"file\" should have a \"tabindex\" attribute to help navigate the form with a keyboard alone.","nl":"Alle invoer-elementen van het type \"file\" moeten een \"tabindex\"-attribuut hebben om navigatie van het formulier met het toetsenbord mogelijk te maken."},"guidelines":[],"tags":["form","tabindex"],"components":["placeholder"],"options":{"attribute":"tabindex","empty":true,"selector":"input[type=file]"}},"inputImageAltIdentifiesPurpose":{"type":"selector","testability":0,"title":{"en":"All \"input\" elements with a type of \"image\" must have an \"alt\" attribute that describes the function of the input","nl":"Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben dat de functie van de invoer beschrijft"},"description":{"en":"All input elements with a type of \"image\" should have an \"alt\" attribute.","nl":"Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben."},"guidelines":{"wcag":{"1.1.1":{"techniques":["H36"]}}},"tags":["form","content"],"options":{"selector":"input[type=image][alt]"}},"inputImageAltIsNotFileName":{"type":"custom","testability":1,"title":{"en":"All \"input\" elements with a type of \"image\" must have an \"alt\" attribute which is not the same as the filename","nl":"Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben dat anders is dan de bestandsnaam"},"description":{"en":"All input elements with a type of \"image\" should have an \"alt\" attribute which is not the same as the filename.","nl":"Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben dat anders is dan de bestandsnaam."},"guidelines":{"508":["a"],"wcag":{"1.1.1":{"techniques":["H36"]}}},"tags":["form","image","content"],"callback":"inputImageAltIsNotFileName"},"inputImageAltIsNotPlaceholder":{"type":"placeholder","testability":1,"title":{"en":"All \"input\" elements with a type of \"image\" must have an \"alt\" attribute which is not placeholder text.","nl":"Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben anders dan alleen placeholdertekst."},"description":{"en":"All \"input\" elements with a type of \"image\" must have an \"alt\" attribute which is not placeholder text.","nl":"Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben anders dan alleen placeholdertekst."},"guidelines":{"508":["a"],"wcag":{"1.1.1":{"techniques":["H36"]},"2.1.1":{"techniques":["H91"]},"2.1.3":{"techniques":["H91"]},"4.1.2":{"techniques":["H91"]}}},"tags":["form","image","content"],"components":["placeholder"],"options":{"attribute":"alt","selector":"input[type=image]"}},"inputImageAltIsShort":{"type":"custom","testability":1,"title":{"en":"All \"input\" elements with a type of \"image\" must have an \"alt\" attribute which is as short as possible","nl":"Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben dat zo kort mogelijk is"},"description":{"en":"All \"input\" elements with a type of \"image\" must have an \"alt\" attribute which is as short as possible.","nl":"Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben dat zo kort mogelijk is."},"guidelines":{"508":["a"],"wcag":{"1.1.1":{"techniques":["H36"]}}},"tags":["form","image","content"],"callback":"inputImageAltIsShort"},"inputImageAltNotRedundant":{"type":"custom","testability":1,"title":{"en":"The \"alt\" text for input \"image\" submit buttons must not be filler text","nl":"De \"alt\"-tekst for \"image\"-knoppen moet anders zijn dan alleen placeholdertekst"},"description":{"en":"Every form image button should not simply use filler text like \"button\" or \"submit\" as the \"alt\" text.","nl":"Elke formulierknop die een afbeelding is, moet bruikbare tekst als \"alt\"-tekst hebben, anders dan \"knop\" of \"verstuur\"."},"guidelines":{"wcag":{"1.1.1":{"techniques":["H36"]}}},"tags":["form","image","content"],"strings":["redundant.inputImage"],"callback":"inputImageAltNotRedundant"},"inputImageHasAlt":{"type":"selector","testability":1,"title":{"en":"All \"input\" elements with a type of \"image\" must have an \"alt\" attribute","nl":"Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben"},"description":{"en":"All input elements with a type of \"image\" should have an \"alt\" attribute.","nl":"Elk \"invoer\"-element met een type \"afbeelding\" moet een \"alt\"-attribuut hebben."},"guidelines":{"508":["a"],"wcag":{"1.1.1":{"techniques":["F65","G94","H36"]},"2.1.1":{"techniques":["H91"]},"2.1.3":{"techniques":["H91"]},"4.1.2":{"techniques":["H91"]}}},"tags":["form","image","content"],"options":{"selector":"input[type=image]:visible","test":":not(input[type=image][alt])"}},"inputImageNotDecorative":{"type":"selector","testability":0,"title":{"en":"The \"alt\" text for input \"image\" buttons must be the same as text inside the image","nl":"De \"alt\"-tekst voor afbeeldingen van invoerknoppen moet hetzelfde zijn als de tekst in de afbeeldingen"},"description":{"en":"Every form image button which has text within the image (say, a picture of the word \"Search\" in a special font) must also have this text in the \"alt\" text.","nl":"Elke formulierknop die een afbeelding is en tekst in de afbeelding heeft (bijvoorbeeld \"Zoek\") moet deze tekst ook in de \"alt\"-tekst hebben."},"guidelines":{"wcag":{"1.1.1":{"techniques":["H36"]}}},"tags":["form","image","content"],"options":{"selector":"input[type=image]"}},"inputPasswordHasTabIndex":{"type":"placeholder","testability":1,"title":{"en":"All \"password\" input elements require a valid \"tabindex\" attribute","nl":"Alle \"paswoord\"-invoervelden moeten een geldig \"tabindex\"-attribuut hebben"},"description":{"en":"All input elements of type \"password\" should have a \"tabindex\" attribute to help navigate the form with a keyboard alone.","nl":"Alle input-elementen van het type \"paswoord\" moeten een \"tabindex\"-attribuut hebben om navigatie met alleen het toetsenbord mogelijk te maken."},"guidelines":[],"tags":["form","content"],"components":["placeholder"],"options":{"attribute":"tabindex","empty":true,"selector":"input[type=password]"}},"inputRadioHasTabIndex":{"type":"placeholder","testability":1,"title":{"en":"All \"radio\" input elements require a valid \"tabindex\" attribute","nl":"Alle invoerelementen van het type \"radio\" moeten een geldig \"tabindex\"-attribuut hebben"},"description":{"en":"All input elements of type \"radio\" should have a \"tabindex\" attribute to help navigate the form with a keyboard alone.","nl":"Alle input-elementen van het type \"radio\" moeten een \"tabindex\"-attribuut hebben om navigatie met alleen het toetsenbord mogelijk te maken."},"guidelines":[],"tags":["form","content"],"components":["placeholder"],"options":{"attribute":"tabindex","empty":true,"selector":"input[type=radio]"}},"inputSubmitHasTabIndex":{"type":"placeholder","testability":1,"title":{"en":"All \"submit\" input elements require a \"tabindex\" attribute","nl":"Alle invoerelementen van het type \"submit\" moeten een geldig \"tabindex\"-attribuut hebben"},"description":{"en":"All input elements of type \"submit\" should have a \"tabindex\" attribute to help navigate the form with a keyboard alone.","nl":"Alle input-elementen van het type \"submit\" moeten een \"tabindex\"-attribuut hebben om navigatie met alleen het toetsenbord mogelijk te maken."},"guidelines":[],"tags":["form","content"],"components":["placeholder"],"options":{"attribute":"tabindex","empty":true,"selector":"input[type=submit]"}},"inputTextHasLabel":{"type":"label","testability":1,"title":{"en":"All \"input\" elements should have a corresponding \"label\"","nl":"Alle invoerelementen moeten een bijbehorend \"label\" hebben"},"description":{"en":"All input elements should have a corresponding label element. Screen readers often enter a \"form mode\" where only label text is read aloud to the user","nl":"Alle input-elementen moeten een bijbehorend label-element hebben. Schermlezers maken vaak gebruik van een \"formuliereninstelling\" waarbij alleen de tekst van de labels hardop aan de gebruiker wordt voorgelezen."},"guidelines":{"wcag":{"1.1.1":{"techniques":["H44"]},"1.3.1":{"techniques":["H44","F68"]},"2.1.1":{"techniques":["H91"]},"2.1.3":{"techniques":["H91"]},"3.3.2":{"techniques":["H44"]},"4.1.2":{"techniques":["H44","H91"]}}},"tags":["form","content"],"options":{"selector":"input[type=text]"}},"inputTextHasTabIndex":{"type":"placeholder","testability":1,"title":{"en":"All \"text\" input elements require a valid \"tabindex\" attribute","nl":"Alle invoerelementen van het type \"text\" moeten een geldig \"tabindex\"-attribuut hebben"},"description":{"en":"All input elements of type \"text\" should have a \"tabindex\" attribute to help navigate the form with a keyboard alone.","nl":"Alle input-elementen van het type \"text\" moeten een \"tabindex\"-attribuut hebben om navigatie met alleen het toetsenbord mogelijk te maken."},"guidelines":[],"tags":["form","content"],"components":["placeholder"],"options":{"attribute":"tabindex","empty":true,"selector":"input[type=text]"}},"inputTextHasValue":{"type":"placeholder","testability":1,"title":{"en":"All \"input\" elements of type \"text\" must have a default text","nl":"Alle invoerelementen van het type \"text\" moeten een standaardtekst hebben"},"description":{"en":"All input elements of type \"text\" should have a default text.","nl":"Alle invoerelementen van het type \"text\" moeten een standaardtekst hebben."},"guidelines":[],"tags":["form","content"],"components":["placeholder"],"options":{"attribute":"value","empty":true,"selector":"input[type=text]"}},"inputTextValueNotEmpty":{"type":"placeholder","testability":1,"title":{"en":"Text input elements require a non-whitespace default text","nl":"Tekstinvoerelementen mogen geen lege standaardtekst hebben"},"description":{"en":"All input elements with a type of \"text\" should have a default text which is not empty.","nl":"Alle invoerelementen van het type \"text\" moeten een standaardtekst hebben die gevuld is."},"guidelines":[],"tags":["form","content"],"components":["placeholder"],"options":{"attribute":"value","empty":true,"selector":"input[type=text]"}},"inputWithoutLabelHasTitle":{"type":"custom","testability":1,"title":{"en":"Form controls without label should have a title attribute","nl":"Formulierelementen zonder label moeten een titelattribuut hebben"},"description":{"en":"If it is not possible to have a label for a form control, then a title attribute on the element should be provided that describes the purpose of the control.","nl":"Als een formulierelement geen label kan krijgen, dan moet een dat element een titelattribuut krijgen dat het doel van het element beschrijft."},"guidelines":{"wcag":{"1.1.1":{"techniques":["H65"]},"1.3.1":{"techniques":["H65"]},"3.3.2":{"techniques":["H65"]},"4.1.2":{"techniques":["H65"]}}},"tags":["form","content"],"components":["placeholder"],"callback":"inputWithoutLabelHasTitle"},"labelDoesNotContainInput":{"type":"selector","testability":1,"title":{"en":"Label elements should not contain an input element","nl":"Labelelementen moeten geen invoerelementen bevatten"},"description":{"en":"Label elements should not wrap around another input element, as this can cause the label to be read twice by screen readers.","nl":"Labelelementen moeten niet om een ander invoerelement heenstaan, omdat dan het label twee keer kan worden voorgelezen door schermlezers."},"guidelines":[],"tags":["form","content"],"options":{"selector":"label:has(input)"}},"labelMustBeUnique":{"type":"custom","testability":1,"title":{"en":"Every form input must have only one label","nl":"Elk formulierinvoerveld heeft maar een label"},"description":{"en":"Each form input should have only one label element.","nl":"Elk formulierinvoerveld mag maar een label element hebben."},"guidelines":{"wcag":{"1.3.1":{"techniques":["F17"]},"4.1.1":{"techniques":["F17"]}}},"tags":["form","content"],"callback":"labelMustBeUnique"},"labelMustNotBeEmpty":{"type":"placeholder","testability":1,"title":{"en":"Labels must contain text","nl":"Labels moeten tekst bevatten"},"description":{"en":"Labels in forms must contain readable text that describes the target form element.","nl":"Labels in formulieren moeten leesbare tekst bevatten die het formulierelement beschrijven."},"guidelines":{"wcag":{"1.1.1":{"techniques":["H44"]},"1.3.1":{"techniques":["H44","F68"]},"3.3.2":{"techniques":["H44"]},"4.1.2":{"techniques":["H44"]}}},"tags":["form","content"],"components":["placeholder"],"options":{"content":true,"empty":true,"selector":"label"}},"labelsAreAssignedToAnInput":{"type":"custom","testability":1,"title":{"en":"All labels should be associated with an input","nl":"Alle labels moeten horen bij een invoerveld"},"description":{"en":"All label elements should be assigned to an input item, and should have a for attribute which equals the id attribute of a form element.","nl":"Alle label-elementen moeten horen bij een invoerveld, en moeten een een for-attribuut hebben dat hetzelfde is als het id-attribuut van een formulierelement."},"guidelines":[],"tags":["form","content"],"callback":"labelsAreAssignedToAnInput"},"languageDirAttributeIsUsed":{"type":"custom","testability":0.5,"title":{"en":"Use the dir attribute when the language direction changes","nl":"Gebruik het dir-attribuut als de richting van de taal verandert"},"description":{"en":"When there are nested directional changes in text, use an inline element with a dir attribute to indicate direction.","nl":"Gebruik een inline element met een dir-attribuut om richting aan te geven wanneer er geneste richtingsveranderingen in de tekst zijn."},"guidelines":{"wcag":{"1.3.2":{"techniques":["H56"]}}},"tags":["language","content"],"callback":"languageDirAttributeIsUsed","components":["language"]},"languageChangesAreIdentified":{"type":"custom","testability":0.5,"title":{"en":"Use language attributes to indicate changes in language","nl":"Gebruik het taal-attribuut om aan te geven dat de taal verandert"},"description":{"en":"When the language of the document changes, make sure to wrap those changes in an element with the lang attribute.","nl":"Als de taal van het document verandert, zet deze veranderingen dan in een element met het lang-attribuut."},"guidelines":{"wcag":{"3.1.2":{"techniques":["H58"]}}},"tags":["language","content"],"callback":"languageChangesAreIdentified","components":["language"]},"languageDirectionPunctuation":{"type":"custom","testability":0.5,"title":{"en":"Place punctuation around language direction changes in the right order","nl":"Zet interpunctie bij richtingsveranderingen in taal in de juiste volgorde"},"description":{"en":"If punctuation is used around a change in language direction, ensure the punctuation appears in the correct place.","nl":"Als er interpunctie staat bij een richtingsverandering in de taal, zorg dat deze dan op de goede plek staat."},"guidelines":{"wcag":{"1.3.2":{"techniques":["G57"]}}},"tags":["language","content"],"callback":"languageDirectionPunctuation","components":["language"]},"languageUnicodeDirection":{"type":"custom","testability":1,"title":{"en":"Use the unicode language direction","nl":"Gebruik de unicode taalrichting"},"description":{"en":"When there are nested directional changes in language, use unicode RTL/LTR characters.","nl":"Gebruik de unicode RTL/LTR afkortingen als er geneste richtingsveranderingen in de taal zijn."},"guidelines":{"wcag":{"1.3.2":{"techniques":["H34"]}}},"tags":["language","content"],"callback":"languageUnicodeDirection","components":["language"]},"legendDescribesListOfChoices":{"type":"selector","testability":0,"title":{"en":"All \"legend\" elements must describe the group of choices","nl":"Alle \"legend\"-elementen moeten een groep keuzes beschrijven"},"description":{"en":"If a legend element is used in a fieldset, the legend content must describe the group of choices.","nl":"Als een legend-element wordt gebruikt in een fieldset, moet de legend content de groep keuzes beschrijven."},"guidelines":{"wcag":{"2.4.6":{"techniques":["G131"]}}},"tags":["form","content"],"options":{"selector":"legend"}},"legendTextNotEmpty":{"type":"selector","testability":1,"title":{"en":"Legend text must not contain just whitespace","nl":"Legend-tekst moet ingevuld zijn"},"description":{"en":"If a legend element is used in a fieldset, the legend should not contain empty text.","nl":"Als een legend-element wordt gebruikt in een fieldset, moet de legend ingevuld zijn."},"guidelines":{"wcag":{"1.3.1":{"techniques":["H71"]},"2.4.6":{"techniques":["G131"]},"3.3.2":{"techniques":["H71"]}}},"tags":["form","content"],"options":{"selector":"legend:empty"}},"legendTextNotPlaceholder":{"type":"placeholder","testability":1,"title":{"en":"\"Legend\" text must not contain placeholder text","nl":"\"Legend\"-tekst moet geen placeholdertekst bevatten"},"description":{"en":"If a legend element is used in a fieldset, the legend should not contain useless placeholder text like \"form\" or \"field\".","nl":"Als een legend-element wordt gebruikt in een fieldset, moet de legend geen placeholdertekst bevatten zoals \"form\" of \"field\"."},"guidelines":{"wcag":{"1.3.1":{"techniques":["H71"]},"2.1.1":{"techniques":["H91"]},"2.4.6":{"techniques":["G131"]},"3.3.2":{"techniques":["H71"]},"4.1.3":{"techniques":["H91"]}}},"tags":["form","content"],"components":["placeholder"],"options":{"content":true,"emtpy":true,"selector":"legend"}},"liDontUseImageForBullet":{"type":"selector","testability":0.5,"guidelines":[],"tags":["list","content"],"options":{"selector":"li:has(img)"}},"linkHasAUniqueContext":{"type":"custom","testability":1,"title":{"en":"Links should have a unique context","nl":"Links moeten een unieke context hebben"},"description":{"en":"","nl":""},"guidelines":[],"tags":["link","content"],"callback":"linkHasAUniqueContext"},"linkUsedForAlternateContent":{"type":"selector","testability":0,"title":{"en":"Use a \"link\" element for alternate content","nl":"Gebruik een \"link\"-element for andersoortige content"},"description":{"en":"Documents which contain things like videos, sound, or other forms of media that are not accessible, should provide a link element with a \"rel\" attribute of \"alternate\" in the document header.","nl":"Documenten die content zoals video's, geluid of andere niet-toegankelijke vormen van media bevatten, moeten een link-element met een \"rel\"-attribuut of \"alternate\" in de documentheaderlink aanbieden."},"guidelines":[],"tags":["document"],"options":{"selector":"html:not(html:has(link[rel=alternate])) body"}},"linkUsedToDescribeNavigation":{"type":"selector","testability":1,"title":{"en":"The document uses link elements to describe navigation if it is within a collection.","nl":"Het document gebruikt link-elementen om navigatie te beschrijven wanneer het binnen een collectie staat."},"description":{"en":"The link element can provide metadata about the position of an HTML page within a set of Web units or can assist in locating content with a set of Web units.","nl":"Het link-element kan metadata bevatten over de positie van een HTML-pagina binnen een swet web units, of kan behulpzaamn zijn bij het lokaliseren van content binnen web units."},"guidelines":[],"tags":["document"],"options":{"selector":"html:not(html:has(link[rel=index]))"}},"listNotUsedForFormatting":{"type":"custom","testability":0,"title":{"en":"Lists should not be used for formatting","nl":"Lijsten worden niet gebruikt voor opmaak"},"description":{"en":"Lists like ul and ol are to provide a structured list, and should not be used to format text. This test views any list with just one item as suspicious, but should be manually reviewed.","nl":"Lijsten zoals ul en ol zijn bedoeld om gestructureerde lijsten te maken. Ze moeten niet gebruikt worden om text op te maken. Controleer of deze lijst echt bedoeld is als lijst of om tekst op te maken."},"guidelines":{"wcag":{"1.3.2":{"techniques":["F1"]}}},"tags":["list","content"],"callback":"listNotUsedForFormatting"},"listOfLinksUseList":{"type":"custom","testability":1,"title":{"en":"A list of links separated by non-readable characters should be in an ul or ol","nl":"Een lijst van links die worden gescheiden door onleesbare tekens moeten in een bulleted of genummerde lijst staan"},"description":{"en":"A list of links without separation between them should be placed in an ol or ul element.","nl":"Een lijst van links die niet duidelijk gescheiden zijn moeten in een bulleted of genummerde lijst staan."},"guidelines":{"wcag":{"1.3.1":{"techniques":["H48"]}}},"tags":["link","content"],"callback":"listOfLinksUseList"},"marqueeIsNotUsed":{"type":"selector","testability":1,"title":{"en":"The \"marquee\" tag should not be used","nl":"De \"marquee\"-tag wordt niet gebruikt"},"description":{"en":"The marquee element is difficult for users to read and is not a standard HTML element. Try to find another way to convey the importance of this text.","nl":"Het marquee-element is moeilijk te lezen voor gebruikers en is geen standaard HTML-element. Gebruik een andere manier om aan te duiden dat het belangrijke content is."},"guidelines":[],"tags":["deprecated","content"],"options":{"selector":"marquee"}},"menuNotUsedToFormatText":{"type":"selector","testability":0,"title":{"en":"Menu elements should not be used for formatting","nl":"Menu-elementen worden niet gebruikt voor opmaak"},"description":{"en":"Menu is a deprecated tag, but is still honored in a transitional DTD. Menu tags are to provide structure for a document and should not be used for formatting. If a menu tag is to be used, it should only contain an ordered or unordered list of links.","nl":"Menu is een afgekeurd tag, maar wordt nog wel gebruikt om structuur aan een document te geven. Het mag niet worden gebruikt voor opmaak. Als een menu-tag wordt gebruikt, mag het alleen bulleted of genummerde lijsten bevatten."},"guidelines":[],"tags":["list","content"],"options":{"selector":"menu:not(menu li:parent(menu))"}},"newWindowIsOpened":{"type":"custom","testability":1,"title":{"en":"A link should not open a new window","nl":"Een link opent geen nieuw scherm"},"description":{"en":"Avoid confusion that may be caused by the appearance of new windows that were not requested by the user.","nl":"Voorkom verwarring die veroorzaakt wordt door het openen van nieuwe schermen die de gebruiker niet verwacht."},"guidelines":{"wcag":{"2.0.0":{"techniques":["H83"]}}},"tags":["javascript","html"],"callback":"newWindowIsOpened"},"noembedHasEquivalentContent":{"type":"selector","testability":0,"title":{"en":"Noembed elements must be the same content as their \"embed\" element","nl":"Noembed-elementen moeten dezelfde content hebben als hun \"embed\"-element"},"description":{"en":"All noembed elements must contain or link to an accessible version of their embed counterparts.","nl":"Alle noembed-elementen moeten een toegankelijke versie van hun embed-tegenhangers bevatten of hier naar linken."},"guidelines":[],"tags":["objects","content"],"options":{"selector":"noembed"}},"noframesSectionMustHaveTextEquivalent":{"type":"selector","testability":0.5,"title":{"en":"All \"noframes\" elements should contain the text content from all frames","nl":"Alle \"noframes\"-elementen moeten de content van alle frames bevatten"},"description":{"en":"The noframes content should either replicate or link to the content visible within the frames.","nl":"The noframes-content moet de zichtbare content binnen de frames repliceren of er naar linken."},"guidelines":[],"tags":["deprecated","frame"],"options":{"selector":"frameset:not(frameset:has(noframes))"}},"objectContentUsableWhenDisabled":{"type":"selector","testability":0,"title":{"en":"When objects are disabled, content should still be available","nl":"Als objecten zijn uitgeschakeld, moet de content nog wel beschikbaar zijn"},"description":{"en":"The content within objects should still be available, even if the object is disabled. To do this, place a link to the direct object source within the object tag.","nl":"Content binnen objecten moet beschikbaar blijven, ook als het object is uitgeschakeld. Plaats hiervoor een link naar de bron van het object binnen de object-tag."},"guidelines":[],"tags":["objects","content"],"options":{"selector":"object"}},"objectDoesNotFlicker":{"type":"selector","testability":0,"title":{"en":"Objects do not flicker","nl":"Objecten knipperen of flitsen niet"},"description":{"en":"The content within an object tag must not flicker.","nl":"De content binnen een object-tag knippert of flitst niet."},"guidelines":{"508":["j"],"wcag":{"2.2.2":{"techniques":["F7"]}}},"tags":["objects","content"],"options":{"selector":"object"}},"objectDoesNotUseColorAlone":{"type":"selector","testability":0,"title":{"en":"Objects must not use color to communicate alone","nl":"Objecten gebruiken meer dan alleen kleur om hun boodschap over te brengen"},"description":{"en":"Objects should contain content that makes sense without color and is accessible to users who are color blind.","nl":"Objecten moeten content bevatten die duidelijk is zonder het kleurgebruik en toegankelijk is voor gebruikers met kleurenblindheid."},"guidelines":{"508":["c"]},"tags":["objects","content"],"options":{"selector":"object"}},"objectInterfaceIsAccessible":{"type":"selector","testability":0,"title":{"en":"Interfaces within objects must be accessible","nl":"Interfaces binnen objecten moeten toegankelijk zijn"},"description":{"en":"Object content should be assessed for accessibility.","nl":"Content binnen objecten moeten gecontroleerd worden op toegankelijkheid."},"guidelines":[],"tags":["objects","content"],"options":{"selector":"object"}},"objectLinkToMultimediaHasTextTranscript":{"type":"selector","testability":0,"title":{"en":"Objects which reference multimedia files should also provide a link to a transcript","nl":"Objecten die verwijzen naar multimediabestanden moeten ook een link aanbieden naar de transcriptie"},"description":{"en":"If an object contains a video, a link to the transcript should be provided near the object.","nl":"Als een object een video bevat, moet een link naar de transcriptie hiervan worden aangeboden bij het object."},"guidelines":[],"tags":["objects","content"],"options":{"selector":"object"}},"objectMustContainText":{"type":"placeholder","testability":1,"title":{"en":"Objects must contain their text equivalents","nl":"Objecten moeten hun tekstuele equivalent bevatten"},"description":{"en":"All object elements should contain a text equivalent if the object cannot be rendered.","nl":"Alle object-elementen moeten een tekstequivalent bevatten in het geval het object niet getoond kan worden."},"guidelines":{"wcag":{"1.1.1":{"techniques":["FLASH1","H27"]}}},"tags":["objects","content"],"components":["placeholder"],"options":{"content":true,"empty":true,"selector":"object"}},"objectMustHaveEmbed":{"type":"selector","testability":1,"title":{"en":"Every object should contain an \"embed\" element","nl":"Elk object moet een \"embed\"-element bevatten"},"description":{"en":"Every object element must also contain an embed element.","nl":"Elk object-element moet ook een \"embed\"-element bevatten."},"guidelines":[],"tags":["objects","content"],"options":{"selector":"object:not(object:has(embed))"}},"objectMustHaveTitle":{"type":"selector","testability":1,"title":{"en":"Objects should have a title attribute","nl":"Objecten moeten een titelattribuut hebben"},"description":{"en":"All object elements should contain a \"title\" attribute.","nl":"Alle object-elementen moeten een \"titel\"-attribuut bevatten."},"guidelines":{"wcag":{"1.1.1":{"techniques":["H27"]}}},"tags":["objects","content"],"options":{"selector":"object:not(object[title])"}},"objectMustHaveValidTitle":{"type":"placeholder","testability":1,"title":{"en":"Objects must not have an empty title attribute","nl":"Objecten hebben geen leeg titelattribuut"},"description":{"en":"All object elements should have a \"title\" attribute which is not empty.","nl":"All object-elementen hebben een \"titel\"-attribuut dat gevuld is."},"guidelines":[],"tags":["objects","content"],"components":["placeholder"],"options":{"attribute":"title","empty":true,"selector":"object"}},"objectProvidesMechanismToReturnToParent":{"type":"selector","testability":0,"title":{"en":"All objects should provide a way for keyboard users to escape","nl":"Alle objecten moeten een manier bevatten voor toetsenbordgebruikers een manier om het object te verlaten"},"description":{"en":"Ensure that a user who has only a keyboard as an input device can escape a object element. This requires manual confirmation.","nl":"Zorg ervoor dat een gebruiker die alleen het toetsenbord als bediening gebruikt een object-element. Hiervoor is handmatige bevestiging nodig."},"guidelines":[],"tags":["objects","content"],"options":{"selector":"object"}},"objectShouldHaveLongDescription":{"type":"selector","testability":0,"title":{"en":"An object might require a long description","nl":"Een object heeft soms een lange beschrijving nodig"},"description":{"en":"Objects might require a long description, especially if their content is complicated.","nl":"Objecten hebben soms een lange beschrijving nodig, zeker in het geval van ingewikkelde content."},"guidelines":[],"tags":["objects","content"],"options":{"selector":"object"}},"objectTextUpdatesWhenObjectChanges":{"type":"selector","testability":0,"title":{"en":"The text equivalents of an object should update if the object changes","nl":"De tekstuele equivalent van een object moet bijgewerkt worden als het object verandert"},"description":{"en":"If an object changes, the text equivalent of that object should also change.","nl":"Als een object verandert, moet zijn tekstuele equivalent ook veranderen."},"guidelines":{"508":["a"]},"tags":["objects","content"],"options":{"selector":"object"}},"objectUIMustBeAccessible":{"type":"selector","testability":0,"title":{"en":"Content within an \"object\" element should be usable with objects disabled","nl":"Content binnen een \"object\"-element moet bruikbaar blijven als het object uitgeschakeld is"},"description":{"en":"Objects who's content changes using java, ActiveX, or other similar technologies, should have their default text change when the object's content changes.","nl":"Van objecten waarvan de content java, ActiveX of vergelijkbare technologie�n gebruiken, moet de standaardtekst veranderen als de content van het object verandert."},"guidelines":[],"tags":["objects","content"],"options":{"selector":"object"}},"objectWithClassIDHasNoText":{"type":"selector","testability":1,"title":{"en":"Objects with \"classid\" attributes should change their text if the content of the object changes","nl":"Objecten met \"classid\"-attributen moeten hun tekst veranderen wanneer de content van het object verandert"},"description":{"en":"Objects with \"classid\" attributes, should have their default text change when the object's content changes.","nl":"Van objecten met \"classid\"-attributen moet de standaardtekst veranderen als de content van het object verandert."},"guidelines":[],"tags":["objects","content"],"options":{"selector":"object[classid]:not(object[classid]:empty)"}},"pNotUsedAsHeader":{"type":"custom","testability":0.5,"title":{"en":"Paragraphs must not be used for headers","nl":"Alinea's worden niet gebruikt als header"},"description":{"en":"Headers are extremely useful for non-sighted users to navigate the structure of the page. Formatting a paragraph to just be big or bold, while it might visually look like a header, does not make it a header.","nl":"Headers van h1 - h6 zijn handig voor blinde en slechtziende gebruikers om door een pagina te navigeren. Maak alinea's daarom niet op zodat deze lijkt op een header. Dit werkt verwarrend."},"guidelines":{"wcag":{"1.3.1":{"techniques":["G141","H42"]},"2.4.10":{"techniques":["G141"]}}},"tags":["header","content"],"callback":"pNotUsedAsHeader"},"paragraphIsWrittenClearly":{"type":"custom","testability":0.5,"guidelines":{"wcag":{"3.1.5":{"techniques":["G86"]}}},"tags":["language","content"],"components":["textStatistics"],"callback":"paragraphIsWrittenClearly"},"passwordHasLabel":{"type":"label","testability":1,"title":{"en":"All password input elements should have a corresponding label","nl":"Alle paswoordinvoerelementen hebben een bijbehorend label"},"description":{"en":"All input elements with a type of \"password\"should have a corresponding label element. Screen readers often enter a \"form mode\" where only label text is read aloud to the user","nl":"Alle input-elementen van het type \"paswoord\" moeten een bijbehorend label-element hebben. Schermlezers maken vaak gebruik van een \"formuliereninstelling\" waarbij alleen de tekst van de labels hardop aan de gebruiker wordt voorgelezen."},"guidelines":{"508":["n"],"wcag":{"1.1.1":{"techniques":["H44"]},"1.3.1":{"techniques":["H44","F68"]},"2.1.1":{"techniques":["H91"]},"2.1.3":{"techniques":["H91"]},"3.3.2":{"techniques":["H44"]},"4.1.2":{"techniques":["H44","H91"]}}},"tags":["form","content"],"components":["label"],"options":{"selector":"input[type=password]"}},"passwordLabelIsNearby":{"type":"labelProximity","testability":0.5,"title":{"en":"All \"password\" input elements have a label that is close","nl":"Alle paswoordinvoerelementen hebben een label dat dicht bij het element staat"},"description":{"en":"All input elements of type \"password\" must have a corresponding label that is close to the form element. Users of screen magnification or with reduced spatial skills are hampered in using a form element if the label for that element is located far away.","nl":"Alle inputelementen van het type \"paswoord\" moeten een bijbehorend label hebben dat dicht bij het formulierelement staat. Gebruikers die het scherm vergroten of met beperkte ruimtelijke vaardigheden kunnen een formulier niet gebruiken als het label van een veld te ver weg staat."},"guidelines":[],"tags":["form","content"],"components":["labelProximity"],"options":{"selector":"input[type=password]"}},"preShouldNotBeUsedForTabularLayout":{"type":"custom","testability":0,"title":{"en":"Pre elements should not be used for tabular data","nl":"Pre-elementen worden niet gebruikt om data als tabel te rangschikken"},"description":{"en":"If a pre element is used for tabular data, change the data to use a well-formed table.","nl":"Als een pre-element wordt gebruikt om data als tabel te rangschikken, verander de data dan zodat je een echte tabel kunt maken."},"guidelines":{"wcag":{"1.3.1":{"techniques":["F33","F34","F48"]},"1.3.2":{"techniques":["F33","F34"]}}},"tags":["table","content"],"callback":"preShouldNotBeUsedForTabularLayout"},"radioHasLabel":{"type":"label","testability":1,"title":{"en":"All \"radio\" input elements have a corresponding label","nl":"Alle invoerelementen van het type \"radio\" hebben een bijbehorend label"},"description":{"en":"All input elements of type \"radio\" should have a corresponding label element. Screen readers often enter a \"form mode\" where only label text is read aloud to the user","nl":"Alle input-elementen van het \"radio\" moeten een bijbehorend label-element hebben. Schermlezers maken vaak gebruik van een \"formuliereninstelling\" waarbij alleen de tekst van de labels hardop aan de gebruiker wordt voorgelezen."},"guidelines":{"508":["n"],"wcag":{"1.1.1":{"techniques":["H44"]},"1.3.1":{"techniques":["H44","F68"]},"2.1.1":{"techniques":["H91"]},"2.1.3":{"techniques":["H91"]},"3.3.2":{"techniques":["H44"]},"4.1.2":{"techniques":["H44","H91"]}}},"tags":["form","content"],"components":["label"],"options":{"selector":"input[type=radio]"}},"radioLabelIsNearby":{"type":"labelProximity","testability":0.5,"title":{"en":"All \"radio\" input elements have a label that is close","nl":"Alle invoerelementen van het type \"radio\" hebben een label dat dicht bij het element staat"},"description":{"en":"All input elements of type \"radio\" must have a corresponding label that is close to the form element. Users of screen magnification or with reduced spatial skills are hampered in using a form element if the label for that element is located far away.","nl":"Alle inputelementen van het type \"radio\" moeten een bijbehorend label hebben dat dicht bij het formulierelement staat. Gebruikers die het scherm vergroten of met beperkte ruimtelijke vaardigheden kunnen een formulier niet gebruiken als het label van een veld te ver weg staat."},"guidelines":[],"tags":["form","content"],"components":["labelProximity"],"options":{"selector":"input[type=radio]"}},"radioMarkedWithFieldgroupAndLegend":{"type":"selector","testability":1,"title":{"en":"All radio button groups are marked using fieldset and legend elements","nl":"Alle groepjes van radio buttons zijn gemarkeerd met fieldset- en legend-elementen"},"description":{"en":"Form element content must contain both fieldset and legend elements if there are related radio buttons.","nl":"Content van formulierelementen moeten zowel fieldset- als legend-elementen bevatten als er gerelateerde radio buttons instaan."},"guidelines":{"wcag":{"1.3.1":{"techniques":["H71"]},"3.3.2":{"techniques":["H71"]}}},"tags":["form","content"],"options":{"selector":"input[type=radio]:not(fieldset input[type=radio])"}},"scriptContentAccessibleWithScriptsTurnedOff":{"type":"selector","testability":0,"title":{"en":"Content on the page should still be available if scripts are disabled","nl":"Content op de pagina moet beschikbaar blijven als scripts zijn uitgeschakeld"},"description":{"en":"All scripts should be assessed to see if, when the user is browsing with scrips turned off, the page content is still available.","nl":"Alle scripts moeten gecontroleerd worden of, wanneer een gebruiker scripts heeft uitgezet, de content van de pagina nog steeds beschikbaar is."},"guidelines":[],"tags":["javascript"],"options":{"selector":"script"}},"scriptInBodyMustHaveNoscript":{"type":"selector","testability":0.5,"title":{"en":"Scripts should have a corresponding \"noscript\" element","nl":"Scripts moeten een bijbehorend \"noscript\"-element hebben"},"description":{"en":"Scripts should be followed by a noscripts element to guide the user to content in an alternative way.","nl":"Scripts moeten worden gevolgd door een noscripts-element om de gebruiker de weg te wijzen naar de content op een andere manier."},"guidelines":{"508":["l"]},"tags":["javascript"],"options":{"selector":"html:not(html:has(noscript)):has(script) body"}},"scriptOnclickRequiresOnKeypress":{"type":"event","testability":1,"title":{"en":"If an element has an \"onclick\" attribute it should also have an \"onkeypress\" attribute","nl":"Als een element een \"onclick\"-attribuut heeft, moet het ook een \"onkeypress\"-attribuut hebben"},"description":{"en":"If an element has an \"onclick\" attribute it should also have an \"onkeypress\" attribute","nl":"Als een element een \"onclick\"-attribuut heeft, moet het ook een \"onkeypress\"-attribuut hebben"},"guidelines":{"508":["l"],"wcag":{"2.1.1":{"techniques":["G90","SCR2","SCR20"]},"2.1.3":{"techniques":["G90","SCR20"]}}},"tags":["javascript"],"components":["event","hasEventListener"],"options":{"correspondingEvent":"onkeypress","searchEvent":"onclick"}},"scriptOndblclickRequiresOnKeypress":{"type":"event","testability":1,"title":{"en":"Any element with an \"ondblclick\" attribute should have a keyboard-related action as well","nl":"Elk element met een \"ondblclick\"-attribuut moet een vergelijkbare actie hebben die kan worden uitgevoerd met een toetsenbord"},"description":{"en":"If an element has an \"ondblclick\" attribute, it should also have a keyboard-related action.","nl":"Als een element een \"ondblclick\"-attribuut heeft, moet het ook een actie bevatten die kan worden uitgevoerd met een toetsenbord."},"guidelines":{"508":["l"],"wcag":{"2.1.1":{"techniques":["G90","SCR2","SCR20"]},"2.1.3":{"techniques":["G90","SCR20"]}}},"tags":["javascript"],"components":["event","hasEventListener"],"options":{"correspondingEvent":"onkeypress","searchEvent":"ondblclick"}},"scriptOnmousedownRequiresOnKeypress":{"type":"event","testability":1,"title":{"en":"If an element has a \"mousedown\" attribute it should also have an \"onkeydown\" attribute","nl":"Als een element een \"mousedown\"-attribuut heeft moet het ook een \"onkeydown\"-attribuut hebben"},"description":{"en":"If an element has a \"mousedown\" attribute it should also have an \"onkeydown\" attribute.","nl":"Als een element een \"mousedown\"-attribuut heeft moet het ook een \"onkeydown\"-attribuut hebben."},"guidelines":{"508":["l"],"wcag":{"2.1.1":{"techniques":["G90","SCR2","SCR20"]},"2.1.3":{"techniques":["G90","SCR20"]}}},"tags":["javascript"],"components":["event","hasEventListener"],"options":{"correspondingEvent":"onkeydown","searchEvent":"onmousedown"}},"scriptOnmousemove":{"type":"event","testability":1,"title":{"en":"Any element with an \"onmousemove\" attribute should have a keyboard-related action as well","nl":"Elk element met een \"onmousemove\"-attribuut moet een vergelijkbare actie hebben die kan worden uitgevoerd met een toetsenbord"},"description":{"en":"If an element has an \"onmousemove\" attribute it should have a keyboard-related action as well.","nl":"Als een element een \"onmousemove\"-attribuut heeft, moet het een vergelijkbare actie hebben die kan worden uitgevoerd met een toetsenbord."},"guidelines":{"508":["l"],"wcag":{"2.1.1":{"techniques":["G90","SCR2","SCR20"]},"2.1.3":{"techniques":["G90","SCR20"]}}},"tags":["javascript"],"components":["event","hasEventListener"],"options":{"correspondingEvent":"onkeypress","searchEvent":"onmousemove"}},"scriptOnmouseoutHasOnmouseblur":{"type":"event","testability":1,"title":{"en":"If an element has a \"onmouseout\" attribute it should also have an \"onblur\" attribute","nl":"Als een element een \"onmouseout\"-attribuut heeft, moet het ook een \"onblur\" attribuut hebben"},"description":{"en":"If an element has a \"onmouseout\" attribute it should also have an \"onblur\" attribute.","nl":"Als een element een \"onmouseout\"-attribuut heeft, moet het ook een \"onblur\"-attribuut hebben."},"guidelines":{"508":["l"],"wcag":{"2.1.1":{"techniques":["G90","SCR2","SCR20"]},"2.1.3":{"techniques":["G90","SCR20"]}}},"tags":["javascript"],"components":["event","hasEventListener"],"options":{"correspondingEvent":"onblur","searchEvent":"onmouseout"}},"scriptOnmouseoverHasOnfocus":{"type":"event","testability":1,"title":{"en":"If an element has a \"onmouseover\" attribute it should also have an \"onfocus\" attribute","nl":"Als een element een \"onmouseover\"-attribuut heeft, moet het ook een \"onfocus\"-attribuut hebben"},"description":{"en":"If an element has a \"onmouseover\" attribute it should also have an \"onfocus\" attribute.","nl":"Als een element een \"onmouseover\"-attribuut heeft, moet het ook een \"onfocus\"-attribuut hebben."},"guidelines":{"508":["l"],"wcag":{"2.1.1":{"techniques":["G90","SCR2","SCR20"]},"2.1.3":{"techniques":["G90","SCR20"]}}},"tags":["javascript"],"components":["event","hasEventListener"],"options":{"correspondingEvent":"onfocus","searchEvent":"onmouseover"}},"scriptOnmouseupHasOnkeyup":{"type":"event","testability":1,"title":{"en":"If an element has a \"onmouseup\" attribute it should also have an \"onkeyup\" attribute","nl":"Als een element een \"onmouseup\"-attribuut heeft, moet het ook een \"onkeyup\"-attribuut hebben"},"description":{"en":"If an element has a \"onmouseup\" attribute it should also have an \"onkeyup\" attribute.","nl":"Als een element een \"onmouseup\"-attribuut heeft, moet het ook een \"onkeyup\"-attribuut hebben."},"guidelines":{"508":["l"],"wcag":{"2.1.1":{"techniques":["G90","SCR2","SCR20"]},"2.1.3":{"techniques":["G90","SCR20"]}}},"tags":["javascript"],"components":["event","hasEventListener"],"options":{"correspondingEvent":"onkeyup","searchEvent":"onmouseup"}},"scriptUIMustBeAccessible":{"type":"selector","testability":0,"title":{"en":"The user interface for scripts should be accessible","nl":"De user interface voor scripts moet toegankelijk zijn"},"description":{"en":"All scripts should be assessed to see if their interface is accessible.","nl":"Alle scripts moeten gecontroleerd worden op toegankelijkheid van hun interface."},"guidelines":{"508":["l"]},"tags":["javascript"],"options":{"selector":"script"}},"scriptsDoNotFlicker":{"type":"selector","testability":0,"title":{"en":"Scripts should not cause the screen to flicker","nl":"Scripts mogen het scherm niet laten knipperen of flitsen"},"description":{"en":"All scripts should be assessed to see if their interface does not flicker.","nl":"Alle scripts moeten gecontroleerd worden om te zien of zij de interface niet laten knipperen of flitsen."},"guidelines":{"508":["j"],"wcag":{"2.2.2":{"techniques":["F7"]}}},"tags":["javascript"],"options":{"selector":"script"}},"scriptsDoNotUseColorAlone":{"type":"selector","testability":0,"title":{"en":"The interface in scripts should not use color alone","nl":"De interface in scripts gebruikt niet alleen maar kleur"},"description":{"en":"All scripts should be assessed to see if their interface does not have an interface which requires distinguishing between colors alone.","nl":"Alle scripts moeten gecontroleerd worden om te zien of hun interface geen interface heeft die alleen op kleur kan worden onderscheiden."},"guidelines":{"508":["c"]},"tags":["javascript","color"],"options":{"selector":"script"}},"selectDoesNotChangeContext":{"type":"event","testability":1,"title":{"en":"\"Select\" elements must not contain an \"onchange\" attribute","nl":"\"Select\" elements bevatten geen \"onchange\" attribute"},"description":{"en":"Actions like \"onchange\" can take control away from users who are trying to navigate the page. Using an \"onchange\" attribute for things like select-list menus should instead be replaced with a drop-down and a button which initiates the action.","nl":"Acties als \"onchange\" kunnen de controle ontnemen van gebruikers die op een pagina proberen te navigeren. Het gebruik van een \"onchange\"-attribuut voor zaken zoals select-list menu's moet vervangen worden door een drop-down en een knop waarmee je de actie start."},"guidelines":[],"tags":["form","content"],"components":["event","hasEventListener"],"options":{"searchEvent":"onchange","selector":"select"}},"selectHasAssociatedLabel":{"type":"label","testability":1,"title":{"en":"All select elements have an explicitly associated label","nl":"Alle select-elementen hebben een expliciet bijbehorend label"},"description":{"en":"All select elements should have a corresponding label element. Screen readers often enter a \"form mode\" where only label text is read aloud to the user","nl":"Alle select-elementen moeten een bijbehorend label-element hebben. Schermlezers maken vaak gebruik van een \"formuliereninstelling\" waarbij alleen de tekst van de labels hardop aan de gebruiker wordt voorgelezen."},"guidelines":{"wcag":{"1.1.1":{"techniques":["H44"]},"1.3.1":{"techniques":["H44","F68"]},"2.1.1":{"techniques":["H91"]},"2.1.3":{"techniques":["H91"]},"3.3.2":{"techniques":["H44"]},"4.1.2":{"techniques":["H44","H91"]}}},"tags":["form","content"],"components":["label"],"options":{"selector":"select"}},"selectJumpMenu":{"type":"custom","testability":0.5,"title":{"en":"Select jump menus should jump on button press, not on state change","nl":"Select jump menu's moeten springen wanneer de knop wordt gebruikt, niet bij statusverandering"},"description":{"en":"If you wish to use a 'Jump' menu with a select item that then redirects users to another page, the jump should occur on the user pressing a button, rather than on the change event of that select element.","nl":"Als je een 'Jump'-menu wilt gebruiken met een select item dat gebruikers naar een andere pagina verwijst, moet de verwijzing plaatsvinden als de gebruiker een knop gebruikt en niet op het moment dat het select element verandert."},"guidelines":{"wcag":{"3.2.2":{"techniques":["F37"]},"3.2.5":{"techniques":["F9"]}}},"tags":["form","content"],"components":["hasEventListener"],"callback":"selectJumpMenu"},"selectWithOptionsHasOptgroup":{"type":"selector","testability":0.5,"title":{"en":"Form select elements should use optgroups for long selections","nl":"Formulier select-elementen moeten optgroups gebruiken voor lange selecties"},"description":{"en":"If a select element has many options, use optgroups to help ease navigation.","nl":"Als een select-element veel opties heeft, gebruik dan optgroups om navigatie makkelijker te maken."},"guidelines":{"wcag":{"1.3.1":{"techniques":["H85"]}}},"tags":["form","content"],"options":{"selector":"select:not(select:has(optgroup)) option:nth-child(5)"}},"siteMap":{"type":"custom","testability":0,"title":{"en":"Websites must have a site map","nl":"Websites moeten een sitemap hebben"},"description":{"en":"Every web site should have a page which provides a site map or another method to navigate most of the site from a single page to save time for users of assistive devices.","nl":"Elke website moet een pagina hebben waarop een sitemap staat of een andere methode om op de site te navigeren vanaf een pagina. Dit spaart gebruikers die hulpmiddelen gebruiken tijd."},"guidelines":{"wcag":{"2.4.5":{"techniques":["G63"]},"2.4.8":{"techniques":["G63"]}}},"tags":["document"],"strings":["siteMap"],"callback":"siteMap"},"skipToContentLinkProvided":{"type":"custom","testability":0.5,"title":{"en":"A \"skip to content\" link should exist as one of the first links on the page","nl":"Er moet een \"skip to content\"-link zijn als een van de eerste links op de pagina"},"description":{"en":"A link reading \"skip to content\" should be the first link on a page.","nl":"Er moet een link zijn om naar de content te navigeren als een van de eerste links op de pagina."},"guidelines":{"508":["o"],"wcag":{"2.4.1":{"techniques":["G1"]}}},"tags":["document"],"strings":["skipContent"],"callback":"skipToContentLinkProvided"},"svgContainsTitle":{"type":"selector","testability":1,"title":{"en":"Inline SVG should use Title elements","nl":"Inline SVG moet titelelementen gebruiken"},"description":{"en":"Any inline SVG image should have an embedded title element.","nl":"Elke inline SVG-afbeelding moet een ingebed title-element hebben."},"guidelines":{"wcag":{"1.1.1":{"techniques":["F65"]}}},"tags":["image","svg","content"],"options":{"selector":"svg:not(svg:has(title))"}},"tableAxisHasCorrespondingId":{"type":"custom","testability":1,"title":{"en":"Axis attribute should have corresponding IDs","nl":"Axis-attributen moeten bijbehorende IDs hebben"},"description":{"en":"When using the axis attribute to group cells together, ensure they have a target element with the same ID.","nl":"Wanneer er axis-attributen gebruikt worden om cellen te groeperen, zorg er dan voor dat hun doelelement hetzelfde ID heeft."},"guidelines":{"wcag":{"1.3.1":{"techniques":["F17"]},"4.1.1":{"techniques":["F17"]}}},"callback":"tableAxisHasCorrespondingId"},"tabIndexFollowsLogicalOrder":{"type":"custom","testability":0.5,"title":{"en":"The tab order of a document is logical","nl":"De tabvolgorde van een document is logisch"},"description":{"en":"Check that the tab order of a page is logical.","nl":"Controleer of de tabvolgorde van een pagina logisch is."},"guidelines":{"wcag":{"2.4.3":{"techniques":["H4"]}}},"tags":["document"],"callback":"tabIndexFollowsLogicalOrder"},"tableCaptionIdentifiesTable":{"type":"selector","testability":0,"title":{"en":"Captions should identify their table","nl":"Beschrijvingen moeten hun tabellen identificeren"},"description":{"en":"Check to make sure that a table's caption identifies the table with a name, figure number, etc.","nl":"Controleer of de beschrijving van een tabel de tabel identificeert met een naam, nummer en dergelijke."},"guidelines":{"wcag":{"1.3.1":{"techniques":["H39"]}}},"tags":["table","content"],"options":{"selector":"caption"}},"tableComplexHasSummary":{"type":"selector","testability":0.5,"title":{"en":"Complex tables should have a summary","nl":"Complexe tabellen moeten een samenvatting hebben"},"description":{"en":"If a table is complex (for example, has some cells with \"colspan\" attributes, the table should have a summary.","nl":"Als een tabel complex is (bijvoorbeeld, als er cellen zijn met \"colspan\"-attributen, moet de tabel een samenvatting hebben."},"guidelines":{"wcag":{"1.3.1":{"techniques":["H39"]}}},"tags":["table","content"],"options":{"selector":"table:not(table[summary], table:has(caption))"}},"tableDataShouldHaveTh":{"type":"selector","testability":1,"title":{"en":"Data tables should contain a header","nl":"Datatabellen moeten \"th\"-elementen bevatten"},"description":{"en":"Tables which contain data (as opposed to layout tables) should contain proper table header elements to mark them for screen readers and enhance the structure of the document.","nl":"Tabellen die data bevatten (in tegenstelling tot lay-out tabellen) moeten th-elementen bevatten om koppen te markeren voor schermlezers en om de structuur van het document te verbeteren."},"guidelines":{"508":["g"],"wcag":{"1.3.1":{"techniques":["F91"]}}},"tags":["table","content"],"options":{"selector":"table:not(table:has(th))"}},"tableHeaderLabelMustBeTerse":{"type":"custom","testability":0.5,"title":{"en":"Table header lables must be terse","nl":"Tabelkoppen moeten bondig zijn"},"description":{"en":"The \"abbr\" attribute for table headers must be terse (less than 20 characters long).","nl":"Het \"abbr\"-attribuut voor tabelkoppen moet bondig zijn (minder dan 20 tekens lang)."},"guidelines":[],"tags":["table","content"],"callback":"tableHeaderLabelMustBeTerse"},"tableIsGrouped":{"type":"selector","testability":0.5,"title":{"en":"Mark up the areas of tables using thead and tbody","nl":"Gebruik thead en tbody voor tabellen"},"description":{"en":"Mark up the areas of tables using thead and tbody.","nl":"Gebruik thead en tbody voor tabellen."},"guidelines":[],"tags":["table","content"],"options":{"selector":"table:not(table:has(thead), table:has(tfoot))"}},"tableLayoutDataShouldNotHaveTh":{"type":"custom","testability":0,"title":{"en":"Layout tables should not contain \"th\" elements","nl":"Lay-out tabellen bevatten geen \"th\"-elementen"},"description":{"en":"Tables which are used purely for layout (as opposed to data tables), should not contain th elements, which would make the table appear to be a data table.","nl":"Tabellen die alleen voor lay-out worden gebruikt (in tegenstelling tot datatabellen), moeten geen th-elementen bevatten, omdat deze de indruk wekken dat het een datatabel betreft."},"guidelines":{"wcag":{"1.3.1":{"techniques":["F46"]}}},"tags":["table","layout","content"],"callback":"tableLayoutDataShouldNotHaveTh"},"tableLayoutHasNoCaption":{"type":"custom","testability":1,"title":{"en":"All tables used for layout have no \"caption\" element","nl":"Alle tabellen die alleen voor lay-out worden gebruikt hebben geen \"caption\"-element"},"description":{"en":"If a table contains no data, and is used simply for layout, then it should not contain a caption element.","nl":"Als een tabel geen data bevat en alle voor lay-out wordt gebruikt, moet hij geen caption-element krijgen."},"guidelines":{"wcag":{"1.3.1":{"techniques":["F46"]}}},"tags":["table","layout","content"],"callback":"tableLayoutHasNoCaption"},"tableLayoutHasNoSummary":{"type":"custom","testability":0.5,"title":{"en":"All tables used for layout have no summary or an empty summary","nl":"Alle tabellen die alleen voor lay-out worden gebruikt hebben geen samenvatting"},"description":{"en":"If a table contains no data, and is used simply for layout, then it should not have a \"summary\" attribute.","nl":"Als een tabel geen data bevat en alleen voor lay-out wordt gebruikt, moet hij geen \"summary\"-attribuut krijgen."},"guidelines":{"wcag":{"1.3.1":{"techniques":["F46"]}}},"tags":["table","layout","content"],"callback":"tableLayoutHasNoSummary"},"tableLayoutMakesSenseLinearized":{"type":"custom","testability":0,"title":{"en":"All tables used for layout should make sense when removed","nl":"Als tabellen voor lay-out worden gebruikt moet de pagina nog duidelijk blijven als de tabel wordt verwijderd"},"description":{"en":"If a table element is used for layout purposes only, then the content of the table should make sense if the table is linearized.","nl":"Als een table-element alleen voor lay-out-doeleinden wordt gebruikt, moet de inhoud van de tabel nog steeds duidelijk zijn als de tabel wordt verwijderd."},"guidelines":{"wcag":{"1.3.2":{"techniques":["G57"]},"4.1.1":{"techniques":["F49"]}}},"tags":["table","layout","content"],"callback":"tableLayoutMakesSenseLinearized"},"tableNotUsedForLayout":{"type":"custom","testability":0.5,"title":{"en":"Tables should not be used for layout","nl":"Tabellen moet niet worden gebruikt voor lay-out"},"description":{"en":"Tables are for data, not for creating a page layout. Consider using standard HTML and CSS techniques instead.","nl":"Tabellen zijn voor data, niet om een pagina op te maken. Gebruik hiervoor HTML en CSS."},"guidelines":{"wcag":{"1.3.2":{"techniques":["F49"]}}},"tags":["table","layout","content"],"callback":"tableNotUsedForLayout"},"tableShouldUseHeaderIDs":{"type":"custom","testability":0.5,"title":{"en":"Table cells use IDs to identify headers","nl":"Tabelcellen gebruiken IDs om koppen te identificeren"},"description":{"en":"If a table is not being used for layout, it should use IDs and header attributes to identify table headers.","nl":"Een tabel moet IDs en header-attributen gebruiken om tabelkoppen te identificeren."},"guidelines":{"wcag":{"1.3.1":{"techniques":["H43"]}}},"tags":["table","content"],"callback":"tableShouldUseHeaderIDs"},"tableSummaryDescribesTable":{"type":"selector","testability":0,"title":{"en":"Table summaries should describe the navigation and structure of the table","nl":"Tabelsamenvattingen moeten de navigatie en structuur van de tabel beschrijven"},"description":{"en":"Table summary elements should describe the navigation tools and structure of the table, as well as provide an overview of what the table describes.","nl":"Tabel \"summary\"-elementen moeten de navigatie en structuur van de tabel beschrijven, en een overzicht bieden van wat er in de tabel staat."},"guidelines":[],"tags":["table","content"],"options":{"selector":"table[summary]"}},"tableSummaryDoesNotDuplicateCaption":{"type":"custom","testability":1,"title":{"en":"Table \"summary\" elements should not duplicate the \"caption\" element","nl":"Tabel \"summary\"-elementen mogen niet hetzelfde zijn als het \"caption\"-element"},"description":{"en":"The summary and the caption must be different, as both provide different information. A caption. /code element identifies the table, while the \"summary\" attribute describes the table contents.","nl":"De samenvatting en beschrijving van een tabel moeten verschillen, want ze bieden verschillende informatie. Een caption-element identificeert welke tabel het betreft en het \"summary\"-attribuut beschrijft de inhoud van de tabel."},"guidelines":[],"tags":["table","content"],"callback":"tableSummaryDoesNotDuplicateCaption"},"tableSummaryIsEmpty":{"type":"placeholder","testability":0.5,"title":{"en":"All data tables should have a summary","nl":"Alle datatabellen moeten een samenvatting hebben"},"description":{"en":"If a table contains data, it should have a \"summary\" attribute.","nl":"Als een tabel data bevat, moet hij een \"summary\"-attribuut hebben."},"guidelines":[],"tags":["table","content"],"components":["placeholder"],"options":{"attribute":"summary","empty":true,"selector":"table[summary]"}},"tableSummaryIsNotTooLong":{"type":"custom","testability":0,"guidelines":[],"tags":["table","content"],"callback":"tableSummaryIsNotTooLong"},"tableSummaryIsSufficient":{"type":"selector","testability":0,"title":{"en":"All data tables should have an adequate summary","nl":"Alle datatabellen moeten een toepasselijke samenvatting hebben"},"description":{"en":"If a table contains data, it should have a \"summary\" attribute that completely communicates the function and use of the table.","nl":"Als een tabel data bevat, moet er een \"summary\"-attribuut zijn dat de functie en het doel van de tabel duidelijk maakt."},"guidelines":[],"tags":["table","content"],"options":{"selector":"table[summary]"}},"tableUseColGroup":{"type":"custom","testability":0,"title":{"en":"Group columns using \"colgroup\" or \"col\" elements","nl":"Groepeer kolommen met \"colgroup\"- of \"col\"-elementen"},"description":{"en":"To help complex table headers make sense, use colgroup or col to group them together.","nl":"Maak complexe tabelkoppen duidelijker door \"colgroup\"- of \"col\"-elementen te gebruiken om ze te groeperen."},"guidelines":[],"tags":["table","content"],"callback":"tableUseColGroup"},"tableUsesAbbreviationForHeader":{"type":"custom","testability":0,"title":{"en":"Table headers over 20 characters should provide an \"abbr\" attribute","nl":"Tabelkoppen met meer dan 20 tekens moeten een \"abbr\"-attribuut hebben"},"description":{"en":"For long table headers, use an \"abbr\" attribute that is less than short (less than 20 characters long).","nl":"Gebruik een \"abbr\"-attribuut korter dan 20 tekens voor lange tabelkoppen."},"guidelines":[],"tags":["table","content"],"callback":"tableUsesAbbreviationForHeader"},"tableUsesCaption":{"type":"selector","testability":1,"title":{"en":"Data tables should contain a \"caption\" element if not described elsewhere","nl":"Datatabellen moeten een \"caption\"-element hebben als ze nergens anders beschreven worden"},"description":{"en":"Unless otherwise described in the document, tables should contain caption elements to describe the purpose of the table.","nl":"Tenzij elders in het document beschreven, moeten tabellen een \"caption\"-element hebben om het doel van de tabel te beschrijven."},"guidelines":{"wcag":{"1.3.1":{"techniques":["H39"]}}},"tags":["table","content"],"options":{"selector":"table:not(table:has(caption))"}},"tableUsesScopeForRow":{"type":"custom","testability":0.5,"title":{"en":"Data tables should use scoped headers for rows with headers","nl":"Datatabellen moeten het \"scope\"-attribuut gebruiken voor rijen met koppen"},"description":{"en":"Where there are table headers for both rows and columns, use the \"scope\" attribute to help relate those headers with their appropriate cells. This test looks for the first and last cells in each row and sees if they differ in layout or font weight.","nl":"Als er tabelkoppen zijn voor zowel rijen als kolommen, gebruik dan het \"scope\"-attribuut om het juiste verband te leggen tussen de koppen en bijbehorende cellen."},"guidelines":{"wcag":{"1.3.1":{"techniques":["H63"]}}},"tags":["table","content"],"callback":"tableUsesScopeForRow"},"tableWithBothHeadersUseScope":{"type":"selector","testability":0.5,"title":{"en":"Data tables with multiple headers should use the \"scope\" attribute","nl":"Datatabellen met meerdere headers moeten het \"scope\"-attribuut gebruiken"},"description":{"en":"Where there are table headers for both rows and columns, use the \"scope\" attribute to help relate those headers with their appropriate cells.","nl":"Als er tabelkoppen zijn voor zowel rijen als kolommen, gebruik dan het \"scope\"-attribuut om het juiste verband te leggen tussen de koppen en bijbehorende cellen."},"guidelines":{"508":["h"],"wcag":{"1.3.1":{"techniques":["F91"]}}},"tags":["table","content"],"options":{"selector":"table:has(tr:not(table tr:first) th:not(th[scope]))"}},"tableWithMoreHeadersUseID":{"type":"custom","testability":0.5,"title":{"en":"Complex data tables should provide \"id\" attributes to headers","nl":"Complexe datatabellen moeten \"id\"-attributen aan headers koppelen"},"description":{"en":"Complex data tables should provide \"id\" attributes to headers and \"headers\" attributes for data cells.","nl":"Complexe datatabellen moeten \"id\"-attributen aan headers koppelen en \"headers\"-attributen aan datacellen."},"guidelines":[],"tags":["table","content"],"callback":"tableWithMoreHeadersUseID"},"tagsAreNestedCorrectly":{"type":"custom","testability":1,"title":{"en":"All tags should be nested correctly","nl":"Alle tags moeten juist genest worden"},"description":{"en":"","nl":""},"guidelines":{"wcag":{"4.1.1":{"techniques":["H74"]}}},"tags":["html"],"components":["htmlSource"],"callback":"tagsAreNestedCorrectly"},"tabularDataIsInTable":{"type":"custom","testability":0.5,"title":{"en":"All tabular information should use a table","nl":"Alle tabelinformatie moet ook daadwerkelijk in een tabel staan"},"description":{"en":"Tables should be used when displaying tabular information.","nl":"Gebruik een echte tabel wanneer je tabelinformatie wilt tonen."},"guidelines":{"wcag":{"1.3.1":{"techniques":["F33","F34","F48"]},"1.3.2":{"techniques":["F33","F34"]}}},"tags":["table","content"],"callback":"tabularDataIsInTable"},"textIsNotSmall":{"type":"custom","testability":0.5,"title":{"en":"The text size is not less than 9 pixels high","nl":"De grootte van de tekst is meer dan 8 pixels hoog"},"description":{"en":"To help users with difficulty reading small text, ensure text size is no less than 9 pixels high.","nl":"Help gebruikers die moeite hebben met het lezen van kleine letters, door ervoor te zorgen dat tekst groter is dan 8 pixels hoog."},"guidelines":[],"tags":["textsize","content"],"components":["convertToPx"],"callback":"textIsNotSmall"},"textareaHasAssociatedLabel":{"type":"label","testability":1,"title":{"en":"All textareas should have a corresponding label","nl":"Alle \"textarea\"-elementen moeten een bijbehorend label hebben"},"description":{"en":"All textarea elements should have a corresponding label element. Screen readers often enter a \"form mode\" where only label text is read aloud to the user","nl":"Alle \"textarea\"-elementen moeten een bijbehorend label hebben. Schermlezers maken vaak gebruik van een \"formuliereninstelling\" waarbij alleen de tekst van de labels hardop aan de gebruiker wordt voorgelezen."},"guidelines":{"wcag":{"1.1.1":{"techniques":["H44"]},"1.3.1":{"techniques":["H44","F68"]},"2.1.1":{"techniques":["H91"]},"2.1.3":{"techniques":["H91"]},"3.3.2":{"techniques":["H44"]},"4.1.2":{"techniques":["H44","H91"]}}},"tags":["form","content"],"components":["label"],"options":{"selector":"textarea"}},"textareaLabelPositionedClose":{"type":"labelProximity","testability":0.5,"title":{"en":"All textareas should have a label that is close to it","nl":"Alle \"textarea\"-elementen moeten een label hebben dat dicht bij het element staat"},"description":{"en":"All textarea elements should have a corresponding label element that is close in proximity.","nl":"Alle \"textarea\"-elementen moeten een bijbehorend label hebben dat dicht bij het element staat."},"guidelines":[],"tags":["form","content"],"components":["labelProximity"],"options":{"selector":"textarea"}},"videoProvidesCaptions":{"type":"selector","testability":0.5,"title":{"en":"All video tags must provide captions","nl":"Alle video tags moeten bijschriften bieden"},"description":{"en":"All HTML5 video tags must provide captions.","nl":"Alle HTML5 video tags moeten bijschriften bieden."},"guidelines":{"508":["b","b"],"wcag":{"1.2.2":{"techniques":["G87"]},"1.2.4":{"techniques":["G87"]}}},"tags":["media","content"],"options":{"selector":"video"}},"videosEmbeddedOrLinkedNeedCaptions":{"type":"custom","testability":1,"title":{"en":"All linked or embedded videos need captions","nl":"Alle gekoppelde of ingebedde video's moeten bijschriften hebben"},"description":{"en":"Any video hosted or otherwise which is linked or embedded must have a caption.","nl":"Elke video die is gekoppeld of ingebed in content moet een bijschrift hebben."},"guidelines":{"wcag":{"1.2.2":{"techniques":["G87"]},"1.2.4":{"techniques":["G87"]}}},"tags":["media","content"],"components":["video","language"],"callback":"videosEmbeddedOrLinkedNeedCaptions"},"whiteSpaceInWord":{"type":"custom","testability":0.5,"title":{"en":"Whitespace should not be used between characters in a word","nl":"Zet geen witruimte tussen letters in een woord"},"description":{"en":"Using extra whitespace between letters in a word causes screen readers to not interpret the word correctly, use the letter-spacing CSS property instead.","nl":"Het gebruik van witruimte tussen de letters van een woord, zorgen dat schermlezers het woord niet volledig kunnen lezen. Gebruik in plaats hiervan css om de ruimte tussen letters te bepalen."},"guidelines":{"wcag":{"1.3.2":{"techniques":["F32","C8"]}}},"tags":["content"],"callback":"whiteSpaceInWord"},"whiteSpaceNotUsedForFormatting":{"type":"custom","testability":0.5,"title":{"en":"Whitespace should not be used for conveying information","nl":"Gebruik geen witruimte om informatie over te brengen"},"description":{"en":"Spaces or tabs are not read by assistive technology and should not be used to convey meaning.","nl":"Spaties of tabs worden niet voorgelezen door hulpprogramma's en moeten niet worden gebruikt om betekenis over te dragen."},"guidelines":{"wcag":{"1.3.2":{"techniques":["G57"]}}},"tags":["content"],"callback":"whiteSpaceNotUsedForFormatting"},"doNotUseGraphicalSymbolToConveyInformation":{"type":"custom","testability":1,"title":{"en":"Using a graphical symbol alone to convey information","nl":"Gebruik van alleen een grafisch symbool om informatie over te brengen"},"description":{"en":"The objective of this technique is to show how using a graphical symbol to convey information can make content difficult to comprehend. A graphical symbol may be an image, an image of text or a pictorial or decorative character symbol (glyph) which imparts information nonverbally. Examples of graphical symbols include an image of a red circle with a line through it, a smiley face, or a glyph which represents a check mark, arrow, or other symbol but is not the character with that meaning. Assistive technology users may have difficulty determining the meaning of the graphical symbol. If a graphical symbol is used to convey information, provide an alternative using features of the technology or use a different mechanism that can be marked with an alternative to represent the graphical symbol. For example, an image with a text alternative can be used instead of the glyph.","nl":"Het doel van deze techniek is te laten zien dat content moeilijker begrepen kan worden wanneer een grafisch symbool wordt gebruikt om informatie over te brengen. Een grafisch symbool kan een afbeelding, een afbeelding van tekst of een pictogram of decoratief teken zijn (glyph) dat non-verbaal informatie overbrengt. Voorbeelden hiervan zijn een rode cirkel met een lijn erdoorheen, een smiley of een vinkje, pijl of ander symbool dat niet noodzakelijkerwijs een duidelijke betekenis heeft. Gebruikers van hulpprogramma's hebben vaak moeite om de bedoeling van een grafisch symbool te duiden. Als een grafisch symbool gebruikt wordt om informatie over te brengen, biedt dan ook een (tekstueel) alternatief."},"guidelines":{"wcag":{"1.3.3":{"techniques":["F26"]}}},"tags":["link","content"],"callback":"doNotUseGraphicalSymbolToConveyInformation"},"linkDoesNotChangeContextOnFocus":{"type":"event","testability":1,"title":{"en":"Link elements must not contain an \"onfocus\" attribute","nl":"Link-elementen bevatten geen \"onfocus\"-attribuut"},"description":{"en":"Actions like \"onfocus\" can take control away from users who are trying to navigate the page. Using an \"onfocus\" attribute for things like links should be replaced with css.","nl":"Acties zoals \"onfocus\" kunnen de controle ontnemen van gebruikers die op een pagina proberen te navigeren. Het gebruik van een \"onfocus\"-attribuut voor zaken als links moet worden vervangen door middel van css."},"guidelines":[],"tags":["form","content"],"components":["event","hasEventListener"],"options":{"searchEvent":"onfocus","selector":"a"}},"buttonDoesNotChangeContextOnFocus":{"type":"event","testability":1,"title":{"en":"Buttons must not contain an \"onfocus\" attribute","nl":"Knoppen bevatten geen \"onfocus\"-attribuut"},"description":{"en":"Actions like \"onfocus\" can take control away from users who are trying to navigate the page. Using an \"onfocus\" attribute for things like buttons should be replaced with css.","nl":"Acties zoals \"onfocus\" kunnen de controle ontnemen van gebruikers die op een pagina proberen te navigeren. Het gebruik van een \"onfocus\"-attribuut voor zaken als knoppen moet worden vervangen door middel van css."},"guidelines":[],"tags":["form","content"],"components":["event","hasEventListener"],"options":{"searchEvent":"onfocus","selector":"input[type=checkbox],input[type=text],button"}},"KINGStrongList":{"type":"custom","testability":1,"title":{"en":"Use strong in lists only"},"description":{"en":"STRONG only allowed when parent element is LI."},"guidelines":[],"tags":["KING"],"callback":"KINGStrongList"},"KINGUseLongDateFormat":{"type":"custom","testability":1,"title":{"en":"Use a long date format"},"description":{"en":"Short date formats might confuse users, Always use the month name: 20 May 2014."},"guidelines":[],"tags":["KING"],"callback":"KINGUseLongDateFormat"},"KINGUsePercentageWithSymbol":{"type":"custom","testability":1,"title":{"en":"Use a symbol within a percentage"},"description":{"en":""},"guidelines":[],"tags":["KING"],"callback":"KINGUsePercentageWithSymbol"},"KINGUseCurrencyAsSymbol":{"type":"custom","testability":1,"title":{"en":"Use a symbol for a currency"},"description":{"en":"Only use symbol and currency name instead of common name such as € or EUR."},"guidelines":[],"tags":["KING"],"callback":"KINGUseCurrencyAsSymbol"},"videoMayBePresent":{"type":"custom","testability":1,"title":{"en":"Video or object uses a link that points to a file with a video extension","nl":"Video of object met een link naar een bestand met een video extensie"},"description":{"en":"","nl":""},"guidelines":[],"tags":["link","video"],"callback":"videoMayBePresent"},"audioMayBePresent":{"type":"custom","testability":1,"title":{"en":"Audio or object uses a link that points to a file with a video extension","nl":"Audio of object met een link naar een bestand met een video extensie"},"description":{"en":"","nl":""},"guidelines":[],"tags":["link","audio"],"callback":"audioMayBePresent"},"animatedGifMayBePresent":{"type":"custom","testability":1,"title":{"en":"Test if a .gif is used on the page. Test if the .gif contains more then one frame","nl":"Test of een .gif afbeelding gebruikt is op de pagina. Test of het .gif bestand uit meer dan één frame bestaat"},"description":{"en":"","nl":""},"guidelines":[],"tags":["link","gif"],"callback":"animatedGifMayBePresent"},"userInputMayBeRequired":{"type":"custom","testability":1,"title":{"en":"Test if user input is required","nl":"Test of er invoervelden zijn"},"description":{"en":"","nl":""},"guidelines":[],"tags":["form","input"],"callback":"userInputMayBeRequired"}}
\ No newline at end of file
diff --git a/plugins/ckeditor/a11ychecker/libs/quail/wcag2.json b/plugins/ckeditor/a11ychecker/libs/quail/wcag2.json
new file mode 100644
index 0000000..dfd6182
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/libs/quail/wcag2.json
@@ -0,0 +1,615 @@
+{
+ "1.1.1": {
+ "id": "wcag20:text-equiv-all",
+ "level": "wcag20:level_a",
+ "default": "cantTell",
+ "testAggregators": [
+ {
+ "passed": "cantTell",
+ "failed": "failed",
+ "tests": [
+ "areaHasAltValue"
+ ]
+ },
+ {
+ "passed": "cantTell",
+ "failed": "failed",
+ "tests": [
+ "imgAltNotEmptyInAnchor"
+ ]
+ },
+ {
+ "passed": "cantTell",
+ "failed": "failed",
+ "tests": [
+ "imgHasAlt"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "type": "stacking",
+ "tests": [
+ "inputImageAltNotRedundant",
+ "inputImageAltIsNotPlaceholder",
+ "inputImageAltIsNotFileName",
+ "inputImageHasAlt"
+ ]
+ }
+ ]
+ },
+ "1.2.1": {
+ "id": "wcag20:media-equiv-av-only-alt",
+ "level": "wcag20:level_a",
+ "preconditions": [
+ "videoMayBePresent",
+ "audioMayBePresent"
+ ]
+ },
+ "1.2.2": {
+ "id": "wcag20:media-equiv-captions",
+ "level": "wcag20:level_a",
+ "testAggregators": [
+ {
+ "passed": "cantTell",
+ "failed": "failed",
+ "tests": [
+ "videosEmbeddedOrLinkedNeedCaptions"
+ ]
+ }
+ ]
+ },
+ "1.2.3": {
+ "id": "wcag20:media-equiv-audio-desc",
+ "level": "wcag20:level_a",
+ "preconditions": [
+ "videoMayBePresent"
+ ]
+ },
+ "1.2.4": {
+ "id": "wcag20:media-equiv-real-time-captions",
+ "level": "wcag20:level_aa",
+ "preconditions": [
+ "videoMayBePresent"
+ ]
+ },
+ "1.2.5": {
+ "id": "wcag20:media-equiv-audio-desc-only",
+ "level": "wcag20:level_aa",
+ "preconditions": [
+ "videoMayBePresent"
+ ]
+ },
+ "1.2.6": {
+ "id": "wcag20:media-equiv-sign",
+ "level": "wcag20:level_aaa"
+ },
+ "1.2.7": {
+ "id": "wcag20:media-equiv-extended-ad",
+ "level": "wcag20:level_aaa"
+ },
+ "1.2.8": {
+ "id": "wcag20:media-equiv-text-doc",
+ "level": "wcag20:level_aaa"
+ },
+ "1.2.9": {
+ "id": "wcag20:media-equiv-live-audio-only",
+ "level": "wcag20:level_aaa"
+ },
+ "1.3.1": {
+ "id": "wcag20:content-structure-separation-programmatic",
+ "level": "wcag20:level_a",
+ "default": "cantTell",
+ "testAggregators": [
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "type": "combined",
+ "tests": [
+ "fileHasLabel",
+ "inputWithoutLabelHasTitle"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "type": "combined",
+ "tests": [
+ "inputTextHasLabel",
+ "inputWithoutLabelHasTitle"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "type": "combined",
+ "tests": [
+ "passwordHasLabel",
+ "inputWithoutLabelHasTitle"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "type": "combined",
+ "tests": [
+ "checkboxHasLabel",
+ "inputWithoutLabelHasTitle"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "type": "combined",
+ "tests": [
+ "radioHasLabel",
+ "inputWithoutLabelHasTitle"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "type": "combined",
+ "tests": [
+ "selectHasAssociatedLabel",
+ "inputWithoutLabelHasTitle"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "type": "combined",
+ "tests": [
+ "textareaHasAssociatedLabel",
+ "inputWithoutLabelHasTitle"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "cantTell",
+ "tests": [
+ "pNotUsedAsHeader"
+ ]
+ },
+ {
+ "passed": "cantTell",
+ "failed": "failed",
+ "tests": [
+ "tableLayoutDataShouldNotHaveTh"
+ ]
+ },
+ {
+ "passed": "cantTell",
+ "failed": "failed",
+ "tests": [
+ "tableLayoutHasNoSummary"
+ ]
+ },
+ {
+ "passed": "cantTell",
+ "failed": "failed",
+ "tests": [
+ "tableLayoutHasNoCaption"
+ ]
+ }
+ ]
+ },
+ "1.3.2": {
+ "id": "wcag20:content-structure-separation-sequence",
+ "level": "wcag20:level_a"
+ },
+ "1.3.3": {
+ "id": "wcag20:content-structure-separation-understanding",
+ "level": "wcag20:level_a"
+ },
+ "1.4.1": {
+ "id": "wcag20:visual-audio-contrast-without-color",
+ "level": "wcag20:level_a",
+ "default": "cantTell",
+ "testAggregators": [
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "tests": [
+ "aInPHasADistinctStyle"
+ ]
+ }
+ ]
+ },
+ "1.4.2": {
+ "id": "wcag20:visual-audio-contrast-dis-audio",
+ "level": "wcag20:level_a",
+ "preconditions": [
+ "videoMayBePresent",
+ "audioMayBePresent"
+ ]
+ },
+ "1.4.3": {
+ "id": "wcag20:visual-audio-contrast-contrast",
+ "level": "wcag20:level_aa",
+ "testAggregators": [
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "tests": [
+ "colorFontContrast",
+ "colorElementBehindContrast",
+ "colorBackgroundImageContrast",
+ "colorElementBehindBackgroundImageContrast",
+ "colorBackgroundGradientContrast",
+ "colorElementBehindBackgroundGradientContrast"
+ ]
+ }
+ ]
+ },
+ "1.4.4": {
+ "id": "wcag20:visual-audio-contrast-scale",
+ "level": "wcag20:level_aa"
+ },
+ "1.4.5": {
+ "id": "wcag20:visual-audio-contrast-text-presentation",
+ "level": "wcag20:level_aa"
+ },
+ "1.4.6": {
+ "id": "wcag20:visual-audio-contrast7",
+ "level": "wcag20:level_aaa"
+ },
+ "1.4.7": {
+ "id": "wcag20:visual-audio-contrast-noaudio",
+ "level": "wcag20:level_aaa"
+ },
+ "1.4.8": {
+ "id": "wcag20:visual-audio-contrast-visual-presentation",
+ "level": "wcag20:level_aaa"
+ },
+ "1.4.9": {
+ "id": "wcag20:visual-audio-contrast-text-images",
+ "level": "wcag20:level_aaa"
+ },
+ "2.1.1": {
+ "id": "wcag20:keyboard-operation-keyboard-operable",
+ "level": "wcag20:level_a"
+ },
+ "2.1.2": {
+ "id": "wcag20:keyboard-operation-trapping",
+ "level": "wcag20:level_a"
+ },
+ "2.1.3": {
+ "id": "wcag20:keyboard-operation-all-funcs",
+ "level": "wcag20:level_aaa"
+ },
+ "2.2.1": {
+ "id": "wcag20:time-limits-required-behaviors",
+ "level": "wcag20:level_a"
+ },
+ "2.2.2": {
+ "id": "wcag20:time-limits-pause",
+ "level": "wcag20:level_a"
+ },
+ "2.2.3": {
+ "id": "wcag20:time-limits-no-exceptions",
+ "level": "wcag20:level_aaa"
+ },
+ "2.2.4": {
+ "id": "wcag20:time-limits-postponed",
+ "level": "wcag20:level_aaa"
+ },
+ "2.2.5": {
+ "id": "wcag20:time-limits-server-timeout",
+ "level": "wcag20:level_aaa"
+ },
+ "2.3.1": {
+ "id": "wcag20:seizure-does-not-violate",
+ "level": "wcag20:level_a"
+ },
+ "2.3.2": {
+ "id": "wcag20:seizure-three-times",
+ "level": "wcag20:level_aaa"
+ },
+ "2.4.1": {
+ "id": "wcag20:navigation-mechanisms-skip",
+ "level": "wcag20:level_a"
+ },
+ "2.4.2": {
+ "id": "wcag20:navigation-mechanisms-title",
+ "level": "wcag20:level_a"
+ },
+ "2.4.3": {
+ "id": "wcag20:navigation-mechanisms-focus-order",
+ "level": "wcag20:level_a"
+ },
+ "2.4.4": {
+ "id": "wcag20:navigation-mechanisms-refs",
+ "level": "wcag20:level_a",
+ "default": "cantTell",
+ "testAggregators": [
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "tests": [
+ "linkHasAUniqueContext"
+ ]
+ }
+ ]
+ },
+ "2.4.5": {
+ "id": "wcag20:navigation-mechanisms-mult-loc",
+ "level": "wcag20:level_aa"
+ },
+ "2.4.6": {
+ "id": "wcag20:navigation-mechanisms-descriptive",
+ "level": "wcag20:level_aa"
+ },
+ "2.4.7": {
+ "id": "wcag20:navigation-mechanisms-focus-visible",
+ "level": "wcag20:level_aa"
+ },
+ "2.4.8": {
+ "id": "wcag20:navigation-mechanisms-location",
+ "level": "wcag20:level_aaa"
+ },
+ "2.4.9": {
+ "id": "wcag20:navigation-mechanisms-link",
+ "level": "wcag20:level_aaa"
+ },
+ "2.4.10": {
+ "id": "wcag20:navigation-mechanisms-headings",
+ "level": "wcag20:level_aaa"
+ },
+ "3.1.1": {
+ "id": "wcag20:meaning-doc-lang-id",
+ "level": "wcag20:level_a",
+ "testAggregators": [
+ {
+ "passed": "cantTell",
+ "failed": "failed",
+ "type": "stacking",
+ "tests": [
+ "documentLangIsISO639Standard",
+ "documentLangNotIdentified"
+ ]
+ }
+ ]
+ },
+ "3.1.2": {
+ "id": "wcag20:meaning-other-lang-id",
+ "level": "wcag20:level_aa"
+ },
+ "3.1.3": {
+ "id": "wcag20:meaning-idioms",
+ "level": "wcag20:level_aaa"
+ },
+ "3.1.4": {
+ "id": "wcag20:meaning-located",
+ "level": "wcag20:level_aaa"
+ },
+ "3.1.5": {
+ "id": "wcag20:meaning-supplements",
+ "level": "wcag20:level_aaa"
+ },
+ "3.1.6": {
+ "id": "wcag20:meaning-pronunciation",
+ "level": "wcag20:level_aaa"
+ },
+ "3.2.1": {
+ "id": "wcag20:consistent-behavior-receive-focus",
+ "level": "wcag20:level_a"
+ },
+ "3.2.2": {
+ "id": "wcag20:consistent-behavior-unpredictable-change",
+ "level": "wcag20:level_a"
+ },
+ "3.2.3": {
+ "id": "wcag20:consistent-behavior-consistent-locations",
+ "level": "wcag20:level_aa"
+ },
+ "3.2.4": {
+ "id": "wcag20:consistent-behavior-consistent-functionality",
+ "level": "wcag20:level_aa"
+ },
+ "3.2.5": {
+ "id": "wcag20:consistent-behavior-no-extreme-changes-context",
+ "level": "wcag20:level_aaa"
+ },
+ "3.3.1": {
+ "id": "wcag20:minimize-error-identified",
+ "level": "wcag20:level_a",
+ "preconditions": [
+ "userInputMayBeRequired"
+ ]
+ },
+ "3.3.2": {
+ "id": "wcag20:minimize-error-cues",
+ "level": "wcag20:level_a"
+ },
+ "3.3.3": {
+ "id": "wcag20:minimize-error-suggestions",
+ "level": "wcag20:level_aa",
+ "preconditions": [
+ "userInputMayBeRequired"
+ ]
+ },
+ "3.3.4": {
+ "id": "wcag20:minimize-error-reversible",
+ "level": "wcag20:level_aa",
+ "preconditions": [
+ "userInputMayBeRequired"
+ ]
+ },
+ "3.3.5": {
+ "id": "wcag20:minimize-error-context-help",
+ "level": "wcag20:level_aaa"
+ },
+ "3.3.6": {
+ "id": "wcag20:minimize-error-reversible-all",
+ "level": "wcag20:level_aaa"
+ },
+ "4.1.1": {
+ "id": "wcag20:ensure-compat-parses",
+ "level": "wcag20:level_a",
+ "default": "cantTell",
+ "testAggregators": [
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "tests": [
+ "documentIDsMustBeUnique"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "tests": [
+ "elementsDoNotHaveDuplicateAttributes"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "tests": [
+ "idRefHasCorrespondingId"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "tests": [
+ "idrefsHasCorrespondingId"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "tests": [
+ "tagsAreNestedCorrectly"
+ ]
+ }
+ ]
+ },
+ "4.1.2": {
+ "id": "wcag20:ensure-compat-rsv",
+ "level": "wcag20:level_a",
+ "default": "cantTell",
+ "testAggregators": [
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "tests": [
+ "areaHasAltValue"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "tests": [
+ "formButtonsHaveValue"
+ ]
+ },
+ {
+ "passed": "cantTell",
+ "failed": "failed",
+ "type": "combined",
+ "tests": [
+ "fileHasLabel",
+ "inputWithoutLabelHasTitle"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "type": "stacking",
+ "tests": [
+ "frameTitlesNotPlaceholder",
+ "frameTitlesNotEmpty",
+ "framesHaveATitle"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "cantTell",
+ "tests": [
+ "imgAltNotEmptyInAnchor"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "type": "stacking",
+ "tests": [
+ "inputImageAltNotRedundant",
+ "inputImageAltIsNotFileName",
+ "inputImageHasAlt",
+ "inputImageAltIsNotPlaceholder"
+ ]
+ },
+ {
+ "passed": "cantTell",
+ "failed": "failed",
+ "type": "combined",
+ "tests": [
+ "inputTextHasLabel",
+ "inputWithoutLabelHasTitle"
+ ]
+ },
+ {
+ "passed": "cantTell",
+ "failed": "failed",
+ "type": "combined",
+ "tests": [
+ "passwordHasLabel",
+ "inputWithoutLabelHasTitle"
+ ]
+ },
+ {
+ "passed": "cantTell",
+ "failed": "failed",
+ "type": "combined",
+ "tests": [
+ "checkboxHasLabel",
+ "inputWithoutLabelHasTitle"
+ ]
+ },
+ {
+ "passed": "cantTell",
+ "failed": "failed",
+ "type": "combined",
+ "tests": [
+ "radioHasLabel",
+ "inputWithoutLabelHasTitle"
+ ]
+ },
+ {
+ "passed": "cantTell",
+ "failed": "failed",
+ "type": "combined",
+ "tests": [
+ "selectHasAssociatedLabel",
+ "inputWithoutLabelHasTitle"
+ ]
+ },
+ {
+ "passed": "cantTell",
+ "failed": "failed",
+ "type": "combined",
+ "tests": [
+ "textareaHasAssociatedLabel",
+ "inputWithoutLabelHasTitle"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "tests": [
+ "aMustContainText"
+ ]
+ },
+ {
+ "passed": "passed",
+ "failed": "failed",
+ "tests": [
+ "buttonHasName"
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/plugins/ckeditor/a11ychecker/plugin.js b/plugins/ckeditor/a11ychecker/plugin.js
new file mode 100644
index 0000000..13e645d
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/plugin.js
@@ -0,0 +1,178 @@
+/**
+* @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+* For licensing, see LICENSE.md or https://ckeditor.com/license
+*/
+
+!function(){var t,e,n,i,s,a,r,o,c,u,l,d,h,p,f,g,m,v,b,y,x,w,C,T,k,I,E;C=function(){"use strict";function t(){this.list=[]}function e(t,e){var n=0;return n=t.element.getPosition(e.element)&CKEDITOR.POSITION_FOLLOWING?1:-1}return t.prototype={list:[],currentIndex:-1},t.prototype.constructor=t,t.prototype.each=function(t){var e=this.list;if(e.map)e.map(t,this);else for(var n=0,i=e.length;i>n;n++)t.call(this,e[n])},t.prototype.count=function(t){if(t){var e=0,n=0;for(n=0;nthis.count()-1?0!==this.currentIndex&&this.moveTo(0):this.moveTo(this.currentIndex+1),this.getFocused()):null},t.prototype.prev=function(){if(!this.count())return null;var t=this.count()-1;return 0===this.currentIndex||-1==this.currentIndex?this.currentIndex!=t&&this.moveTo(t):this.moveTo(this.currentIndex-1),this.getFocused()},t.prototype.getIssueByElement=function(t){var e=null;return this.each(function(n){n.element.equals(t)&&(e=n)}),e},t.prototype.getIssuesByElement=function(t,e){for(var n,i,s=[],a=this.list,r=0,o=a.length;o>r;r++)n=a[r],i=!e||!n.isIgnored(),n.element.equals(t)&&i&&s.push(n);return s},t.prototype.indexOf=function(t){return CKEDITOR.tools.indexOf(this.list,t)},t.prototype.getIssueByIndex=function(t){var e=this.getItem(t);return e.element;
+},t.prototype.sort=function(){this.list.sort(e)},t.prototype.filter=function(t){return this.list=this.list.filter(t),this.list},CKEDITOR.event.implementOn(t.prototype),t}(),T=function(t){"use strict";function e(){}return e.prototype={fixesMapping:{},config:{}},CKEDITOR.event.implementOn(e.prototype),e.prototype.constructor=e,e.fixes={},e.prototype.process=function(e,n,i){var s=new t;return this.fire("process",{issues:s,contentElement:n})===!1?!1:(i&&i(s),!0)},e.prototype.filterIssues=function(t,e){if(this._filterIssue){var n=this,i=function(t){return n._filterIssue.call(n,t,e)};t.filter(i)}},e.prototype.getIssueDetails=function(t,e){},e.getFixType=function(t,n){e.fixes[t]?n&&n(e.fixes[t]):!function(i){e.fixes[t]=i,n&&n(i)}()},e.prototype.getFixes=function(t,e,n){var i=this.fixesMapping[t.id];if(i&&i.length){var s,a=[],r=function(t){a.push(t),a.length===i.length&&e(a)};for(s=0;ss;s++)a[s](i);delete n[t]},t.prototype.setLoadedTypes=function(t){e=t},t.prototype.getLoadedTypes=function(){return e},t.prototype.getWaitingCallbacks=function(){return n},CKEDITOR.event.implementOn(t.prototype),t}(),e=function(t){"use strict";function e(e){t.call(this,e);
+}e.prototype=new t,e.prototype.constructor=e,e.prototype._langDictionary={};var n={},i=[];return e.prototype.get=function(e){return e.langCode=e.langCode||"en",this.deferGetCall(e.langCode,arguments)?void 0:(CKEDITOR.plugins.a11ychecker.dev||(e.name=e.langCode+"/"+e.name),t.prototype.get.call(this,e))},e.prototype.getInstance=function(t){t=t||{};var e=t.name,n=t.langCode||"en",i=this;this.get({name:e,callback:function(s){var a=new s(t.issue);CKEDITOR.plugins.a11ychecker.dev&&(a.lang=i._langDictionary[n][e]),t.callback(a)},langCode:n})},e.prototype.deferGetCall=function(t,e){var n=CKEDITOR.tools.indexOf;return!CKEDITOR.plugins.a11ychecker.dev||this._langDictionary[t]?!1:(this._addDeferredGet(t,e),-1===n(i,t)&&(i.push(t),CKEDITOR.scriptLoader.load(this.basePath+"lang/"+t+".js")),!0)},e.prototype.add=function(e,n){return t.prototype.add.call(this,e,n)},e.prototype.lang=function(t,e){this._langDictionary[t]=e;var i=n[t];if(i)for(var s=i.length-1;s>=0;s--)this.get.apply(this,i[s])},e.prototype._addDeferredGet=function(t,e){
+n[t]?n[t].push(e):n[t]=[e]},e.prototype._getDeferredGetCount=function(t){return n[t]?n[t].length:0},e.prototype._clearDeferredGetQueue=function(){n={}},e}(t),n=function(){"use strict";function t(t){this.controller=t,this._storedSel=null}return t.prototype={},t.prototype.constructor=t,t.prototype.init=function(){var t=this.controller,e=t.editor;e&&e.fire("lockSnapshot",{dontUpdate:!0}),t.issues&&t.editableDecorator.markIssues(t.issues),CKEDITOR.env.chrome&&t.editor&&(this._storedSel=t.editor.getSelection().createBookmarks())},t.prototype.close=function(){var t=this.controller;t.editableDecorator.removeMarkup(),t.viewerController&&t.viewerController.viewer.panel.hide(),t.issues&&t.issues.resetFocus(),this._storedSel&&this.controller.editor.getSelection().selectBookmarks(this._storedSel),this.controller.editor.fire("unlockSnapshot")},t.prototype.unsetStoredSelection=function(){var t=this._storedSel;t&&(this.removeBookmark(t),this._storedSel=null)},t.prototype.removeBookmark=function(t){for(var e=0;en;n++)e=t.getItem(n),this.markIssueElement(e,t)},t.prototype.addListeners=function(){var e=this.editor,n=e.editable(),i=this,s=CKEDITOR.tools.bind(i.clickListener,i);if(!n)throw new Error("Editable not available");n.attachListener(n,"click",s),e.on("contentDom",function(){var t=e.editable();t.attachListener(t,"click",s)}),e.dataProcessor.htmlFilter.addRules({elements:{$:function(n){return e._.a11ychecker.disableFilterStrip||delete n.attributes[t.ID_ATTRIBUTE_NAME_FULL],
+e.config.a11ychecker_noIgnoreData&&delete n.attributes["data-a11y-ignore"],n}}})},t.prototype.applyMarkup=function(){var i=this.editable(),s=!!this.editor.plugins.fakeobjects,a=t.INITIAL_ID_VALUE;i.forEach(function(i){return i.data(t.ID_ATTRIBUTE_NAME,a),s&&e(i)&&n(i,t.ID_ATTRIBUTE_NAME_FULL,a),a+=1,!0},CKEDITOR.NODE_ELEMENT,!1)},t.prototype.decorateScratchpad=function(e){e.data(t.ID_ATTRIBUTE_NAME,t.INITIAL_ID_VALUE)},t.prototype.removeMarkup=function(){var n=this.editable(),s=!!this.editor.plugins.fakeobjects,a=this.unmarkIssueElement;n.forEach(function(n){n.removeAttribute&&n.removeAttribute(t.ID_ATTRIBUTE_NAME_FULL),s&&e(n)&&i(n,t.ID_ATTRIBUTE_NAME_FULL),n.hasClass("cke_a11yc_issue")&&a(n)},CKEDITOR.NODE_ELEMENT,!1)},t.prototype.clickListener=function(t){var e=t.data.getTarget(),n=this.editor._.a11ychecker;if(!e.hasClass("cke_a11yc_issue")){var i,s=e.getParents(!0);for(e=null,i=0;is;s++)n=e.getItem(s),i=n.originalElement.data(t.ID_ATTRIBUTE_NAME),i===String(t.INITIAL_ID_VALUE)?n.element=r:n.element=r.findOne("*["+t.ID_ATTRIBUTE_NAME_FULL+'="'+i+'"]')},t.prototype.markIgnoredIssue=function(t){t.element.addClass("cke_a11yc_ignored")},t.prototype.markIssueElement=function(t,e){var n=t.element,i=t.testability,s=t.isIgnored()&&!e.getIssuesByElement(n,!0).length;void 0===i&&(i=1),n.addClass("cke_a11yc_issue"),s?this.markIgnoredIssue(t):(n.addClass(this.testabilityClasses[i]),n.removeClass("cke_a11yc_ignored"))},t.prototype.unmarkIssueElement=function(t,e){var n=t.removeClass?t:t.element;e||n.removeClass("cke_a11yc_issue"),n.removeClass("cke_a11yc_error").removeClass("cke_a11yc_warning").removeClass("cke_a11yc_notice").removeClass("cke_a11yc_ignored").removeClass("cke_a11yc_focused");
+},t}(),r=function(){"use strict";function t(){}return t.prototype={preferredIssue:null},t.prototype.constructor=t,t.prototype.set=function(t){this.preferredIssue=t},t.prototype.unset=function(t){this.set(null)},t.prototype.getFromList=function(e){var n=null,i=this.preferredIssue&&this.preferredIssue.element,s=!1;return 0===e.count()?n:i?(i&&t._nodeIsRemoved(i)&&(i=t._retreiveElementFromSelection(i.getDocument())),e.each(function(t){s||(t.element.equals(i)?(s=!0,n=t):!n&&t.element.getPosition(i)&CKEDITOR.POSITION_FOLLOWING&&(n=t))}),n||e.getItem(0)):e.getItem(0)},t._retreiveElementFromSelection=function(t){var e=t.getSelection();return e?e.getCommonAncestor():null},t.prototype.getFromListIndex=function(t){var e=this.getFromList(t);return e?t.indexOf(e):null},t._nodeIsRemoved=function(t){var e=t.getParents();return!(e[0]&&"html"==e[0].getName())},t}(),o=function(){"use strict";function t(t){this.controller=t}return t.prototype={show:function(){this.getEditorCommand().setState(CKEDITOR.TRISTATE_ON);
+},hide:function(){this._selectIssue(),this.getEditorCommand().setState(CKEDITOR.TRISTATE_OFF)},update:function(){this.controller.issues.on("focusChanged",this.focusChanged,this)},focusChanged:function(t){var e=t.data;e.previous&&this.unmarkFocus(e.previous.element),e.current&&this.markFocus(e.current.element)},unmarkFocus:function(t){t.removeClass("cke_a11yc_focused")},markFocus:function(t){t.addClass("cke_a11yc_focused")},getEditorCommand:function(){return this.controller.editor.getCommand("a11ychecker")}},t.prototype.constructor=t,t.prototype._selectIssue=function(){var t=this.controller,e=t.issues.getFocused();e&&t._withUndoManager(function(){var n=t.editor,i=t.mode;t.editableDecorator.removeMarkup(),n.getSelection().selectElement(e.element),i.unsetStoredSelection&&i.unsetStoredSelection(),n.fire("updateSnapshot"),i.unsetStoredSelection&&(i._storedSel=n.getSelection().createBookmarks())})},t}(),c=function(){"use strict";function t(t){this.viewer=t,this.templates={};for(var e in this.templateDefinitions)this.templates[e]=new CKEDITOR.template(this.templateDefinitions[e]);
+this.parts={},this.lang=t.editor.lang.a11ychecker,this.build()}return t.prototype={templateDefinitions:{wrapper:'',title:'',info:''},setTitle:function(t){this.parts.title.setHtml(t)},setInfo:function(t){this.parts.info.setHtml(t)},build:function(){this.parts={wrapper:CKEDITOR.dom.element.createFromHtml(this.templates.wrapper.output()),title:CKEDITOR.dom.element.createFromHtml(this.templates.title.output()),info:CKEDITOR.dom.element.createFromHtml(this.templates.info.output())},this.parts.title.appendTo(this.parts.wrapper),this.parts.info.appendTo(this.parts.wrapper)}},CKEDITOR.event.implementOn(t.prototype),t}(),u=function(t){"use strict";function e(t,e){this.viewer=t,this.lang=e,this.templates={};for(var n in this.templateDefinitions)this.templates[n]=new CKEDITOR.template(this.templateDefinitions[n]);this.templates.counterText=new CKEDITOR.template(this.lang.navigationCounter),
+this.parts={},this.build()}function n(t,e){return function(n){var i=n.data.getKeystroke();i==t&&(e.call(this),n.data.preventDefault())}}var i={};return i[t.testability.ERROR]="error",i[t.testability.WARNING]="warning",i[t.testability.NOTICE]="notice",e.prototype={templateDefinitions:{wrapper:'',counter:'',buttonWrapper:'',button:''},update:function(t,e,n){var s=this.lang.testability,a=s[void 0!==n?n:1],r=i[void 0!==n?n:1];this.parts.counter.setText(this.templates.counterText.output({current:t+1,total:e,testability:a}));for(var o in i)this.parts.wrapper.removeClass("cke_a11yc_testability_"+i[o]);this.parts.wrapper.addClass("cke_a11yc_testability_"+r)},build:function(){
+this.parts={wrapper:CKEDITOR.dom.element.createFromHtml(this.templates.wrapper.output()),counter:CKEDITOR.dom.element.createFromHtml(this.templates.counter.output()),previous:CKEDITOR.dom.element.createFromHtml(this.templates.button.output({title:this.lang.navigationPrevTitle,"class":"previous",text:this.lang.navigationPrev})),next:CKEDITOR.dom.element.createFromHtml(this.templates.button.output({title:this.lang.navigationNextTitle,"class":"next",text:this.lang.navigationNext}))};var t=CKEDITOR.dom.element.createFromHtml(this.templates.buttonWrapper.output()),e=t.clone();t.append(this.parts.previous),e.append(this.parts.next),this.parts.wrapper.append(this.parts.counter),this.parts.wrapper.append(t),this.parts.wrapper.append(e),this.parts.previous.unselectable(),this.parts.next.unselectable();var i=n(32,function(t){this.fire("click")});this.parts.previous.on("keydown",i),this.parts.next.on("keydown",i),this.parts.previous.on("click",function(){this.fire("previous")},this),this.parts.next.on("click",function(){
+this.fire("next")},this)}},CKEDITOR.event.implementOn(e.prototype),e}(k),l=function(){"use strict";function t(t,e){e&&(CKEDITOR.tools.extend(this,e,!0),this.name=t,this.id=CKEDITOR.tools.getNextId()+"_input",this.wrapper=CKEDITOR.dom.element.createFromHtml(this.wrapperTemplate.output({label:this.label,id:this.id})))}return t.prototype={wrapperTemplate:new CKEDITOR.template(''),getValue:function(){return this.input.getValue()},setValue:function(t){this.input.setValue(t)},setInitialValue:function(){void 0!==this.value&&this.setValue(this.value)},remove:function(){this.wrapper.remove()}},t}(),d=function(t){"use strict";var e={Text:function(e,n){t.apply(this,arguments),this.input=CKEDITOR.dom.element.createFromHtml(this.inputTemplate.output({id:this.id})),this.input.appendTo(this.wrapper),this.setInitialValue()},Checkbox:function(e,n){t.apply(this,arguments),
+this.input=CKEDITOR.dom.element.createFromHtml(this.inputTemplate.output({id:this.id})),this.input.appendTo(this.wrapper),this.setInitialValue()},Select:function(e,n){var i,s;t.apply(this,arguments),this.options={},this.input=CKEDITOR.dom.element.createFromHtml(this.inputTemplate.output({id:this.id}));for(i in n.options)s=new CKEDITOR.dom.element("option"),s.setText(n.options[i]),s.setAttribute("value",i),s.appendTo(this.input),this.options[i]=s;this.input.appendTo(this.wrapper),this.setInitialValue()}};return e.Text.prototype=CKEDITOR.tools.extend(new t,{inputTemplate:new CKEDITOR.template('')}),e.Checkbox.prototype=CKEDITOR.tools.extend(new t,{inputTemplate:new CKEDITOR.template(''),getValue:function(){return this.input.$.checked;
+}},!0),e.Select.prototype=CKEDITOR.tools.extend(new t,{inputTemplate:new CKEDITOR.template('')}),e}(l),h=function(t){"use strict";function e(t){this.viewer=t,this.templates={};for(var e in this.templateDefinitions)this.templates[e]=new CKEDITOR.template(this.templateDefinitions[e]);this.inputs={},this.parts={},this.build()}function n(t,e){return function(n){var i=n.data.getKeystroke(),s=CKEDITOR.tools,a=s.isArray(t)?-1!==s.indexOf(t,i):i==t;a&&(e.call(this,n),n.data.preventDefault())}}return e.prototype={templateDefinitions:{wrapper:'',fieldset:'',actionset:'',buttonWrapper:'',button:''
+},addInput:function(e,n){this.inputs[e]=new(t[CKEDITOR.tools.capitalize(n.type)])(e,n),this.inputs[e].wrapper.appendTo(this.parts.fieldset),this.fire("addInput",this.inputs[e])},removeInput:function(t){this.inputs[t].remove(),this.fire("removeInput",this.inputs[t]),this.inputs[t]=null},setInputs:function(t){this.removeInputs(),this.inputs={};for(var e in t)this.addInput(e,t[e])},removeInputs:function(){for(var t in this.inputs)this.removeInput(t)},serialize:function(){var t={};for(var e in this.inputs)t[e]=this.inputs[e].getValue();return t},build:function(){var t=this.viewer.editor.lang.a11ychecker;this.parts={wrapper:CKEDITOR.dom.element.createFromHtml(this.templates.wrapper.output()),fieldset:CKEDITOR.dom.element.createFromHtml(this.templates.fieldset.output()),actionset:CKEDITOR.dom.element.createFromHtml(this.templates.actionset.output()),quickfixButton:CKEDITOR.dom.element.createFromHtml(this.templates.button.output({title:t.quickFixButtonTitle,text:t.quickFixButton,"class":"cke_a11yc_ui_button_ok"
+})),ignoreButton:CKEDITOR.dom.element.createFromHtml(this.templates.button.output({title:t.ignoreBtnTitle,text:t.ignoreBtn,"class":"cke_a11yc_ui_button_ignore"}))},this.parts.fieldset.appendTo(this.parts.wrapper),this.parts.actionset.appendTo(this.parts.wrapper);var e=CKEDITOR.dom.element.createFromHtml(this.templates.buttonWrapper.output({"class":"cke_a11yc_ui_button_ok_wrapper"})),i=CKEDITOR.dom.element.createFromHtml(this.templates.buttonWrapper.output({"class":"cke_a11yc_ui_button_ignore_wrapper"}));this.parts.quickfixButton.appendTo(e),this.parts.ignoreButton.appendTo(i),e.appendTo(this.parts.actionset),i.appendTo(this.parts.actionset),this.parts.quickfixButton.on("click",function(t){this.fire("submit"),t.data.preventDefault()},this),this.parts.fieldset.on("keydown",n(13,function(t){this.fire("submit")}),this),this.parts.quickfixButton.on("keydown",n(32,function(t){this.fire("submit")}),this),this.parts.ignoreButton.on("click",function(t){this.fire("ignore"),t.data.preventDefault();
+},this),this.parts.ignoreButton.on("keydown",function(t){32==t.data.getKeystroke()&&(t.data.preventDefault(),this.fire("ignore"))},this)},show:function(){this.parts.fieldset.show(),this.parts.quickfixButton.show()},hide:function(){this.parts.fieldset.hide(),this.parts.quickfixButton.hide()},setIgnored:function(t){var e=this.parts.ignoreButton;e.getFirst().setHtml(this.viewer.editor.lang.a11ychecker[t?"stopIgnoreBtn":"ignoreBtn"]),e.setAttribute("aria-pressed",t)}},CKEDITOR.event.implementOn(e.prototype),e}(d),p=function(){"use strict";function t(t){this.viewer=t,this.templates={};for(var e in this.templateDefinitions)this.templates[e]=new CKEDITOR.template(this.templateDefinitions[e]);this.parts={},this.build()}return t.prototype={templateDefinitions:{wrapper:'',info:"{text}
",button:''},
+build:function(){var t=this.viewer.editor.lang.a11ychecker;this.parts={wrapper:CKEDITOR.dom.element.createFromHtml(this.templates.wrapper.output()),info:CKEDITOR.dom.element.createFromHtml(this.templates.info.output({text:t.listeningInfo})),button:CKEDITOR.dom.element.createFromHtml(this.templates.button.output({title:t.listeningCheckAgain,text:t.listeningCheckAgain}))},this.parts.wrapper.append(this.parts.info),this.parts.wrapper.append(this.parts.button),this.parts.button.on("click",function(){this.fire("check")},this)}},CKEDITOR.event.implementOn(t.prototype),t}(),f=function(){"use strict";function t(){this.list=[]}return t.prototype={},t.prototype.constructor=t,t.prototype.count=function(){return this.list.length},t.prototype.addItem=function(t){t.on("keydown",this.keyDownListener,this),this.list.push(t),this.sort()},t.prototype.removeItem=function(t){"number"!=typeof t&&(t=CKEDITOR.tools.indexOf(this.list,t)),this.list[t].removeListener("keydown",this.keyDownListener),this.list.splice(t,1);
+},t.prototype.getItem=function(t){return this.list[t]},t.prototype.keyDownListener=function(t){var e=CKEDITOR.tools.indexOf(this.list,t.sender),n=t.data.getKey(),i=t.data.getKeystroke();if(-1!==e&&1!==this.list.length&&9==n){var s=i&CKEDITOR.SHIFT,a=s?this.getPrev(e):this.getNext(e);a&&(a.focus(),t.data.preventDefault(1),t.data.stopPropagation())}},t.prototype.getNext=function(t){var e,n=0,i=this.list.length;"number"==typeof t&&i>t+1&&(n=t+1),e=this.getItem(n);var s,a;for(s=1;i-1>s&&!e.isVisible();s++)a=n+s,a>=i&&(a-=i),e=this.getItem(a);return s!=i-1||e.isVisible()?e:void 0},t.prototype.getPrev=function(t){var e,n=this.list.length,i=n-1;"number"==typeof t&&t>0&&(i=t-1),e=this.getItem(i);var s,a;for(s=1;n-1>s&&!e.isVisible();s++)a=i-s,0>a&&(a=n+a),e=this.getItem(a);return s!=n-1||e.isVisible()?e:void 0},t.prototype.sort=function(){this.list.sort(this._sort)},t.prototype._sort=function(t,e){var n=0;return n=t.getPosition(e)&CKEDITOR.POSITION_FOLLOWING?1:-1},t}(),g=function(){"use strict";
+function t(t,e){this.viewer=t,CKEDITOR.tools.extend(this,e),this.panelShowListeners=this.panelShowListeners(t),this.activePanelShowlisteners=[]}return t.prototype={enterMode:function(){this.init&&this.init(this.viewer),this.addPanelShowListeners()},leaveMode:function(){this.close&&this.close(this.viewer),this.removePanelShowListeners()},addPanelShowListener:function(t){this.activePanelShowlisteners.push(t)},addPanelShowListeners:function(t){if(this.panelShowListeners)for(var e=0;es;s++)t[s].display(n,e.editor);i&&n.show()},i)},quickFixAccepted:function(t){var e,n=this.viewer.editor,i=n._.a11ychecker,s=i.viewerController,a=this.serialize(),r=s.quickFixSelected;if(r)if(e=r.validate(a),e.length){alert(e.join(","));var o=CKEDITOR.tools.objectKeys(this.inputs);o.length&&this.inputs[o[0]].input.focus(),t.cancel()}else i.applyQuickFix(r,a);else console.error("No quickfix available!"),t.cancel()},showIssue:function(t,e){t.element.scrollIntoView(),this.viewer.panel.attach(t.element),e&&(e.event&&this.fire(e.event),e.callback&&e.callback.call(this))},startListening:function(){this.viewer.setMode("listening"),this.viewer.panel.show(),this.editor.focus()},stopListening:function(){this.viewer.panel.hide(),this.viewer.setMode("checking")}},CKEDITOR.event.implementOn(e.prototype),
+e}(m),b=function(){"use strict";function t(e){if(this.controller=e,e){var n=t.parseConfig(e.editor.config.a11ychecker_keystrokes);this.setEditorHotkeys(e.editor,n),this.setBalloonHotkeys(e.viewerController,n)}}return t.prototype={},t.prototype.constructor=t,t.prototype.setEditorHotkeys=function(t,e){for(var n in e)t.setKeystroke(Number(n),e[n])},t.prototype.setBalloonHotkeys=function(t,e){var n=this,i=n.controller.editor,s=t.viewer.panel,a=s.parts.panel;s.addShowListener(function(){return a.on("keydown",n.getBalloonKeydown(i,e))})},t.prototype.getBalloonKeydown=function(t,e){return function(n){var i=e[n.data.getKeystroke()];i&&(t.execCommand(i),n.data.preventDefault())}},t.parseConfig=function(t){var e,n,i={},s=t||{},a={open:CKEDITOR.CTRL+CKEDITOR.ALT+69,next:CKEDITOR.CTRL+69,prev:CKEDITOR.CTRL+CKEDITOR.SHIFT+69,listen:CKEDITOR.SHIFT+27,close:27};for(n in a)void 0===s[n]&&(s[n]=a[n]),e="open"==n?"":"."+n,i[s[n]]="a11ychecker"+e;return i},t}(),y=function(){"use strict";function t(){}return t.getPreferredLanguage=function(t,e,n,i){
+i=i||window.navigator;var s=[t,e,"en"],a=/([a-z]+)(?:-([a-z]+))?/,r=i.language||i.userLanguage,o=CKEDITOR.tools.indexOf;r&&s.splice(1,0,r);for(var c=0,u=s.length;u>c;c++)if(s[c]){var l=s[c].toLowerCase(),d=l.match(a),h=d[1],p=d[2];if(p&&-1!==o(n,l))return l;if(-1!==o(n,h))return h}return null},t}(),x=function(t,e,n,i,s,a,r,o,c){"use strict";function u(t){this._={},this.editor=t,this.editableDecorator=new i(this.editor),this.ui=new a(this),this.preferredIssueFinder=new s,t&&(this.viewerController=new r(this,{title:t.lang.a11ychecker.balloonLabel}),this.attachEditorListeners(t),this.hotkeyManager=new o(this))}return u.modes={CHECKING:1,LISTENING:2,BUSY:3},u.prototype={issues:null,viewerController:null,enabled:!1,disableFilterStrip:!1},u.prototype.constructor=u,u.prototype.setEngine=function(t){this.engine=t},u.prototype.exec=function(t){return this.enabled?void this.close():(this.issues&&this.issues.clear(),this.enable(),void this.check({ui:!0,callback:t}))},u.prototype.listen=function(){
+if(this.enabled){var t=u.modes;if(this.modeType===t.LISTENING)this.check();else{var e=this.issues.getFocused()&&this.issues.getFocused().element;this.setMode(t.LISTENING),e&&this.editor.getSelection().selectElement(e)}}},u.prototype.check=function(t){t=t||{};var e,n=this,i=n.editor;this.setMode(u.modes.BUSY),t.ui&&this.ui.show(),e=this.getTempOutput(),this.editableDecorator.applyMarkup(),this.editableDecorator.decorateScratchpad(e),this.disableFilterStrip=!0,e.setHtml(i.getData()),this.disableFilterStrip=!1,CKEDITOR.document.getBody().append(e);var s=function(e){n._engineProcessed.call(n,e,t)};this.engine.process(this,e,s)},u.prototype.disable=function(){this.enabled&&(this.enabled=!1,this.fire("disabled"))},u.prototype.enable=function(){this.enabled||(this.enabled=!0,this.fire("enabled"),this.setMode(u.modes.CHECKING))},u.prototype.next=function(t){var e,n=this.issues;0!==n.count()&&(e=this.issues.next(),this.viewerController.showIssue(e,{event:"next",callback:t}))},u.prototype.prev=function(t){
+var e,n=this.issues;0!==n.count()&&(e=this.issues.prev(),this.viewerController.showIssue(e,{event:"prev",callback:t}))},u.prototype.showIssue=function(t,e){var n,i,s=this.issues,a=t,r=function(){this.viewer.navigation.parts.next.focus(),e&&e.call(this)};return"number"!=typeof a&&(a=s.indexOf(a)),n=s.getItem(a),n&&n==s.getFocused()?(r.call(this.viewerController),!0):(i=s.moveTo(a),i&&this.viewerController&&this.viewerController.showIssue(s.getItem(a),{callback:r}),i)},u.prototype.showIssueByElement=function(t,e){var n=this.issues.getIssueByElement(t);return n?this.showIssue(n,e):!1},u.prototype.ignoreIssue=function(){var t=this.issues.getFocused();t&&(t.setIgnored(!t.isIgnored()),this.editableDecorator.markIssueElement(t,this.issues))},u.prototype.close=function(){this.enabled&&(this.ui.hide(),this.disable(),this.issues.clear(),this.preferredIssueFinder.unset(),this.mode.close(),this.mode=null,this.modeType=null)},u.prototype.setMode=function(i){var s,a={};if(a[u.modes.CHECKING]=t,a[u.modes.LISTENING]=e,
+a[u.modes.BUSY]=n,s=a[i],!s)throw new Error("Invalid mode value, use Controller.modes members");i!==this.modeType&&(this.mode&&this.mode.close(),this.mode=new s(this),this.mode.init(),this.modeType=i)},u.prototype.attachEditorListeners=function(t){var e=this,n=["a11ychecker","a11ychecker.listen","a11ychecker.next","a11ychecker.prev","a11ychecker.close","wysiwyg","source"];t.on("beforeSetMode",function(){e.close()}),t.on("beforeCommandExec",function(t){var i=String(t.data.name);-1===CKEDITOR.tools.indexOf(n,i)&&e.enabled&&e.setMode(u.modes.LISTENING)},null,null,9999)},u.prototype.applyQuickFix=function(t,e){this._withUndoManager(function(){var e=this.mode,n=this.editor;this.editableDecorator.removeMarkup(),t.markSelection(n,n.getSelection()),e.unsetStoredSelection&&e.unsetStoredSelection(),this.editor.fire("updateSnapshot")}),t.fix(e,CKEDITOR.tools.bind(this._onQuickFix,this))},u.prototype._onQuickFix=function(t){this._withUndoManager(function(){this.editor.fire("saveSnapshot")});var e={
+quickFix:t,issue:t.issue},n=this.fire("fixed",e,this.editor);n!==!1&&this.check({ui:!0})},u.prototype._setIssueList=function(t){var e=this;t.sort(),t.on("focusChanged",function(t){var n=t.data.current;n&&e.preferredIssueFinder.set(n)}),e.issues=t},u.prototype.onNoIssues=function(){alert(this.editor.lang.a11ychecker.noIssuesMessage),this.close()},u.prototype.getTempOutput=function(){var t=this._;return t.scratchpad||(t.scratchpad=CKEDITOR.document.createElement("div"),t.scratchpad.setStyle("display","none")),t.scratchpad},u.prototype.getQuickFixLang=function(){var t=this.editor,e=t.config,n=t.plugins.a11ychecker.quickFixesLang.split(",");return c.getPreferredLanguage(e.language,e.defaultLanguage,n)||n[0]},u.prototype._engineProcessed=function(t,e){var n,i,s=this;s.editableDecorator.resolveEditorElements(t),s._setIssueList(t),s.setMode(u.modes.CHECKING),e.ui&&s.ui.update(),n=s.fire("checked",{issues:t}),e.callback&&e.callback.call(s,t.count(!0)===!0,t),n!==!1&&(t.count()?(i=s.preferredIssueFinder.getFromListIndex(t)||0,
+i>=t.count()&&(i=0),s.showIssue(t.getItem(i))):s.onNoIssues())},u.prototype._withUndoManager=function(t){var e=this.editor,n=!!e.undoManager.locked;n&&e.fire("unlockSnapshot"),t.call(this),n&&e.fire("lockSnapshot",{dontUpdate:!0})},CKEDITOR.event.implementOn(u.prototype),u}(n,i,s,a,r,o,v,b,y),E=function(){"use strict";function t(){}return t.prototype={guideline:["aAdjacentWithSameResourceShouldBeCombined","aImgAltNotRepetitive","aLinksAreSeparatedByPrintableCharacters","aMustNotHaveJavascriptHref","aSuspiciousLinkText","blockquoteNotUsedForIndentation","documentVisualListsAreMarkedUp","headerH1","headerH2","headerH3","headerH4","imgAltIsDifferent","imgAltIsTooLong","imgAltNotEmptyInAnchor","imgAltTextNotRedundant","imgHasAlt","imgShouldNotHaveTitle","pNotUsedAsHeader","tableDataShouldHaveTh","imgWithEmptyAlt"]},t}(),function(){"use strict";function t(t){return o(t)?r(t,"a11ychecker.next","next"):void 0}function n(t){return o(t)?r(t,"a11ychecker.prev","prev"):void 0}function i(t){return r(t,"a11ychecker","exec");
+}function s(t){return t._.a11ychecker.listen()}function a(t){return t._.a11ychecker.close()}function r(t,e,n){return t._.a11ychecker[n](function(){t.fire("afterCommandExec",{name:e,command:t.getCommand(e),commandData:{}})})}function o(t){var e=t._.a11ychecker;return e&&e.modeType===e.constructor.modes.CHECKING}function c(t){var e=this.config,n=e.contentsCss;CKEDITOR.tools.isArray(n)||(e.contentsCss=n?[n]:[]),e.contentsCss.push(t)}var u="a11ychecker";CKEDITOR.plugins.add(u,{requires:"balloonpanel",lang:"en,nl,de,pt-br",quickFixesLang:"en,nl,de,pt-br",icons:u,hidpi:!0,onLoad:function(){var t=this.path;CKEDITOR.document.appendStyleSheet(t+"skins/"+this.getStylesSkinName()+"/a11ychecker.css"),function(e,n,i,s,a){CKEDITOR.tools.extend(CKEDITOR.plugins.a11ychecker,{Engine:e,Issue:n,IssueList:i,IssueDetails:s}),CKEDITOR.plugins.a11ychecker.quickFixes=new a(t+"quickfix/")}(T,k,C,I,e)},beforeInit:function(t){var e=this;t.config.a11ychecker_noIgnoreData||t.filter.allow("*[data-a11y-ignore]","a11ychecker"),
+this.createTemporaryNamespace(t),t.once("instanceReady",function(){!function(n){var i=new n(t),s=t._.a11ychecker;t._.a11ychecker=i,s.getEngineType(function(n){i.setEngine(new n(e)),i.engine.config=i.engine.createConfig(t),s.fire("loaded",null,t)})}(x)}),e.commandRegister.call(e,t),e.guiRegister(t)},guiRegister:function(t){var e=this.path+"skins/"+this.getStylesSkinName()+"/contents.css",n=t.addContentsCss||c;t.ui.addButton&&t.ui.addButton("A11ychecker",{label:t.lang.a11ychecker.toolbar,command:u,toolbar:"document,10"}),n.call(t,e)},commandRegister:function(e){e.addCommand(u,{exec:i,async:!0,canUndo:!1,editorFocus:!1}),e.addCommand(u+".listen",{exec:s,canUndo:!1,editorFocus:!1}),e.addCommand(u+".next",{exec:t,async:!0,canUndo:!1,editorFocus:!1}),e.addCommand(u+".prev",{exec:n,async:!0,canUndo:!1,editorFocus:!1}),e.addCommand(u+".close",{exec:a})},createTemporaryNamespace:function(t){t._.a11ychecker={getEngineType:function(t){function e(t){this.jsonPath=(t?t.path:"")+"libs/quail/"}var n,i,s=CKEDITOR.plugins.a11ychecker,a=s.Engine,r=s.IssueList,o=s.Issue,c=s.IssueDetails,u=window.jQuery||window.$;
+!function(t){i=t}(E),function(){if(!u||!u.fn)throw new Error("Missing jQuery. Accessibility Checker's default engine, Quail.js requires jQuery to work correctly.");u.fn.quail||!function(t){Function.prototype.bind=Function.prototype.bind||function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=Array.prototype.slice,n=e.call(arguments,1),i=this,s=function(){},a=function(){return i.apply(this instanceof s?this:t||window,n.concat(e.call(arguments)))};return s.prototype=this.prototype,a.prototype=new s,a};var e={options:{},components:{},lib:{},testabilityTranslation:{0:"suggestion",.5:"moderate",1:"severe"},html:null,strings:{},accessibilityResults:{},accessibilityTests:null,guidelines:{wcag:{setup:function(t,e,n){n=n||{};for(var i in this.successCriteria)if(this.successCriteria.hasOwnProperty(i)){var s=this.successCriteria[i];s.registerTests(t),e&&e.listenTo&&"function"==typeof e.listenTo&&n.successCriteriaEvaluated&&e.listenTo(s,"successCriteriaEvaluated",n.successCriteriaEvaluated);
+}},successCriteria:{}}},tests:{},textSelector:":not(:empty)",suspectPHeaderTags:["strong","b","em","i","u","font"],suspectPCSSStyles:["color","font-weight","font-size","font-family"],focusElements:"a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]",emoticonRegex:/((?::|;|B|P|=)(?:-)?(?:\)|\(|o|O|D|P))/g,selfClosingTags:["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"],optionalClosingTags:["p","li","th","tr","td"],run:function(n){function i(t,e,n){if(n.guideline&&n.guideline.length){t.tests=t.lib.TestCollection([],{scope:t.html||null});for(var i=0,s=n.guideline.length;s>i;++i){var a=n.guideline[i];e[a]&&(e[a].scope=t.html||null,t.tests.set(a,e[a]))}}else t.tests=t.lib.TestCollection(e,{scope:t.html||null})}function s(){if("undefined"!=typeof n.customTests)for(var t in n.customTests)n.customTests.hasOwnProperty(t)&&(n.customTests[t].scope=e.html||null,
+e.tests.set(t,n.customTests[t]));var i=function(){};for(var s in e.guidelines)e.guidelines[s]&&"function"==typeof e.guidelines[s].setup&&e.guidelines[s].setup(e.tests,this,{successCriteriaEvaluated:n.successCriteriaEvaluated||i});e.tests.run({preFilter:n.preFilter||function(){},caseResolve:n.caseResolve||function(){},testComplete:n.testComplete||function(){},testCollectionComplete:n.testCollectionComplete||function(){},complete:n.complete||function(){}})}if(n.reset&&(e.accessibilityResults={}),e.tests=e.lib.TestCollection([],{scope:e.html||null}),"undefined"!=typeof quailBuilderTests)e.tests=e.lib.TestCollection(quailBuilderTests,{scope:e.html||null}),s.call(e);else if("wcag2"===n.guideline)e.lib.wcag2.run(n);else if(n.accessibilityTests)i(e,n.accessibilityTests,n),s.call(e);else{var a=n.jsonPath;"string"==typeof n.guideline&&(a+="/guidelines/"+n.guideline),t.ajax({url:a+"/tests.json",dataType:"json",success:function(t){"object"==typeof t&&(i(e,t,n),s.call(e))},error:function(){throw new Error("Tests could not be loaded");
+}})}},listenTo:function(t,e,n){n=n.bind(this),t.registerListener.call(t,e,n)},getConfiguration:function(t){var e=this.tests.find(t),n=e&&e.get("guidelines"),i=n&&this.options.guidelineName&&n[this.options.guidelineName],s=i&&i.configuration;return s?s:!1},isUnreadable:function(t){return"string"!=typeof t?!0:t.trim().length?!1:!0},isDataTable:function(e){if(e.find("tr").length<3)return!1;if(e.find("th[scope]").length)return!0;var n=e.find("tr:has(td)").length,i=e.find("td[rowspan], td[colspan]"),s=!0;if(i.length){var a={};i.each(function(){"undefined"==typeof a[t(this).index()]&&(a[t(this).index()]=0),a[t(this).index()]++}),t.each(a,function(t,e){n>e&&(s=!1)})}var r=e.find("table");if(r.length){var o={};r.each(function(){var e=t(this).parent("td").index();e!==!1&&"undefined"==typeof o[e]&&(o[e]=0),o[e]++}),t.each(o,function(t,e){n>e&&(s=!1)})}return s},getTextContents:function(t){if(t.is("p, pre, blockquote, ol, ul, li, dl, dt, dd, figure, figcaption"))return t.text();for(var e="",n=t[0].childNodes,i=0,s=n.length;s>i;i+=1)3===n[i].nodeType&&(e+=n[i].nodeValue);
+return e},validURL:function(t){return-1===t.search(" ")},cleanString:function(t){return t.toLowerCase().replace(/^\s\s*/,"")},containsReadableText:function(n,i){if(n=n.clone(),n.find("option").remove(),!e.isUnreadable(n.text()))return!0;if(!e.isUnreadable(n.attr("alt")))return!0;if(i){var s=!1;if(n.find("*").each(function(){e.containsReadableText(t(this),!0)&&(s=!0)}),s)return!0}return!1}};if(window&&(window.quail=e),t.fn.quail=function(t){return this.length?(e.options=t,e.html=this,e.run(t),this):this},t.expr[":"].quailCss=function(e,n,i){var s=i[3].split(/\s*=\s*/);return t(e).css(s[0]).search(s[1])>-1},e.components.acronym=function(e,n,i){n.get("$scope").each(function(){var e=t(this),s={},a={};e.find("acronym[title], abbr[title]").each(function(){a[t(this).text().toUpperCase().trim()]=t(this).attr("title")}),e.find("p, div, h1, h2, h3, h4, h5").each(function(){var e=this,r=t(e),o=r.text().split(" "),c=[];o.length>1&&r.text().toUpperCase()!==r.text()?(t.each(o,function(t,e){e.length<2||(e=e.replace(/[^a-zA-Zs]/,""),
+e.toUpperCase()===e&&"undefined"==typeof a[e.toUpperCase().trim()]&&("undefined"==typeof s[e.toUpperCase()]&&c.push(e),s[e.toUpperCase()]=e))}),n.add(i(c.length?{element:e,expected:r.closest(".quail-test").data("expected"),info:{acronyms:c},status:"failed"}:{element:e,expected:r.closest(".quail-test").data("expected"),status:"passed"}))):n.add(i({element:e,expected:r.closest(".quail-test").data("expected"),status:"passed"}))})})},e.components.color=function(){function n(t,n,i,s,a,r){t.add(n({element:i,expected:function(t,n){return e.components.resolveExpectation(t,n)}(i,a),message:r,status:s}))}function i(e){return""!==t.trim(e)}function s(n){var i=n.parentNode,s=t(i);return 1!==i.nodeType?!1:-1!==["script","style","title","object","applet","embed","template","noscript"].indexOf(i.nodeName.toLowerCase())?!1:e.isUnreadable(s.text())?!1:!0}function a(t){function e(t){return Object.keys(t).length}var n={},i=t.groupCasesBySelector(),s="";for(var a in i)if(i.hasOwnProperty(a)){var r=i[a];r.each(function(t,e){
+e.get("status")===n&&(n[a]=s)})}return e(n)===e(i)}var r={cache:{},getLuminosity:function(t,e){var n="getLuminosity_"+t+"_"+e;if(t=r.parseColor(t),e=r.parseColor(e),void 0!==r.cache[n])return r.cache[n];var i,s,a=t.r/255,o=t.g/255,c=t.b/255,u=.03928>=a?a/12.92:Math.pow((a+.055)/1.055,2.4),l=.03928>=o?o/12.92:Math.pow((o+.055)/1.055,2.4),d=.03928>=c?c/12.92:Math.pow((c+.055)/1.055,2.4),h=e.r/255,p=e.g/255,f=e.b/255,g=.03928>=h?h/12.92:Math.pow((h+.055)/1.055,2.4),m=.03928>=p?p/12.92:Math.pow((p+.055)/1.055,2.4),v=.03928>=f?f/12.92:Math.pow((f+.055)/1.055,2.4);return i=.2126*u+.7152*l+.0722*d,s=.2126*g+.7152*m+.0722*v,r.cache[n]=Math.round((Math.max(i,s)+.05)/(Math.min(i,s)+.05)*10)/10,r.cache[n]},fetchImageColorAtPixel:function(t,e,n){e="undefined"!=typeof e?e:1,n="undefined"!=typeof n?n:1;var i=document.createElement("canvas"),s=i.getContext("2d");s.drawImage(t,0,0);var a=s.getImageData(e,n,1,1).data;return"rgb("+a[0]+","+a[1]+","+a[2]+")"},testElmContrast:function(t,e,n){var i=r.getColor(e,"background");
+return r.testElmBackground(t,e,i,n)},testElmBackground:function(t,e,n,i){var s,a=r.getColor(e,"foreground");return"wcag"===t?s=r.passesWCAGColor(e,a,n,i):"wai"===t&&(s=r.passesWAIColor(a,n)),s},passesWCAGColor:function(t,n,i,s){var a=e.components.convertToPx(t.css("fontSize"));if("undefined"==typeof s)if(a>=18)s=3;else{var o=t.css("fontWeight");s=a>=14&&("bold"===o||parseInt(o,10)>=700)?3:4.5}return r.getLuminosity(n,i)>s},passesWAIColor:function(t,e){var n=r.getWAIErtContrast(t,e),i=r.getWAIErtBrightness(t,e);return n>500&&i>125},getWAIErtContrast:function(t,e){var n=r.getWAIDiffs(t,e);return n.red+n.green+n.blue},getWAIErtBrightness:function(t,e){var n=r.getWAIDiffs(t,e);return(299*n.red+587*n.green+114*n.blue)/1e3},getWAIDiffs:function(t,e){return{red:Math.abs(t.r-e.r),green:Math.abs(t.g-e.g),blue:Math.abs(t.b-e.b)}},getColor:function(e,n){var i=r;e.attr("data-cacheId")||e.attr("data-cacheId","id_"+Math.random());var s="getColor_"+n+"_"+e.attr("data-cacheId");if(void 0!==r.cache[s])return r.cache[s];
+if("foreground"===n)return r.cache[s]=e.css("color")?e.css("color"):"rgb(0,0,0)",r.cache[s];var a=e.css("background-color");return r.hasBackgroundColor(a)?(r.cache[s]=a,r.cache[s]):(e.parents().each(function(){var e=t(this).css("background-color");return r.hasBackgroundColor(e)?i.cache[s]=e:void 0}),r.cache[s]="rgb(255,255,255)",r.cache[s])},getForeground:function(t){return r.getColor(t,"foreground")},parseColor:function(t){return"object"==typeof t?t:"#"===t.substr(0,1)?{r:parseInt(t.substr(1,2),16),g:parseInt(t.substr(3,2),16),b:parseInt(t.substr(5,2),16),a:!1}:"rgb"===t.substr(0,3)?(t=t.replace("rgb(","").replace("rgba(","").replace(")","").split(","),{r:t[0],g:t[1],b:t[2],a:"undefined"==typeof t[3]?!1:t[3]}):void 0},getBackgroundImage:function(e){e.attr("data-cacheId")||e.attr("data-cacheId","id_"+Math.random());var n="getBackgroundImage_"+e.attr("data-cacheId");if(void 0!==r.cache[n])return r.cache[n];for(e=e[0];e&&1===e.nodeType&&"BODY"!==e.nodeName&&"HTML"!==e.nodeName;){var i=t(e).css("background-image");
+if(i&&"none"!==i&&-1!==i.search(/^(.*?)url(.*?)$/i))return r.cache[n]=i.replace("url(","").replace(/['"]/g,"").replace(")",""),r.cache[n];e=e.parentNode}return r.cache[n]=!1,!1},getBackgroundGradient:function(e){e.attr("data-cacheId")||e.attr("data-cacheId","id_"+Math.random());var n="getBackgroundGradient_"+e.attr("data-cacheId");if(void 0!==r.cache[n])return r.cache[n];var i=function(e){return""!==t.trim(e)};for(e=e[0];e&&1===e.nodeType&&"BODY"!==e.nodeName&&"HTML"!==e.nodeName;){if(r.hasBackgroundColor(t(e).css("background-color")))return r.cache[n]=!1,!1;var s=t(e).css("backgroundImage");if(s&&"none"!==s&&-1!==s.search(/^(.*?)gradient(.*?)$/i)){var a=s.match(/gradient(\(.*\))/g);if(a.length>0)return a=a[0].replace(/(linear|radial|from|\bto\b|gradient|top|left|bottom|right|\d*%)/g,""),r.cache[n]=t.grep(a.match(/(rgb\([^\)]+\)|#[a-z\d]*|[a-z]*)/g),i),r.cache[n]}e=e.parentNode}return r.cache[n]=!1,!1},getAverageRGB:function(t){var e=t.src;if(void 0!==r.cache[e])return r.cache[e];var n,i,s,a,o=5,c={
+r:0,g:0,b:0},u=document.createElement("canvas"),l=u.getContext&&u.getContext("2d"),d=-4,h={r:0,g:0,b:0,a:0},p=0;if(!l)return r.cache[e]=c,c;s=u.height=t.height,i=u.width=t.width,l.drawImage(t,0,0);try{n=l.getImageData(0,0,i,s)}catch(f){return r.cache[e]=c,c}for(a=n.data.length;(d+=4*o)0&&(p=p[0].replace(/(linear|radial|from|\bto\b|gradient|top|left|bottom|right|\d*%)/g,""),a=t.grep(p.match(/(rgb\([^\)]+\)|#[a-z\d]*|[a-z]*)/g),i))}break;case"background-image":if(r.hasBackgroundColor(h)){a=!1;continue}d=l.css("backgroundImage"),d&&"none"!==d&&-1!==d.search(/^(.*?)url(.*?)$/i)&&(a=d.replace("url(","").replace(/['"]/g,"").replace(")",""))}o.push({element:l,visibility:l.css("visibility")}),l.css("visibility","hidden"),l=document.elementFromPoint(c,u)}for(var f=0;fn.data("content-score"))&&(n=e)}),n)}},e.components.convertToPx=function(n){if(n.search("px")>-1)return parseInt(n,10);var i=t('').appendTo(e.html),s=i.height();return i.remove(),s},e.components.event=function(e,n,i,s){var a=n.get("$scope"),r=s.selector&&a.find(s.selector)||a.find("*"),o=s.searchEvent||"",c=s.correspondingEvent||"";r.each(function(){var s,a=o.replace("on",""),r=e.components.hasEventListener(t(this),a);t._data&&(s=t._data(this,"events"));var u=s&&s[a]&&!!s[a].length,l=!!c.length,d=e.components.hasEventListener(t(this),c.replace("on","")),h=t(this).closest(".quail-test").data("expected"),p=n.add(i({element:this,expected:h}));p.set(!r&&!u||l&&d?{status:"passed"}:{status:"failed"})})},e.components.hasEventListener=function(e,n){return"undefined"!=typeof t(e).attr("on"+n)?!0:t._data(t(e)[0],"events")&&"undefined"!=typeof t._data(t(e)[0],"events")[n]?!0:t(e).is("a[href], input, button, video, textarea")&&"undefined"!=typeof t(e)[0][n]&&("click"===n||"focus"===n)&&t(e)[0][n].toString().search(/^\s*function\s*(\b[a-z$_][a-z0-9$_]*\b)*\s*\((|([a-z$_][a-z0-9$_]*)(\s*,[a-z$_][a-z0-9$_]*)*)\)\s*{\s*\[native code\]\s*}\s*$/i)>-1?!1:"undefined"!=typeof t(e)[0][n];
+},e.components.headingLevel=function(e,n,i,s){var a=!1;n.get("$scope").find(":header").each(function(){var r=parseInt(t(this).get(0).tagName.substr(-1,1),10),o=this;n.add(i(a===s.headingLevel&&r>a+1?{element:o,expected:function(t){return e.components.resolveExpectation(t)}(o),status:"failed"}:{element:this,expected:function(t){return e.components.resolveExpectation(t)}(o),status:"passed"})),a=r})},e.components.htmlSource={getHtml:function(n){var i=this;if("undefined"!=typeof e.options.htmlSource&&e.options.htmlSource)return void n(e.options.htmlSource,i.parseHtml(e.options.htmlSource));var s=t.ajax({url:window.location.href,async:!1});s&&"undefined"!=typeof s.responseText&&n(s.responseText,i.parseHtml(s.responseText))},traverse:function(e,n,i,s){var a=this;"undefined"==typeof s&&n(e,i,!1),"undefined"!=typeof e.children&&(e.childCount=1,t.each(e.children,function(t,i){n(i,e.childCount,e),a.traverse(i,n,e.childCount,!0),"tag"===i.type&&e.childCount++})),t.isArray(e)&&t.each(e,function(t,e){
+a.traverse(e,n)})},addSelector:function(t,e,n){if("tag"===t.type&&"undefined"!=typeof t.name&&"undefined"==typeof t.selector){t.selector=n&&"undefined"!=typeof n.selector?n.selector.slice():[];var i=t.name;return"undefined"!=typeof t.attributes&&("undefined"!=typeof t.attributes.id?i+="#"+t.attributes.id[0]:"undefined"!=typeof t.attributes["class"]&&(i+="."+t.attributes["class"][0].replace(/\s/,"."))),!e||"undefined"!=typeof t.attributes&&"undefined"!=typeof t.attributes.id||(i+=":nth-child("+e+")"),t.selector.push(i),t.selector}},parseHtml:function(t){if("undefined"==typeof Tautologistics)return!1;t=t.replace(/]*)>/g,"");var e=new Tautologistics.NodeHtmlParser.HtmlBuilder(function(){},{}),n=new Tautologistics.NodeHtmlParser.Parser(e);n.parseComplete(t);var i=e.dom,s=this;return this.traverse(i,s.addSelector),i}},"undefined"!=typeof Tautologistics){var n={Text:"text",Tag:"tag",Attr:"attr",CData:"cdata",Comment:"comment"};Tautologistics.NodeHtmlParser.HtmlBuilder.prototype.write=function(t){
+if(this._done&&this.handleCallback(new Error("Writing to the builder after done() called is not allowed without a reset()")),this._options.includeLocation&&t.type!==n.Attr&&(t.location=this._getLocation(),this._updateLocation(t)),t.type!==n.Text||!this._options.ignoreWhitespace||!HtmlBuilder.reWhitespace.test(t.data)){var e,i;if(this._tagStack.last())if(e=this._tagStack.last(),t.type===n.Tag)if("/"===t.name.charAt(0)){var s=this._options.caseSensitiveTags?t.name.substring(1):t.name.substring(1).toLowerCase();if(e.name===s&&(e.closingTag=!0),!this.isEmptyTag(t)){for(var a=this._tagStack.length-1;a>-1&&this._tagStack[a--].name!==s;);if(a>-1||this._tagStack[0].name===s)for(;a",u="/",l="/",d="!",h=new RegExp("[dD]"),p=new RegExp("[a-z0-9-]"),f=new RegExp("^"),g=["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"],m=["pre","code","textarea","script","style"],v=["p","li","tr","th","td"],b=function(t,e){return{name:n,line:t+1,"char":e}},y=function(t){var e=new Error("Ending tag not found for: "+t.name+" at line: "+t.line+" char: "+t["char"]+" starting tags: "+i[0].name);throw e.lineData=t,e},x=function(t){var e=new Error("Comment ending not found for: `comment` at line: "+t.line+" char: "+t["char"]);throw e.lineData=t,e},w=function(t){var e=new Error("Ending `/` not found for: `"+t.name+"` at line: "+t.line+" char: "+t["char"]);throw e.lineData=t.name,e},C=function(n){e=t,t=n},T=function(t){s-=t},k=function(t,e,s){if(p.test(t))n+=t;else if(t===u)C(_);else if(t===d)n="",C(O);else if(g.indexOf(n)>-1)r.strict_self_closing_tags?C(I):(n="",C(S));else{
+var a=b(e,s);i.push(a),m.indexOf(n)>-1?(n="",T(1),C(R)):(n="",T(1),C(E))}},I=function(t,e,i){t===l?(n="",C(q)):t===c&&w(b(e,i))},E=function(t){t===c&&C(q)},S=function(t){t===o&&C(k)},_=function(t){function e(){var t=i.pop();t.name===n?C(S):v.indexOf(t.name)>-1?e():y(t)}p.test(t)?n+=t:(e(),n="")},D=function(t){t===u?C(_):(T(1),C(k))},q=function(t){t===o&&C(D)},R=function(t){t===o&&C(F)},F=function(t){t===u&&C(A)},A=function(t){if(p.test(t))n+=t;else{var e=i.pop();e.name===n?C(S):y(e),n=""}},O=function(t){h.test(t)?(n="",C(S)):(T(3),C(L))},L=function(t,e,n){a||(a={content:"",line:e+1,"char":n+1,name:"comment"}),a.content+=t,f.test(a.content)&&(a=null,C(S))},N=function(e,o){var c=null;try{var u,l=e.split("\n");C(S),n="",i=[],a=null,r=o||{};for(var d=0,h=l.length;h>d;d++)for(s=0,u=l[d].length;u>s&&t;s++)t(l[d][s],d,s);if(a)x(a);else if(i.length>0){var p=i[i.length-1];-1===v.indexOf(p.name)&&y(p)}c=null}catch(f){c=f.message}finally{return c}};return N};e.components.htmlTagValidator=i(),e.components.label=function(e,n,i,s){
+var a=n.get("$scope");a.each(function(){var a=t(this);a.find(s.selector).each(function(){n.add(i(t(this).parent("label").length&&a.find("label[for="+t(this).attr("id")+"]").length&&e.containsReadableText(t(this).parent("label"))||e.containsReadableText(a.find("label[for="+t(this).attr("id")+"]"))?{element:this,expected:t(this).closest(".quail-test").data("expected"),status:"passed"}:{element:this,expected:t(this).closest(".quail-test").data("expected"),status:"failed"}))})})},e.components.labelProximity=function(e,n,i,s){var a=n.get("$scope");a.find(s.selector).each(function(){var e=a.find("label[for="+t(this).attr("id")+"]").first();n.add(i(e.length&&t(this).parent().is(e.parent())?{element:this,expected:t(this).closest(".quail-test").data("expected"),status:"passed"}:{element:this,expected:t(this).closest(".quail-test").data("expected"),status:"failed"}))})},e.components.language={maximumDistance:300,textDirection:{rtl:/[\u0600-\u06FF]|[\u0750-\u077F]|[\u0590-\u05FF]|[\uFE70-\uFEFF]/gm,
+ltr:/[\u0041-\u007A]|[\u00C0-\u02AF]|[\u0388-\u058F]/gm},textDirectionChanges:{rtl:/[\u200E]|/gm,ltr:/[\u200F]|/gm},scripts:{basicLatin:{regularExpression:/[\u0041-\u007F]/g,languages:["ceb","en","eu","ha","haw","id","la","nr","nso","so","ss","st","sw","tlh","tn","ts","xh","zu","af","az","ca","cs","cy","da","de","es","et","fi","fr","hr","hu","is","it","lt","lv","nl","no","pl","pt","ro","sk","sl","sq","sv","tl","tr","ve","vi"]},arabic:{regularExpression:/[\u0600-\u06FF]/g,languages:["ar","fa","ps","ur"]},cryllic:{regularExpression:/[\u0400-\u04FF]|[\u0500-\u052F]/g,languages:["bg","kk","ky","mk","mn","ru","sr","uk","uz"]}},scriptSingletons:{bn:/[\u0980-\u09FF]/g,bo:/[\u0F00-\u0FFF]/g,el:/[\u0370-\u03FF]/g,gu:/[\u0A80-\u0AFF]/g,he:/[\u0590-\u05FF]/g,hy:/[\u0530-\u058F]/g,ja:/[\u3040-\u309F]|[\u30A0-\u30FF]/g,ka:/[\u10A0-\u10FF]/g,km:/[\u1780-\u17FF]|[\u19E0-\u19FF]/g,kn:/[\u0C80-\u0CFF]/g,ko:/[\u1100-\u11FF]|[\u3130-\u318F]|[\uAC00-\uD7AF]/g,lo:/[\u0E80-\u0EFF]/g,ml:/[\u0D00-\u0D7F]/g,
+mn:/[\u1800-\u18AF]/g,or:/[\u0B00-\u0B7F]/g,pa:/[\u0A00-\u0A7F]/g,si:/[\u0D80-\u0DFF]/g,ta:/[\u0B80-\u0BFF]/g,te:/[\u0C00-\u0C7F]/g,th:/[\u0E00-\u0E7F]/g,zh:/[\u3100-\u312F]|[\u2F00-\u2FDF]/g},getDocumentLanguage:function(t,n){var i=navigator.language||navigator.userLanguage;return"undefined"!=typeof e.options.language&&(i=e.options.language),t.parents("[lang]").length&&(i=t.parents("[lang]:first").attr("lang")),"undefined"!=typeof t.attr("lang")&&(i=t.attr("lang")),i=i.toLowerCase().trim(),n?i.split("-")[0]:i}},e.components.placeholder=function(e,n,i,s){var a=function(e,s){n.add(i({element:e,expected:t(e).closest(".quail-test").data("expected"),status:s}))};n.get("$scope").find(s.selector).each(function(){var n="";if("none"===t(this).css("display")&&!t(this).is("title"))return void a(this,"inapplicable");if("undefined"!=typeof s.attribute){if(("undefined"==typeof t(this).attr(s.attribute)||"tabindex"===s.attribute&&t(this).attr(s.attribute)<=0)&&!s.content)return void a(this,"failed");t(this).attr(s.attribute)&&"undefined"!==t(this).attr(s.attribute)&&(n+=t(this).attr(s.attribute));
+}if(("undefined"==typeof s.attribute||!s.attribute||s.content)&&(n+=t(this).text(),t(this).find("img[alt]").each(function(){n+=t(this).attr("alt")})),"string"==typeof n&&n.length>0){n=e.cleanString(n);var i=/^([0-9]*)(k|kb|mb|k bytes|k byte)$/g,r=i.exec(n.toLowerCase());r&&r[0].length?a(this,"failed"):s.empty&&e.isUnreadable(n)?a(this,"failed"):e.strings.placeholders.indexOf(n)>-1?a(this,"failed"):a(this,"passed")}else s.empty&&"number"!=typeof n&&a(this,"failed")})},e.components.resolveExpectation=function(e,n){var i,s=t(e).closest(".quail-test"),a=s.data("expected");n||(i=s.data("expected"));var r="string"==typeof a&&a.split("|");if(n&&0===r.length&&a.indexOf(":")>-1&&(r=[a]),r.length>0&&1===e.nodeType)for(var o,c,u=0,l=r.length;l>u;++u)if(o=r[u].split(":"),n){if(o[0]===n){if(!o[1]||"ignore"===o[1])return;i=o[1]}}else if(c=t(o[0],s),1===c.length&&e===c.get(0)){if(!o[1]||"ignore"===o[1])return;i=o[1]}return i},e.components.selector=function(e,n,i,s){this.get("$scope").each(function(){var i=t(this),a=t(this).find(s.selector);
+a.length?a.each(function(){var i,a=t(this);i=s.test&&!a.is(s.test)?"passed":"failed",n.add(e.lib.Case({element:this,expected:a.closest(".quail-test").data("expected"),status:i}))}):n.add(e.lib.Case({element:void 0,expected:i.data("expected")||i.find("[data-expected]").data("expected"),status:s.test?"inapplicable":"passed"}))})},e.statistics={setDecimal:function(t,e){var n=Math.pow(10,e||0);return e?Math.round(n*t)/n:t},average:function(t,n){for(var i=t.length,s=0;i--;)s+=t[i];return e.statistics.setDecimal(s/t.length,n)},variance:function(t,n){for(var i=e.statistics.average(t,n),s=t.length,a=0;s--;)a+=Math.pow(t[s]-i,2);return a/=t.length,e.statistics.setDecimal(a,n)},standardDeviation:function(t,n){var i=Math.sqrt(e.statistics.variance(t,n));return e.statistics.setDecimal(i,n)}},e.components.textStatistics={cleanText:function(t){return t.replace(/[,:;()\-]/," ").replace(/[\.!?]/,".").replace(/[ ]*(\n|\r\n|\r)[ ]*/," ").replace(/([\.])[\. ]+/,"$1").replace(/[ ]*([\.])/,"$1").replace(/[ ]+/," ").toLowerCase();
+},sentenceCount:function(t){return t.split(".").length+1},wordCount:function(t){return t.split(" ").length+1},averageWordsPerSentence:function(t){return this.wordCount(t)/this.sentenceCount(t)},averageSyllablesPerWord:function(e){var n=this,i=0,s=n.wordCount(e);return s?(t.each(e.split(" "),function(t,e){i+=n.syllableCount(e)}),i/s):0},syllableCount:function(t){var e=t.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/,"").match(/[aeiouy]{1,2}/g);return e&&0!==e.length?e.length:1}},e.components.video={isVideo:function(e){var n=!1;return t.each(this.providers,function(){e.is(this.selector)&&this.isVideo(e)&&(n=!0)}),n},findVideos:function(e,n){t.each(this.providers,function(i,s){e.find(this.selector).each(function(){var e=t(this);s.isVideo(e)&&s.hasCaptions(e,n)})})},providers:{youTube:{selector:"a, iframe",apiUrl:"http://gdata.youtube.com/feeds/api/videos/?q=%video&caption&v=2&alt=json",isVideo:function(t){return this.getVideoId(t)!==!1?!0:!1},getVideoId:function(t){var e=t.is("iframe")?"src":"href",n=/^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&\?]*).*/,i=t.attr(e).match(n);
+return i&&11===i[7].length?i[7]:!1},hasCaptions:function(e,n){var i=this.getVideoId(e);t.ajax({url:this.apiUrl.replace("%video",i),async:!1,dataType:"json",success:function(t){n(e,t.feed.openSearch$totalResults.$t>0)}})}},flash:{selector:"object",isVideo:function(e){var n=!1;return 0===e.find("param").length?!1:(e.find("param[name=flashvars]").each(function(){t(this).attr("value").search(/\.(flv|mp4)/i)>-1&&(n=!0)}),n)},hasCaptions:function(e,n){var i=!1;e.find("param[name=flashvars]").each(function(){(t(this).attr("value").search("captions")>-1&&t(this).attr("value").search(".srt")>-1||t(this).attr("value").search("captions.pluginmode")>-1)&&(i=!0)}),n(e,i)}},videoElement:{selector:"video",isVideo:function(t){return t.is("video")},hasCaptions:function(n,i){var s=n.find("track[kind=subtitles], track[kind=captions]");if(!s.length)return void i(n,!1);var a=e.components.language.getDocumentLanguage(n,!0);n.parents("[lang]").length&&(a=n.parents("[lang]").first().attr("lang").split("-")[0]);
+var r=!1;return s.each(function(){if(!t(this).attr("srclang")||t(this).attr("srclang").toLowerCase()===a){r=!0;try{var e=t.ajax({url:t(this).attr("src"),type:"HEAD",async:!1,error:function(){}});404===e.status&&(r=!1)}catch(n){}}}),r?void i(n,!0):void i(n,!1)}}}},e.strings.colors={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"00ffff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000000",blanchedalmond:"ffebcd",blue:"0000ff",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"00ffff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",
+deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"ff00ff",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgrey:"d3d3d3",lightgreen:"90ee90",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"778899",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"00ff00",limegreen:"32cd32",linen:"faf0e6",magenta:"ff00ff",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370d8",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",
+mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"d87093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",red:"ff0000",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"ffffff",whitesmoke:"f5f5f5",yellow:"ffff00",yellowgreen:"9acd32"},e.strings.languageCodes=["bh","bi","nb","bs","br","bg","my","es","ca","km","ch","ce","ny","ny","zh","za","cu","cu","cv","kw","co","cr","hr","cs","da","dv","dv","nl","dz","en","eo","et","ee","fo","fj","fi","nl","fr","ff","gd","gl","lg","ka","de","ki","el","kl","gn","gu","ht","ht","ha","he","hz","hi","ho","hu","is","io","ig","id","ia","ie","iu","ik","ga","it","ja","jv","kl","kn","kr","ks","kk","ki","rw","ky","kv","kg","ko","kj","ku","kj","ky","lo","la","lv","lb","li","li","li","ln","lt","lu","lb","mk","mg","ms","ml","dv","mt","gv","mi","mr","mh","ro","ro","mn","na","nv","nv","nd","nr","ng","ne","nd","se","no","nb","nn","ii","ny","nn","ie","oc","oj","cu","cu","cu","or","om","os","os","pi","pa","ps","fa","pl","pt","pa","ps","qu","ro","rm","rn","ru","sm","sg","sa","sc","gd","sr","sn","ii","sd","si","si","sk","sl","so","st","nr","es","su","sw","ss","sv","tl","ty","tg","ta","tt","te","th","bo","ti","to","ts","tn","tr","tk","tw","ug","uk","ur","ug","uz","ca","ve","vi","vo","wa","cy","fy","wo","xh","yi","yo","za","zu"],
+e.strings.newWindow=[/new (browser )?(window|frame)/,/popup (window|frame)/],e.strings.placeholders=["title","untitled","untitled document","this is the title","the title","content"," ","new page","new","nbsp"," ","spacer","image","img","photo","frame","frame title","iframe","iframe title","legend"],e.strings.redundant={inputImage:["submit","button"],link:["link to","link","go to","click here","link","click","more"],required:["*"]},e.strings.siteMap=["site map","map","sitemap"],e.strings.skipContent=[/(jump|skip) (.*) (content|main|post)/i],e.strings.suspiciousLinks=["click here","click","more","here","read more","download","add","delete","clone","order","view","read","clic aquí","clic","haga clic","más","aquí","image"],e.strings.symbols=["|","*",/\*/g,"
*","•","•","♦","›","»","‣","▶",".","◦","✓","◽","•","—","◾"],e.KINGStrongList=function(e,n,i){n.get("$scope").find("strong").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")
+});n.add(e),e.set({status:t(this).parent().is("li")?"passed":"failed"})})},e.KINGUseCurrencyAsSymbol=function(e,n,i){function s(s,a){var r=["dollar","euro","pound","franc","krona","rupee","ruble","dinar"],o=new RegExp("\\d{1,}\\s*("+r.join("|")+")\\w*\\b|("+r.join("|")+")\\w*\\b\\s*\\d{1,}","ig"),c=e.getTextContents(t(a)),u=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(u),u.set({status:o.test(c)?"failed":"passed"})}n.get("$scope").find("p").each(s)},e.KINGUseLongDateFormat=function(e,n,i){function s(e,s){var a,r=/\d{1,2}([.\/-])\d{1,2}\1\d{2,4}/g,o=s.childNodes,c=!1,u=[],l=0;for(a=o.length;a>l;l++)o[l].nodeType===Node.TEXT_NODE&&u.push(o[l]);for(l=0;l0,o=i.find("a");o.each(s?a:r)}function a(e,s){var a=t(s),r=s.getAttribute("href"),o=a.find("+ a");if(o.length){var c=o[0].getAttribute("href"),u="passed",l=i({element:s,expected:a.closest(".quail-test").data("expected")});r===c&&(u="failed"),n.add(l),l.set({status:u})}}function r(e,s){var a=i({element:s});n.add(a),a.set({status:"inapplicable",expected:t(s).closest(".quail-test").data("expected")})}n.get("$scope").each(s)},e.aImgAltNotRepetitive=function(e,n,i){n.get("$scope").find("a img[alt]").each(function(){
+var s=n.add(i({element:this})),a=t(this).closest(".quail-test").data("expected");s.set(e.cleanString(t(this).attr("alt"))===e.cleanString(t(this).parent("a").text())?{expected:a,status:"failed"}:{expected:a,status:"passed"})})},e.aInPHasADistinctStyle=function(e,n,i){function s(t){return t.outerWidth()-t.innerWidth()>0||t.outerHeight()-t.innerHeight()>0}function a(e,n){var i=!1,a=["font-weight","font-style"],r=e.css("text-decoration");return"none"!==r&&r!==n.css("text-decoration")&&(i=!0),"rgba(0, 0, 0, 0)"!==e.css("background-color")&&a.push("background"),t.each(a,function(t,s){i||e.css(s)===n.css(s)||(i=!0)}),i||s(e)}function r(t){var e="block"===t.css("display"),n=t.css("position"),i="relative"!==n&&"static"!==n;return e||i}var o=/^([\s|-]|>|<|\\|\/|&(gt|lt);)*$/i;n.get("$scope").each(function(){var e=t(this),s=e.find("p a[href]:visible");s.each(function(){var e=t(this),s=e.closest("p"),c=e.parent(),u=i({element:this,expected:e.closest(".quail-test").data("expected")});n.add(u);var l=e.text().trim(),d=s.clone().find("a[href]").remove().end().text();
+""===l||d.match(o)?u.set("status","inapplicable"):e.css("color")===s.css("color")?u.set("status","passed"):a(e,s)?u.set("status","passed"):r(e)?u.set("status","passed"):e.find("img").length>0?u.set("status","passed"):c.text().trim()===l&&a(c,s)?u.set("status","passed"):u.set("status","failed")})})},e.aLinkTextDoesNotBeginWithRedundantWord=function(e,n,i){n.get("$scope").find("a").each(function(){var s=t(this),a="";t(this).find("img[alt]").length&&(a+=t(this).find("img[alt]:first").attr("alt")),a+=t(this).text(),a=a.toLowerCase();var r;t.each(e.strings.redundant.link,function(t,e){a.search(e)>-1&&(r=n.add(i({element:this,expected:s.closest(".quail-test").data("expected"),status:"failed"})))}),r||n.add(i({element:this,expected:s.closest(".quail-test").data("expected"),status:"passed"}))})},e.aLinkWithNonText=function(e,n,i){n.get("$scope").find("a").each(function(){var s=i({element:this,expected:t(this).closest(".quail-test").data("expected")});if(n.add(s),!t(this).is("a:has(img, object, embed)[href]"))return void s.set({
+status:"inapplicable"});if(!e.isUnreadable(t(this).text()))return void s.set({status:"passed"});var a=0;t(this).find("img, object, embed").each(function(){(t(this).is("img")&&e.isUnreadable(t(this).attr("alt"))||!t(this).is("img")&&e.isUnreadable(t(this).attr("title")))&&a++}),s.set(t(this).find("img, object, embed").length===a?{status:"failed"}:{status:"passed"})})},e.aLinksAreSeparatedByPrintableCharacters=function(e,n,i){n.get("$scope").find("a").each(function(){var s=n.add(i({element:this})),a=t(this).closest(".quail-test").data("expected");t(this).next("a").length&&s.set(e.isUnreadable(t(this).get(0).nextSibling.wholeText)?{expected:a,status:"failed"}:{expected:a,status:"passed"})})},e.aLinksDontOpenNewWindow=function(e,n,i){n.get("$scope").find("a").not("[target=_new], [target=_blank]").each(function(){n.add(i({element:this,expected:t(this).closest(".quail-test").data("expected"),status:"passed"}))}),n.get("$scope").find("a[target=_new], a[target=_blank]").each(function(){var s=t(this),a=!1,r=0,o=s.text()+" "+s.attr("title"),c="";
+do c=e.strings.newWindow[r],o.search(c)>-1&&(a=!0),++r;while(!a&&r-1?{status:"failed"}:{status:"passed"})})},e.animatedGifMayBePresent=function(e,n,i){function s(t,e,n){if("gif"!==e)return void n(!1);var i=new XMLHttpRequest;i.open("GET",t,!0),i.responseType="arraybuffer",i.addEventListener("load",function(){var t=new Uint8Array(i.response),e=0;if(71!==t[0]||73!==t[1]||70!==t[2]||56!==t[3])return void n(!1);for(var s=0;s1)return void n(!0);n(!1)}),i.send()}n.get("$scope").find("img").each(function(){
+var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e);var a=t(this).attr("src"),r=t(this).attr("src").split(".").pop().toLowerCase();return"gif"!==r?void e.set({status:"inapplicable"}):void s(a,r,function(t){return t?void e.set({status:"cantTell"}):void e.set({status:"inapplicable"})})})},e.appletContainsTextEquivalent=function(e,n,i){n.get("$scope").find('applet[alt=""], applet:not(applet[alt])').each(function(){var s=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(s),s.set(e.isUnreadable(t(this).text())?{status:"failed"}:{status:"passed"})})},e.ariaOrphanedContent=function(e,n,i){var s=n.get("$scope");s.each(function(){var e=t(this),s=!!e.attr("role"),a=!!e.find("[role]").length;if(!s&&!a)return void n.add(i({expected:e.data("expected"),status:"inapplicable"}));var r=e.find("*:not(*[role] *, *[role], script, meta, link)");r.length?r.each(function(){n.add(i({element:this,expected:t(this).closest(".quail-test").data("expected"),
+status:"failed"}))}):n.add(i({expected:e.data("expected"),status:"passed"}))})},e.audioMayBePresent=function(e,n,i){var s=["mp3","m4p","ogg","oga","opus","wav","wma","wv"];n.get("$scope").each(function(){var e=t(this),a=!1;e.find("object, audio").each(function(){a=!0,n.add(i({element:this,expected:t(this).closest(".quail-test").data("expected"),status:"cantTell"}))}),e.find("a[href]").each(function(){var e=t(this),r=e.attr("href").split(".").pop();-1!==t.inArray(r,s)&&(a=!0,n.add(i({element:this,expected:e.closest(".quail-test").data("expected"),status:"cantTell"})))}),a||n.add(i({element:this,status:"inapplicable",expected:t(this).closest(".quail-test").data("expected")}))})},e.blockquoteUseForQuotations=function(e,n,i){n.get("$scope").find("p").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});return n.add(e),t(this).parents("blockquote").length>0?void e.set({status:"inapplicable"}):void e.set(t(this).text().substr(0,1).search(/'|"|«|“|「/)>-1&&t(this).text().substr(-1,1).search(/'|"|»|„|」/)>-1?{
+status:"failed"}:{status:"passed"})})},e.closingTagsAreUsed=function(e,n,i){e.components.htmlSource.getHtml(function(s,a){e.components.htmlSource.traverse(a,function(s){if("tag"===s.type&&t.isArray(s.selector)){var a;a=/#/.test(s.selector.slice(-1)[0])?s.selector.slice(-1)[0]:s.selector.join(" > ");var r=t(a,n.get("$scope")).get(0);r||(r=s.raw||a),n.add(i("undefined"!=typeof s.closingTag||s.closingTag||-1!==e.selfClosingTags.indexOf(s.name.toLowerCase())?{element:r,expected:"object"==typeof r&&1===r.nodeType&&t(r).closest(".quail-test").data("expected")||null,status:"passed"}:{element:r,expected:"object"==typeof r&&1===r.nodeType&&t(r).closest(".quail-test").data("expected")||null,status:"failed"}))}})})},e.colorBackgroundGradientContrast=function(e,n,i,s){function a(t,e,n,i,s){var a,u,l,d=r.getBackgroundGradient(i);if(d){for(var h=0;hh;h++){
+var p=r.testElmBackground(n.algorithm,i,"#"+u.colourAt(h));p||(o(t,e,s,"failed",c,"The background gradient makes the text unreadable"),a=!0)}a||o(t,e,s,"passed",c,"The background gradient does not affect readability")}}var r=e.components.color.colors,o=e.components.color.buildCase,c="colorBackgroundGradientContrast";n.get("$scope").each(function(){for(var r=document.evaluate("descendant::text()[normalize-space()]",this,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null),c=[],u=r.iterateNext();u;)e.components.color.textShouldBeTested(u)&&c.push(u.parentNode),u=r.iterateNext();0===c.length&&o(n,i,null,"inapplicable","","There is no text to evaluate"),c.forEach(function(e){a(n,i,s,t(e),e)})})},e.colorBackgroundImageContrast=function(e,n,i,s){function a(t,e,n,i,s){var a=r.getBackgroundImage(i);if(a){var u=document.createElement("img");u.crossOrigin="Anonymous",u.onload=function(){var a=r.getAverageRGB(u),l=r.testElmBackground(n.algorithm,i,a);l?o(t,e,s,"passed",c,"The element's background image does not affect readability"):o(t,e,s,"failed",c,"The element's background image makes the text unreadable");
+},u.onerror=u.onabort=function(){o(t,e,s,"cantTell",c,"The element's background image could not be loaded ("+a+")")},u.src=a}}var r=e.components.color.colors,o=e.components.color.buildCase,c="colorBackgroundImageContrast";n.get("$scope").each(function(){for(var r=document.evaluate("descendant::text()[normalize-space()]",this,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null),c=[],u=r.iterateNext();u;)e.components.color.textShouldBeTested(u)&&c.push(u.parentNode),u=r.iterateNext();0===c.length&&o(n,i,null,"inapplicable","","There is no text to evaluate"),c.forEach(function(e){a(n,i,s,t(e),e)})})},e.colorElementBehindBackgroundGradientContrast=function(e,n,i,s){function a(t,e,n,i,s){var a,u;if(i.is("option")||(a=r.getBehindElementBackgroundGradient(i)),a){for(var l=0;ll;l++)u=!r.testElmBackground(n.algorithm,i,"#"+d.colourAt(l));
+u?o(t,e,s,"failed",c,"The background gradient of the element behind this element makes the text unreadable"):o(t,e,s,"passed",c,"The background gradient of the element behind this element does not affect readability")}}var r=e.components.color.colors,o=e.components.color.buildCase,c="colorElementBehindBackgroundGradientContrast";n.get("$scope").each(function(){for(var r=document.evaluate("descendant::text()[normalize-space()]",this,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null),c=[],u=r.iterateNext();u;)e.components.color.textShouldBeTested(u)&&c.push(u.parentNode),u=r.iterateNext();0===c.length&&o(n,i,null,"inapplicable","","There is no text to evaluate"),c.forEach(function(e){a(n,i,s,t(e),e)})})},e.colorElementBehindBackgroundImageContrast=function(e,n,i,s){function a(t,e,n,i,s){var a;if(i.is("option")||(a=r.getBehindElementBackgroundImage(i)),a){var u=document.createElement("img");u.crossOrigin="Anonymous",u.onload=function(){var a=r.getAverageRGB(u),l=r.testElmBackground(n.algorithm,i,a);
+l?o(t,e,s,"passed",c,"The background image of the element behind this element does not affect readability"):o(t,e,s,"failed",c,"The background image of the element behind this element makes the text unreadable")},u.onerror=u.onabort=function(){o(t,e,s,"cantTell",c,"The background image of the element behind this element could not be loaded ("+a+")")},u.src=a}}var r=e.components.color.colors,o=e.components.color.buildCase,c="colorElementBehindBackgroundImageContrast";n.get("$scope").each(function(){for(var r=document.evaluate("descendant::text()[normalize-space()]",this,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null),c=[],u=r.iterateNext();u;)e.components.color.textShouldBeTested(u)&&c.push(u.parentNode),u=r.iterateNext();0===c.length&&o(n,i,null,"inapplicable","","There is no text to evaluate"),c.forEach(function(e){a(n,i,s,t(e),e)})})},e.colorElementBehindContrast=function(e,n,i,s){function a(t,e,n,i,s){var a;if(i.is("option")||(a=r.getBehindElementBackgroundColor(i)),a){var u=r.testElmBackground(n.algorithm,i,a);
+u?o(t,e,s,"passed",c,"The element behind this element does not affect readability"):o(t,e,s,"failed",c,"The element behind this element makes the text unreadable")}}var r=e.components.color.colors,o=e.components.color.buildCase,c="colorElementBehindContrast";n.get("$scope").each(function(){for(var r=document.evaluate("descendant::text()[normalize-space()]",this,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null),c=[],u=r.iterateNext();u;)e.components.color.textShouldBeTested(u)&&c.push(u.parentNode),u=r.iterateNext();0===c.length&&o(n,i,null,"inapplicable","","There is no text to evaluate"),c.forEach(function(e){a(n,i,s,t(e),e)})})},e.colorFontContrast=function(e,n,i,s){function a(t,e,n,i,s){r.testElmContrast(n.algorithm,i)?o(t,e,s,"passed",c,"The font contrast of the text is sufficient for readability"):o(t,e,s,"failed",c,"The font contrast of the text impairs readability")}var r=e.components.color.colors,o=e.components.color.buildCase,c="colorFontContrast";n.get("$scope").each(function(){
+for(var r=document.evaluate("descendant::text()[normalize-space()]",this,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null),c=[],u=r.iterateNext();u;)e.components.color.textShouldBeTested(u)&&c.push(u.parentNode),u=r.iterateNext();0===c.length&&o(n,i,null,"inapplicable","","There is no text to evaluate"),c.forEach(function(e){a(n,i,s,t(e),e)})})},e.contentPositioningShouldNotChangeMeaning=function(e,n,i){var s=["top","left","right","bottom"],a={},r=!1;n.get("$scope").find("*:has(*:quailCss(position=absolute))").each(function(){a={top:{},left:{},right:{},bottom:{}},r=!1;var e=t(this);e.find("h1, h2, h3, h4, h5, h6, p, blockquote, ol, li, ul, dd, dt").filter(":quailCss(position=absolute)").each(function(){for(var e=0;e2&&!r&&(r=!0,n.add(i({element:e.get(0),
+expected:e.closest(".quail-test").data("expected"),status:"failed"})))})})})},e.definitionListsAreUsed=function(e,n,i){n.get("$scope").find("dl").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e),e.set({status:"inapplicable"})}),n.get("$scope").find("p, li").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e);var s=t(this);t(this).find("span, strong, em, b, i").each(function(){if(t(this).text().length<50&&0===s.text().search(t(this).text())){if(t(this).is("span")&&t(this).css("font-weight")===s.css("font-weight")&&t(this).css("font-style")===s.css("font-style"))return void e.set({status:"passed"});e.set({status:"failed"})}})})},e.doNotUseGraphicalSymbolToConveyInformation=function(e,n,i){n.get("$scope").find(e.textSelector+":not(abbr, acronym)").each(function(){var s="✓",a="?xo[]()+-!*xX",r=t(this).text(),o=r.replace(/[\W\s]+/g,"");0===o.length?-1===s.indexOf(r)&&n.add(i({element:this,
+expected:function(t){return e.components.resolveExpectation(t)}(this),status:"failed"})):n.add(i(1===r.length&&a.indexOf(r)>=0?{element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"failed"}:{element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"passed"}))}),n.get("$scope").find(e.textSelector).filter("abbr, acronym").each(function(){n.add(i({element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"inapplicable"}))})},e.doctypeProvided=function(e,n,i){var s=n.get("$scope").get(0);n.add(i(0!==t(s.doctype).length||document.doctype?{element:s,expected:"pass",status:"passed"}:{element:s,expected:"fail",status:"failed"}))},e.documentAbbrIsUsed=function(t,e,n){t.components.acronym(t,e,n,"abbr")},e.documentAcronymsHaveElement=function(t,e,n){t.components.acronym(t,e,n,"acronym")},e.documentIDsMustBeUnique=function(e,n,i){n.get("$scope").each(function(){0===t(this).children().length&&n.add(i({
+element:this,status:"inapplicable",expected:t(this).closest(".quail-test").data("expected")}))}),n.get("$scope").find(":not([id])").each(function(){n.add(i({element:this,status:"inapplicable",expected:t(this).closest(".quail-test").data("expected")}))}),n.get("$scope").each(function(){var s={};t(this).find("[id]").each(function(){var a=i({element:this,expected:function(t){return e.components.resolveExpectation(t)}(this)});n.add(a),"undefined"==typeof s[t(this).attr("id")]&&0===Object.keys(s).length?(a.set({status:"inapplicable"}),s[t(this).attr("id")]=t(this).attr("id")):"undefined"==typeof s[t(this).attr("id")]?(a.set({status:"passed"}),s[t(this).attr("id")]=t(this).attr("id")):a.set({status:"failed"})})})},e.documentIsWrittenClearly=function(e,n,i){n.get("$scope").find(e.textSelector).each(function(){var s=e.components.textStatistics.cleanText(t(this).text()),a=i({element:this,expected:t(this).closest(".quail-test").data("expected")});return n.add(a),e.isUnreadable(s)?void a.set({status:"inapplicable"
+}):void a.set(Math.round(206.835-1.015*e.components.textStatistics.averageWordsPerSentence(s)-84.6*e.components.textStatistics.averageSyllablesPerWord(s))<60?{status:"failed"}:{status:"passed"})})},e.documentLangIsISO639Standard=function(e,n,i){var s=n.get("$scope").is("html")?n.get("$scope"):n.get("$scope").find("html").first(),a=i({element:s[0],expected:s.closest(".quail-test").length?s.closest(".quail-test").data("expected"):s.data("expected")}),r=s.attr("lang"),o=!1;n.add(a),s.is("html")&&"undefined"!=typeof r?(t.each(e.strings.languageCodes,function(t,e){o||0!==r.indexOf(e)||(o=!0)}),a.set(o?null===r.match(/^[a-z]{2}(-[A-Z]{2})?$/)?{status:"failed"}:{status:"passed"}:{status:"failed"})):a.set({status:"inapplicable"})},e.documentStrictDocType=function(t,e,n){e.add(n("undefined"!=typeof document.doctype&&document.doctype&&-1!==document.doctype.systemId.search("strict")?{element:document,expected:e.get("$scope").data("expected"),status:"passed"}:{element:document,expected:e.get("$scope").data("expected"),
+status:"failed"}))},e.documentTitleIsShort=function(t,e,n){var i=e.get("$scope").find("head title:first"),s=n({element:i,expected:i.closest(".quail-test").data("expected")});return e.add(s),i.length?void s.set({status:i.text().length>150?"failed":"passed"}):void s.set({element:e.get("$scope"),status:"inapplicable"})},e.documentValidatesToDocType=function(){"undefined"==typeof document.doctype},e.documentVisualListsAreMarkedUp=function(e,n,i){var s=["♦","›","»","‣","▶","◦","✓","◽","•","—","◾","-\\D","\\\\","\\*(?!\\*)","\\.\\s","x\\s","•","•",">","[0-9]+\\.","\\(?[0-9]+\\)","[\\u25A0-\\u25FF]","[IVX]{1,5}\\.\\s"],a=RegExp("(^|
]*>)[\\s]*("+s.join("|")+")","gi");n.get("$scope").find(e.textSelector).each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e);var s=t(this).html().match(a);e.set({status:s&&s.length>2?"failed":"passed"})})},e.elementAttributesAreValid=function(e,n,i){e.components.htmlSource.getHtml(function(s,a){
+a&&e.components.htmlSource.traverse(a,function(e){if("undefined"!=typeof e.raw&&t.isArray(e.selector)){var s,a=!1;s=/#/.test(e.selector.slice(-1)[0])?e.selector.slice(-1)[0]:e.selector.join(" > ");var r=t(s,n.get("$scope")).get(0);r||(r=e.raw||s);var o=e.raw.match(/\'|\"/g);o&&o.length%2!==0&&(n.add(i({element:r,expected:"object"==typeof r&&1===r.nodeType&&t(r).closest(".quail-test").data("expected")||null,status:"failed"})),a=!0),e.raw.search(/([a-z]*)=(\'|\")([a-z\.]*)(\'|\")[a-z]/i)>-1&&(n.add(i({element:r,expected:"object"==typeof r&&1===r.nodeType&&t(r).closest(".quail-test").data("expected")||null,status:"failed"})),a=!0);var c=e.raw.split("=");c.shift(),t.each(c,function(){-1===this.search(/\'|\"/)&&this.search(/\s/i)>-1&&(n.add(i({element:r,expected:"object"==typeof r&&1===r.nodeType&&t(r).closest(".quail-test").data("expected")||null,status:"failed"})),a=!0)}),a||n.add(i({element:r,expected:"object"==typeof r&&1===r.nodeType&&t(r).closest(".quail-test").data("expected")||null,status:"passed"
+}))}})})},e.elementsDoNotHaveDuplicateAttributes=function(e,n,i){e.components.htmlSource.getHtml(function(s,a){a&&e.components.htmlSource.traverse(a,function(e){if("tag"===e.type&&t.isArray(e.selector)){var s;s=/#/.test(e.selector.slice(-1)[0])?e.selector.slice(-1)[0]:e.selector.join(" > ");var a=t(s,n.get("$scope")).get(0);if(a||(a=e.raw||s),"undefined"!=typeof e.attributes){var r=[];t.each(e.attributes,function(t,e){e.length>1&&r.push(e)}),n.add(i(r.length?{element:a,expected:"object"==typeof a&&1===a.nodeType&&t(a).closest(".quail-test").data("expected")||null,info:r,status:"failed"}:{element:a,expected:"object"==typeof a&&1===a.nodeType&&t(a).closest(".quail-test").data("expected")||null,info:r,status:"passed"}))}}})})},e.embedHasAssociatedNoEmbed=function(e,n,i){n.get("$scope").find("embed").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e),e.set({status:t(this).find("noembed").length||t(this).next().is("noembed")?"passed":"failed"
+})})},e.emoticonsExcessiveUse=function(e,n,i){n.get("$scope").find(e.textSelector).each(function(){var s=0,a=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(a),t.each(t(this).text().split(" "),function(t,n){n.search(e.emoticonRegex)>-1&&s++}),a.set(0===s?{status:"inapplicable"}:{status:s>4?"failed":"passed"})})},e.emoticonsMissingAbbr=function(e,n,i){n.get("$scope").find(e.textSelector+":not(abbr, acronym)").each(function(){var s=t(this),a=s.clone(),r=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(r),a.find("abbr, acronym").each(function(){t(this).remove()});var o="passed";t.each(a.text().split(" "),function(t,n){n.search(e.emoticonRegex)>-1&&(o="failed")}),r.set({status:o})})},e.focusIndicatorVisible=function(e,n,i){n.get("$scope").find(e.focusElements).each(function(){var s=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(s);var a={borderWidth:t(this).css("border-width"),borderColor:t(this).css("border-color"),
+backgroundColor:t(this).css("background-color"),boxShadow:t(this).css("box-shadow")};if(t(this).focus(),a.backgroundColor.trim()!==t(this).css("background-color").trim())return t(this).blur(),void s.set({status:"passed"});var r=e.components.convertToPx(t(this).css("border-width"));if(r>2&&r!==e.components.convertToPx(a.borderWidth))return t(this).blur(),void s.set({status:"passed"});var o=t(this).css("box-shadow")&&"none"!==t(this).css("box-shadow")?t(this).css("box-shadow").match(/(-?\d+px)|(rgb\(.+\))/g):!1;return o&&t(this).css("box-shadow")!==a.boxShadow&&e.components.convertToPx(o[3])>3?(t(this).blur(),void s.set({status:"passed"})):(t(this).blur(),void s.set({status:"failed"}))})},e.formWithRequiredLabel=function(e,n,i){var s,a=e.strings.redundant,r=!1;a.required[a.required.indexOf("*")]=/\*/g,n.get("$scope").each(function(){var o=t(this);o.find("label").each(function(){var o=t(this).text().toLowerCase(),c=t(this),u=n.add(i({element:this,expected:function(t){return e.components.resolveExpectation(t);
+}(this)}));for(var l in a.required)o.search(l)>=0&&!n.get("$scope").find("#"+c.attr("for")).attr("aria-required")&&u.set({status:"failed"});r=c.css("color")+c.css("font-weight")+c.css("background-color"),s&&r!==s&&u.set({status:"failed"}),s=r,"undefined"==typeof u.get("status")&&u.set({status:"passed"})})})},e.headerTextIsTooLong=function(e,n,i){var s=128;n.get("$scope").find("h1, h2, h3, h4, h5, h6").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected"),status:t(this).text().replace(/^\s+|\s+$/gm,"").length>s?"failed":"passed"});n.add(e)})},e.headersAttrRefersToATableCell=function(e,n,i){n.get("$scope").find("table").each(function(){var e=this,s=i({element:e,expected:t(this).closest(".quail-test").data("expected")});n.add(s);var a=t(e).find("th[headers], td[headers]");return 0===a.length?void s.set({status:"inapplicable"}):void a.each(function(){var n=t(this).attr("headers").split(/\s+/);t.each(n,function(n,i){return""===i||t(e).find("th#"+i+",td#"+i).length>0?void s.set({
+status:"passed"}):void s.set({status:"failed"})})})})},e.headersUseToMarkSections=function(e,n,i){n.get("$scope").find("p").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e);var s=t(this);s.find("strong:first, em:first, i:first, b:first").each(function(){e.set({status:s.text().trim()===t(this).text().trim()?"failed":"passed"})})}),n.get("$scope").find("ul, ol").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e);var s=t(this);if(s.prevAll(":header").length||s.find("li").length!==s.find("li:has(a)").length)return void e.set({status:"passed"});var a=!0;s.find("li:has(a)").each(function(){t(this).text().trim()!==t(this).find("a:first").text().trim()&&(a=!1)}),a&&e.set({status:"failed"})})},e.headersUsedToIndicateMainContent=function(e,n,i){n.get("$scope").each(function(){var s=t(this),a=e.components.content.findContent(s);n.add(i("undefined"==typeof a||0!==a.find(":header").length&&a.find(e.textSelector).first().is(":header")?{
+element:a.get(0),expected:a.closest(".quail-test").data("expected"),status:"passed"}:{element:a.get(0),expected:a.closest(".quail-test").data("expected"),status:"failed"}))})},e.idRefHasCorrespondingId=function(e,n,i){n.get("$scope").find("label[for], *[aria-activedescendant]").each(function(){var e=t(this),s=i({element:this,expected:e.closest(".quail-test").data("expected")});n.add(s);var a=e.attr("for")||e.attr("aria-activedescendant");s.set(0===n.get("$scope").find("#"+a).length?{status:"failed"}:{status:"passed"})})},e.idrefsHasCorrespondingId=function(e,n,i){function s(e){var n=[],i=["headers","aria-controls","aria-describedby","aria-flowto","aria-labelledby","aria-owns"];return t.each(i,function(t,i){var s=e.attr(i);return"undefined"!=typeof s&&s!==!1?void(n=s):void 0}),n.split(/\s+/)}n.get("$scope").each(function(){var e=t(this).find("td[headers], th[headers], [aria-controls], [aria-describedby], [aria-flowto], [aria-labelledby], [aria-owns]");return 0===e.length?void n.add(i({element:this,
+expected:t(this).closest(".quail-test").data("expected"),status:"inapplicable"})):void e.each(function(){var e=this,a=n.add(i({element:this,expected:t(this).closest(".quail-test").data("expected")})),r=s(t(e)),o="passed";t.each(r,function(e,n){return""!==n&&0===t("#"+n).length?void(o="failed"):void 0}),a.set({status:o})})})},e.imgAltIsDifferent=function(e,n,i){n.get("$scope").find("img:not([src])").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected"),status:"inapplicable"});n.add(e)}),n.get("$scope").find("img[alt][src]").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e),e.set(t(this).attr("src")===t(this).attr("alt")||t(this).attr("src").split("/").pop()===t(this).attr("alt")?{status:"failed"}:{status:"passed"})})},e.imgAltIsTooLong=function(e,n,i){n.get("$scope").find("img[alt]").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e),e.set({
+status:t(this).attr("alt").length>100?"failed":"passed"})})},e.imgAltNotEmptyInAnchor=function(e,n,i){n.get("$scope").find("a[href]:has(img)").each(function(){var s=t(this),a=s.text(),r=i({element:this,expected:s.closest(".quail-test").data("expected")});n.add(r),s.find("img[alt]").each(function(){a+=" "+t(this).attr("alt")}),r.set(e.isUnreadable(a)?{status:"failed"}:{status:"passed"})})},e.imgAltTextNotRedundant=function(e,n,i){var s={};n.get("$scope").find("img[alt]").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e),"undefined"==typeof s[t(this).attr("alt")]?s[t(this).attr("alt")]=t(this).attr("src"):e.set(s[t(this).attr("alt")]!==t(this).attr("src")?{status:"failed"}:{status:"passed"})})},e.imgGifNoFlicker=function(e,n,i){n.get("$scope").find('img[src$=".gif"]').each(function(){var e=t(this),s=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(s),t.ajax({url:e.attr("src"),dataType:"text",success:function(t){
+s.set(-1!==t.search("NETSCAPE2.0")?{status:"failed"}:{status:"inapplicable"})}})})},e.imgHasLongDesc=function(e,n,i){n.get("$scope").find("img[longdesc]").each(function(){var s=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(s),s.set(t(this).attr("longdesc")!==t(this).attr("alt")&&e.validURL(t(this).attr("longdesc"))?{status:"passed"}:{status:"failed"})})},e.imgImportantNoSpacerAlt=function(e,n,i){n.get("$scope").find("img[alt]").each(function(){var s=t(this).width()?t(this).width():parseInt(t(this).attr("width"),10),a=t(this).height()?t(this).height():parseInt(t(this).attr("height"),10),r=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(r),r.set(e.isUnreadable(t(this).attr("alt").trim())&&t(this).attr("alt").length>0&&s>50&&a>50?{status:"failed"}:{status:"passed"})})},e.imgMapAreasHaveDuplicateLink=function(e,n,i){var s={};n.get("$scope").find("a").each(function(){s[t(this).attr("href")]=t(this).attr("href")}),n.get("$scope").find("img[usemap]").each(function(){
+var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e);var a=t(this),r=n.get("$scope").find(a.attr("usemap"));r.length||(r=n.get("$scope").find('map[name="'+a.attr("usemap").replace("#","")+'"]')),r.length?r.find("area").each(function(){e.set("undefined"==typeof s[t(this).attr("href")]?{status:"failed"}:{status:"passed"})}):e.set({status:"inapplicable"})})},e.imgNonDecorativeHasAlt=function(e,n,i){n.get("$scope").find("img[alt]").each(function(){var s=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(s),s.set(e.isUnreadable(t(this).attr("alt"))&&(t(this).width()>100||t(this).height()>100)?{status:"failed"}:{status:"passed"})})},e.imgWithMathShouldHaveMathEquivalent=function(e,n,i){n.get("$scope").find("img:not(img:has(math), img:has(tagName))").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e),t(this).parent().find("math").length||e.set({status:"failed"})})},e.inputCheckboxRequiresFieldset=function(e,n,i){
+n.get("$scope").find(":checkbox").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e),e.set(t(this).parents("fieldset").length?{status:"passed"}:{status:"failed"})})},e.inputImageAltIsNotFileName=function(e,n,i){n.get("$scope").find("input[type=image][alt]").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e),e.set(t(this).attr("src")===t(this).attr("alt")?{status:"failed"}:{status:"passed"})})},e.inputImageAltIsShort=function(e,n,i){n.get("$scope").find("input[type=image]").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e),e.set(t(this).attr("alt").length>100?{status:"failed"}:{status:"passed"})})},e.inputImageAltNotRedundant=function(e,n,i){n.get("$scope").find("input[type=image][alt]").each(function(){var s=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(s),s.set(e.strings.redundant.inputImage.indexOf(e.cleanString(t(this).attr("alt")))>-1?{
+status:"failed"}:{status:"passed"})})},e.inputWithoutLabelHasTitle=function(e,n,i){n.get("$scope").each(function(){var s=t(this).find("input, select, textarea");if(0===s.length){var a=i({element:this,expected:t(this).closest(".quail-test").data("expected"),status:"inapplicable"});return void n.add(a)}s.each(function(){var s=i({element:this,expected:t(this).closest(".quail-test").data("expected")});return n.add(s),"none"===t(this).css("display")?void s.set({status:"inapplicable"}):void s.set(n.get("$scope").find("label[for="+t(this).attr("id")+"]").length||t(this).attr("title")&&!e.isUnreadable(t(this).attr("title"))?{status:"passed"}:{status:"failed"})})})},e.labelMustBeUnique=function(e,n,i){var s={};n.get("$scope").find("label[for]").each(function(){"undefined"==typeof s[t(this).attr("for")]&&(s[t(this).attr("for")]=0),s[t(this).attr("for")]++}),n.get("$scope").find("label[for]").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected"),status:1===s[t(this).attr("for")]?"passed":"failed"
+});n.add(e)})},e.labelsAreAssignedToAnInput=function(e,n,i){n.get("$scope").find("label").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e),e.set(t(this).attr("for")&&n.get("$scope").find("#"+t(this).attr("for")).length&&n.get("$scope").find("#"+t(this).attr("for")).is(":input")?{status:"passed"}:{status:"failed"})})},e.languageChangesAreIdentified=function(e,n,i){var s,a,r,o,c,u,l=n.get("$scope"),d=e.components.language.getDocumentLanguage(l,!0),h=function(n,i,s,a){var r,o=n.find("[lang="+i+"]");return 0===o.length?!0:(s=s.length,o.each(function(){r=e.getTextContents(t(this)).match(a),r&&(s-=r.length)}),s>0)},p=function(t){return t.attr("lang")?t.attr("lang").trim().toLowerCase().split("-")[0]:t.parents("[lang]").length?t.parents("[lang]:first").attr("lang").trim().toLowerCase().split("-")[0]:e.components.language.getDocumentLanguage(l,!0)};l.find(e.textSelector).each(function(){c=this,o=t(this),d=p(o),s=e.getTextContents(o),u=!1,
+t.each(e.components.language.scriptSingletons,function(t,a){t!==d&&(r=s.match(a),r&&r.length&&h(o,t,r,a)&&(n.add(i({element:c,expected:function(t){return e.components.resolveExpectation(t)}(c),info:{language:t},status:"failed"})),u=!0))}),t.each(e.components.language.scripts,function(t,l){-1===l.languages.indexOf(d)&&(r=s.match(l.regularExpression),r&&r.length&&h(o,t,r,a)&&(n.add(i({element:c,expected:function(t){return e.components.resolveExpectation(t)}(c),info:{language:t},status:"failed"})),u=!0))}),"undefined"!=typeof guessLanguage&&!o.find("[lang]").length&&o.text().trim().length>400&&guessLanguage.info(o.text(),function(t){t[0]!==d&&(n.add(i({element:c,expected:function(t){return e.components.resolveExpectation(t)}(c),info:{language:t[0]},status:"failed"})),u=!0)}),u||n.add(i({element:c,expected:function(t){return e.components.resolveExpectation(t)}(c),status:"passed"}))})},e.languageDirAttributeIsUsed=function(e,n,i){function s(){var s=t(this),r=s.attr("dir");if(!r){var o=s.closest("[dir]").attr("dir");
+r=o||r}"string"==typeof r&&(r=r.toLowerCase()),"undefined"==typeof a[r]&&(r="ltr");var c="ltr"===r?"rtl":"ltr",u=e.getTextContents(s),l=u.match(a[c]);if(l){var d=l.length;s.find("[dir="+c+"]").each(function(){var t=s[0].textContent.match(a[c]);t&&(d-=t.length)});var h=n.add(i({element:this,expected:function(t){return e.components.resolveExpectation(t)}(this)}));h.set({status:d>0?"failed":"passed"})}}var a=e.components.language.textDirection;n.get("$scope").each(function(){t(this).find(e.textSelector).each(s)})},e.languageDirectionPunctuation=function(e,n,i){var s=n.get("$scope"),a={},r=/[\u2000-\u206F]|[!"#$%&'\(\)\]\[\*+,\-.\/:;<=>?@^_`{|}~]/gi,o=s.attr("dir")?s.attr("dir").toLowerCase():"ltr",c="ltr"===o?"rtl":"ltr",u=e.components.language.textDirection;s.each(function(){var s=t(this);s.find(e.textSelector).each(function(){var s=t(this);o=s.attr("dir")?s.attr("dir").toLowerCase():s.parent("[dir]").first().attr("dir")?s.parent("[dir]").first().attr("dir").toLowerCase():o,"undefined"==typeof u[o]&&(o="ltr"),
+c="ltr"===o?"rtl":"ltr";var l=e.getTextContents(s),d=l.match(u[c]),h=n.add(i({element:this,expected:function(t){return e.components.resolveExpectation(t)}(this)}));if(!d)return void h.set({status:"inapplicable"});for(var p=l.search(u[c]),f=l.lastIndexOf(d.pop());a=r.exec(l);)if(a.index===p-1||a.index===f+1)return void h.set({status:"failed"});h.set({status:"passed"})})})},e.languageUnicodeDirection=function(e,n,i){var s=n.get("$scope"),a=e.components.language.textDirection,r=e.components.language.textDirectionChanges;s.each(function(){var s=t(this);s.find(e.textSelector).each(function(){var s=n.add(i({element:this,expected:function(t){return e.components.resolveExpectation(t)}(this)})),o=t(this),c=o.text().trim(),u=-1!==c.substr(0,1).search(a.ltr)?"rtl":"ltr";s.set(-1===c.search(a[u])?{status:"inapplicable"}:-1!==c.search(r[u])?{status:"passed"}:{status:"failed"})})})},e.linkHasAUniqueContext=function(e,n,i){function s(e){for(var n=t(e),i=n,s=a(n.text());!i.is("body, html")&&-1===u.indexOf(i.css("display"));)i=i.parent();
+var r=i.text().match(/[^\.!\?]+[\.!\?]+/g);null===r&&(r=[i.text()]);for(var o=0;o0)return!1}return r(s(e),s(n))?!1:!0}function c(t){var e=t.text();return t.find("img[alt]").each(function(){e+=" "+this.alt.trim()}),a(e)}var u=["block","flex","list-item","table","table-caption","table-cell"];n.get("$scope").each(function(){var e=t(this),s=e.find("a[href]:visible"),a={};
+if(0===s.length){var r=i({element:this,status:"inapplicable",expected:e.closest(".quail-test").data("expected")});n.add(r)}s.each(function(){var e=c(t(this));"undefined"==typeof a[e]&&(a[e]=[]),a[e].push(this)}),t.each(a,function(e,s){for(;s.length>1;){for(var a=s.pop(),r=!1,c=s.length-1;c>=0;c-=1){var u=s[c];o(a,u)&&(r=!0,s.splice(c,1),n.add(i({element:u,status:"failed",expected:t(u).closest(".quail-test").data("expected")})))}n.add(i({element:a,status:r?"failed":"passed",expected:t(a).closest(".quail-test").data("expected")}))}1===s.length&&n.add(i({element:s[0],status:"passed",expected:t(s[0]).closest(".quail-test").data("expected")}))})})},e.listNotUsedForFormatting=function(e,n,i){n.get("$scope").find("ol, ul").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e),e.set(t(this).find("li").length<2?{status:"failed"}:{status:"passed"})})},e.listOfLinksUseList=function(e,n,i){var s=/(♦|›|»|‣|▶|.|◦|>|✓|◽|•|—|◾|\||\*|•|•)/g;n.get("$scope").find("a").each(function(){
+var a=n.add(i({element:this})),r=t(this).closest(".quail-test").data("expected");if(t(this).next("a").length){var o=t(this).get(0).nextSibling.wholeText.replace(s,"");a.set(!t(this).parent("li").length&&e.isUnreadable(o)?{expected:r,status:"failed"}:{expected:r,status:"passed"})}})},e.newWindowIsOpened=function(e,n,i){var s,a=window.open;window.open=function(t){n.each(function(e,n){var i=n.get("element").href;i.indexOf(t)>-1&&n.set("status","failed")})},n.get("$scope").find("a").each(function(){s=i({element:this,expected:function(t){return e.components.resolveExpectation(t)}(this)}),n.add(s),t(this).trigger("click")}),window.open=a},e.pNotUsedAsHeader=function(e,n,i){n.get("$scope").find("p").each(function(){var s=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(s),t(this).text().search(".")>=1&&s.set({status:"inapplicable"});var a=!1;if(t(this).text().search(".")<1){var r=t(this),o=r.prev("p");t.each(e.suspectPHeaderTags,function(e,n){r.find(n).length&&r.find(n).each(function(){
+t(this).text().trim()===r.text().trim()&&(s.set({status:"failed"}),a=!0)})}),o.length&&t.each(e.suspectPCSSStyles,function(t,e){return r.css(e)!==o.css(e)?(s.set({status:"failed"}),a=!0,!1):void 0}),"bold"===r.css("font-weight")&&(s.set({status:"failed"}),a=!0)}a||s.set({status:"passed"})})},e.paragraphIsWrittenClearly=function(e,n,i){n.get("$scope").find("p").each(function(){var s=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(s);var a=e.components.textStatistics.cleanText(t(this).text());s.set(Math.round(206.835-1.015*e.components.textStatistics.averageWordsPerSentence(a)-84.6*e.components.textStatistics.averageSyllablesPerWord(a))<60?{status:"failed"}:{status:"passed"})})},e.preShouldNotBeUsedForTabularLayout=function(e,n,i){n.get("$scope").find("pre").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e);var s=t(this).text().split(/[\n\r]+/);e.set({status:s.length>1&&t(this).text().search(/\t/)>-1?"failed":"passed"
+})})},e.scriptFocusIndicatorVisible=function(){e.html.find(e.focusElements).each(function(){var n,i,s,a;s=[];for(var r=0,o=document.styleSheets.length;o>r;++r){n=document.styleSheets[r],i=n.cssRules||n.rules;for(var c=i.length-1;c>=0;--c)a=i[c],a.selectorText&&-1!==a.selectorText.indexOf(":focus")&&(s.push({css:a.cssText,index:c,sheet:r}),n.deleteRule(c))}var u={borderWidth:t(this).css("border-width"),borderColor:t(this).css("border-color"),backgroundColor:t(this).css("background-color"),boxShadow:t(this).css("box-shadow"),outlineWidth:t(this).css("outline-width"),outlineColor:t(this).css("outline-color")};t(this).focus();var l=e.components.convertToPx(t(this).css("outline-width"));if(l>2&&l!==e.components.convertToPx(u.outlineWidth))return void t(this).blur();if(u.backgroundColor!==t(this).css("background-color"))return void t(this).blur();var d=e.components.convertToPx(t(this).css("border-width"));if(d>2&&d!==e.components.convertToPx(u.borderWidth))return void t(this).blur();var h=t(this).css("box-shadow")&&"none"!==t(this).css("box-shadow")?t(this).css("box-shadow").match(/(-?\d+px)|(rgb\(.+\))/g):!1;
+if(h&&t(this).css("box-shadow")!==u.boxShadow&&e.components.convertToPx(h[3])>3)return void t(this).blur();t(this).blur();for(var p,f=s.length-1;f>=0;--r)p=s[f],document.styleSheets[p.sheet].insertRule(p.css,p.index);e.testFails("scriptFocusIndicatorVisible",t(this))})},e.selectJumpMenu=function(e,n,i){var s=n.get("$scope");0!==s.find("select").length&&s.find("select").each(function(){n.add(i(0===t(this).parent("form").find(":submit").length&&e.components.hasEventListener(t(this),"change")?{element:this,expected:t(this).closest(".quail-test").data("expected"),status:"failed"}:{element:this,expected:t(this).closest(".quail-test").data("expected"),status:"passed"}))})},e.siteMap=function(e,n,i){var s=!0,a=i({element:n.get("$scope").get(0),expected:n.get("$scope").data("expected")});n.add(a),n.get("$scope").find("a").each(function(){if("passed"!==a.get("status")){var n=t(this).text().toLowerCase();return t.each(e.strings.siteMap,function(t,e){return n.search(e)>-1?void(s=!1):void 0}),s===!1?void a.set({
+status:"failed"}):void(s&&a.set({status:"passed"}))}})},e.skipToContentLinkProvided=function(e,n,i){n.get("$scope").each(function(){var s=t(this),a=!1;s.find('a[href*="#"]').each(function(){if(!a)for(var r=t(this),o=r.attr("href").split("#").pop(),c=s.find("#"+o),u=e.strings.skipContent.slice();!a&&u.length;){var l=u.pop();if(r.text().search(l)>-1&&c.length){if(r.focus(),r.is(":visible")&&"hidden"!==r.css("visibility"))return a=!0,void n.add(i({element:r.get(0),expected:r.closest(".quail-test").data("expected"),status:"passed"}));r.blur()}}}),a||n.add(i({expected:s.data("expected")||s.find("[data-expected]").data("expected"),status:"failed"}))})},e.tabIndexFollowsLogicalOrder=function(e,n,i){n.get("$scope").each(function(){var s=t(this),a=0;s.find("[tabindex]").each(function(){var s=t(this),r=s.attr("tabindex");n.add(i(parseInt(r,10)>=0&&parseInt(r,10)!==a+1?{element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"failed"}:{element:this,expected:function(t){
+return e.components.resolveExpectation(t)}(this),status:"passed"})),a++})})},e.tableAxisHasCorrespondingId=function(e,n,i){n.get("$scope").find("[axis]").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e),e.set(0===t(this).parents("table").first().find("th#"+t(this).attr("axis")).length?{status:"failed"}:{status:"passed"})})},e.tableHeaderLabelMustBeTerse=function(e,n,i){n.get("$scope").find("th, table tr:first td").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e),e.set(t(this).text().length>20&&(!t(this).attr("abbr")||t(this).attr("abbr").length>20)?{status:"failed"}:{status:"passed"})})},e.tableLayoutDataShouldNotHaveTh=function(e,n,i){n.get("$scope").find("table").each(function(){var s=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(s),s.set(0!==t(this).find("th").length?e.isDataTable(t(this))?{status:"passed"}:{status:"failed"}:{status:"inapplicable"
+})})},e.tableLayoutHasNoCaption=function(e,n,i){n.get("$scope").find("table").each(function(){n.add(i(t(this).find("caption").length?e.isDataTable(t(this))?{element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"passed"}:{element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"failed"}:{element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"inapplicable"}))})},e.tableLayoutHasNoSummary=function(e,n,i){n.get("$scope").each(function(){var s=t(this);s.find("table[summary]").each(function(){var s=n.add(i({element:this,expected:t(this).closest(".quail-test").data("expected")}));s.set(e.isDataTable(t(this))||e.isUnreadable(t(this).attr("summary"))?{status:"passed"}:{status:"failed"})})})},e.tableLayoutMakesSenseLinearized=function(e,n,i){n.get("$scope").find("table").each(function(){e.isDataTable(t(this))||n.add(i({element:this,expected:function(t){return e.components.resolveExpectation(t);
+}(this),status:"failed"}))})},e.tableNotUsedForLayout=function(e,n,i){n.get("$scope").find("table").each(function(){n.add(i(e.isDataTable(t(this))?{element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"passed"}:{element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"failed"}))})},e.tableShouldUseHeaderIDs=function(e,n,i){n.get("$scope").find("table").each(function(){var s=t(this),a=!1;e.isDataTable(s)&&(s.find("th").each(function(){a||t(this).attr("id")||(a=!0,n.add(i({element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"failed"})))}),a||s.find("td[header]").each(function(){a||t.each(t(this).attr("header").split(" "),function(t,r){s.find("#"+r).length||(a=!0,n.add(i({element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"failed"})))})}))})},e.tableSummaryDoesNotDuplicateCaption=function(e,n,i){n.get("$scope").find("table[summary]:has(caption)").each(function(){
+n.add(i(e.cleanString(t(this).attr("summary"))===e.cleanString(t(this).find("caption:first").text())?{element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"failed"}:{element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"passed"}))})},e.tableSummaryIsNotTooLong=function(e,n,i){n.get("$scope").find("table[summary]").each(function(){t(this).attr("summary").trim().length>100&&n.add(i({element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"failed"}))})},e.tableUseColGroup=function(e,n,i){n.get("$scope").find("table").each(function(){e.isDataTable(t(this))&&!t(this).find("colgroup").length&&n.add(i({element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"failed"}))})},e.tableUsesAbbreviationForHeader=function(e,n,i){n.get("$scope").find("th:not(th[abbr])").each(function(){t(this).text().length>20&&n.add(i({element:this,expected:function(t){return e.components.resolveExpectation(t);
+}(this),status:"failed"}))})},e.tableUsesScopeForRow=function(e,n,i){n.get("$scope").find("table").each(function(){t(this).find("td:first-child").each(function(){var s=t(this).next("td");("bold"===t(this).css("font-weight")&&"bold"!==s.css("font-weight")||t(this).find("strong").length&&!s.find("strong").length)&&n.add(i({element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"failed"}))}),t(this).find("td:last-child").each(function(){var s=t(this).prev("td");("bold"===t(this).css("font-weight")&&"bold"!==s.css("font-weight")||t(this).find("strong").length&&!s.find("strong").length)&&n.add(i({element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"failed"}))})})},e.tableWithMoreHeadersUseID=function(e,n,i){n.get("$scope").find("table:has(th)").each(function(){var s=t(this),a=0;s.find("tr").each(function(){t(this).find("th").length&&a++,a>1&&!t(this).find("th[id]").length&&n.add(i({element:this,expected:function(t){return e.components.resolveExpectation(t);
+}(this),status:"failed"}))})})},e.tabularDataIsInTable=function(e,n,i){n.get("$scope").find("pre").each(function(){n.add(i(t(this).html().search(" ")>=0?{element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"failed"}:{element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"passed"}))})},e.tagsAreNestedCorrectly=function(t,e,n){t.components.htmlSource.getHtml(function(i){var s=t.components.htmlTagValidator(i),a=n({expected:e.get("$scope").filter(".quail-test").eq(0).data("expected")});e.add(a),a.set(s?{status:"failed",html:s}:{status:"passed"})})},e.textIsNotSmall=function(e,n,i){n.get("$scope").find(e.textSelector).each(function(){var s=t(this).css("font-size");s.search("em")>0&&(s=e.components.convertToPx(s)),s=parseInt(s.replace("px",""),10),n.add(i(10>s?{element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"failed"}:{element:this,expected:function(t){return e.components.resolveExpectation(t);
+}(this),status:"passed"}))})},e.userInputMayBeRequired=function(e,n,i){n.get("$scope").each(function(){var e=i({element:this,expected:t(this).closest(".quail-test").data("expected")});n.add(e);var s=t(this).find("form"),a=0,r=t(this).find("input:not(form input, [type=button],[type=reset],[type=image],[type=submit],[type=hidden])");return s.each(function(){var e=t(this).find("input:not([type=button],[type=reset],[type=image],[type=submit],[type=hidden])");e.length>1&&(a=e.length)}),a>0?void e.set({status:"cantTell"}):r.length>1?void e.set({status:"cantTell"}):void e.set({status:"inapplicable"})})},e.videoMayBePresent=function(e,n,i){var s=["webm","flv","ogv","ogg","avi","mov","qt","wmv","asf","mp4","m4p","m4v","mpg","mp2","mpeg","mpg","mpe","mpv","m2v","3gp","3g2"],a=["//www.youtube.com/embed/","//player.vimeo.com/video/"];n.get("$scope").each(function(){var e=t(this),r=!1;e.find("object, video").each(function(){r=!0,n.add(i({element:this,expected:t(this).closest(".quail-test").data("expected"),
+status:"cantTell"}))}),e.find("a[href]").each(function(){var e=t(this),a=e.attr("href").split(".").pop();-1!==t.inArray(a,s)&&(r=!0,n.add(i({element:this,expected:e.closest(".quail-test").data("expected"),status:"cantTell"})))}),e.find("iframe").each(function(){(-1!==this.src.indexOf(a[0])||-1!==this.src.indexOf(a[1]))&&(r=!0,n.add(i({element:this,expected:e.closest(".quail-test").data("expected"),status:"cantTell"})))}),r||n.add(i({element:this,status:"inapplicable",expected:t(this).closest(".quail-test").data("expected")}))})},e.videosEmbeddedOrLinkedNeedCaptions=function(t,e,n){t.components.video.findVideos(e.get("$scope"),function(i,s){e.add(n(s?{element:i[0],expected:function(e){return t.components.resolveExpectation(e)}(i),status:"passed"}:{element:i[0],expected:function(e){return t.components.resolveExpectation(e)}(i),status:"failed"}))})},e.whiteSpaceInWord=function(e,n,i){var s,a;n.get("$scope").find(e.textSelector).each(function(){a=t(this).text()?t(this).text().match(/[^\s\\]/g):!1,
+s=t(this).text()?t(this).text().match(/[^\s\\]\s[^\s\\]/g):!1,n.add(i(a&&s&&s.length>3&&s.length>=a.length/2-2?{element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"failed"}:{element:this,expected:function(t){return e.components.resolveExpectation(t)}(this),status:"passed"}))})},e.whiteSpaceNotUsedForFormatting=function(e,n,i){n.get("$scope").find(e.textSelector).each(function(){var s=n.add(i({element:this,expected:function(t){return e.components.resolveExpectation(t)}(this)}));if(0===t(this).find("br").length)return void s.set({status:"passed"});var a=t(this).html().toLowerCase().split(/(
)+/),r=0;t.each(a,function(t,e){-1!==e.search(/(\s|\ ){2,}/g)&&r++}),s.set(r>1?{status:"failed"}:{status:"cantTell"})})},e.lib.Case=function(){function e(t){return new e.fn.init(t)}return e.fn=e.prototype={constructor:e,init:function(t){this.listeners={},this.timeout=null,this.attributes=t||{};var e=this;return this.attributes.status&&"untested"!==this.attributes.status?setTimeout(function(){
+e.resolve()},0):(this.attributes.status="untested",this.timeout=setTimeout(function(){e.giveup()},350)),this},attributes:null,get:function(t){return this.attributes[t]},set:function(t,e){var n=!1;if("object"==typeof t)for(var i in t)t.hasOwnProperty(i)&&("status"===i&&(n=!0),this.attributes[i]=t[i]);else"status"===t&&(n=!0),this.attributes[t]=e;return n&&this.resolve(),this},hasStatus:function(t){"object"!=typeof t&&(t=[t]);for(var e=this.get("status"),n=0,i=t.length;i>n;++n)if(t[n]===e)return!0;return!1},resolve:function(){clearTimeout(this.timeout);var t,e=this.attributes.element;e&&e.nodeType&&1===e.nodeType&&(this.attributes.selector=this.defineUniqueSelector(e),this.attributes.html||(this.attributes.html="","HTML"===e.nodeName||"BODY"===e.nodeName?this.attributes.html="<"+e.nodeName+">":"string"==typeof e.outerHTML&&(t=e.outerHTML.trim().replace(/(\r\n|\n|\r)/gm,"").replace(/>\s+<"),t.length>200&&(t=t.substr(0,200)+"... [truncated]"),this.attributes.html=t))),this.dispatch("resolve",this);
+},giveup:function(){clearTimeout(this.timeout),this.attributes.status="notTested",this.dispatch("timeout",this)},listenTo:function(t,e,n){n=n.bind(this),t.registerListener.call(t,e,n)},registerListener:function(t,e){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(e)},dispatch:function(t){if(this.listeners[t]&&this.listeners[t].length){var e=[].slice.call(arguments);this.listeners[t].forEach(function(t){t.apply(null,e)})}},defineUniqueSelector:function(e){function n(e){return 1===t(e).length}function i(t){var e="",n=t.id||"";return n.length>0&&(e="#"+n),e}function s(t){var e="",n=t.className||"";return n.length>0&&(n=n.split(/\s+/),n=o(n,function(t){return/active|enabled|disabled|first|last|only|collapsed|open|clearfix|processed/.test(t)}),n.length>0)?"."+n.join("."):e}function a(t){var e,n="",i=["href","type"];if("undefined"==typeof t||"undefined"==typeof t.attributes||null===t.attributes)return n;for(var s=0,a=i.length;a>s;s++)e=t.attributes[i[s]]&&t.attributes[i[s]].value,
+e&&(n+="["+i[s]+'="'+e+'"]');return n}function r(t){var e="",r="",o=!1,c=!0;do{if(r="",(r=i(t)).length>0){e=r+" "+e;break}!o&&(r=s(t)).length>0&&(e=r+" "+e,n(e)&&(o=!0)),c&&((r=a(t)).length>0&&(e=r+e),e=t.nodeName.toLowerCase()+e,c=!1),t=t.parentNode}while(t&&1===t.nodeType&&"BODY"!==t.nodeName&&"HTML"!==t.nodeName);return e.trim()}function o(t,e){for(var n=[],i=0,s=t.length;s>i;i++)e.call(null,t[i])||n.push(t[i]);return n}return e&&r(e)},push:[].push,sort:[].sort,concat:[].concat,splice:[].splice},e.fn.init.prototype=e.fn,e}(),e.lib.Section=function(){function t(e,n){return new t.fn.init(e,n)}return t.fn=t.prototype={constructor:t,init:function(t,n){if(!t)return this;if(this.id=t,n.techniques&&n.techniques.length){for(var i=0,s=n.techniques.length;s>i;++i)this.push(e.lib.Technique(n.techniques[i]));return this}return this},length:0,each:function(t){for(var e=[].slice.call(arguments,1),n=0,i=this.length;i>n;++n)e.unshift(this[n]),e.unshift(n),t.apply(this[n],e);return this},find:function(t){
+for(var e=0,n=this.length;n>e;++e)if(this[e].get("name")===t)return this[e];return null},set:function(t,n){for(var i=0,s=this.length;s>i;++i)if(this[i].get("name")===t)return this[i].set(n),this[i];var a=e.lib.Test(t,n);return this.push(a),a},addTechnique:function(t){this.push(t)},regiterTechniqueTestResult:function(){},push:[].push,sort:[].sort,splice:[].splice},t.fn.init.prototype=t.fn,t}(),e.lib.SuccessCriteria=function(){function n(t){return new n.fn.init(t)}function i(t){return Object.keys(t).length}return n.fn=n.prototype={constructor:n,init:function(t){return this.listeners={},this.attributes=this.attributes||{},this.attributes.status="untested",this.attributes.results={},this.attributes.totals={},this.set(t||{}),this},length:0,attributes:null,get:function(e){if("$scope"===e){var n=this.attributes.scope,i=t(this.attributes.scope);return this.attributes[e]?this.attributes[e]:n?i:t(document)}return this.attributes[e]},set:function(t,e){var n=!1;if("object"==typeof t)for(var i in t)t.hasOwnProperty(i)&&("status"===i&&(n=!0),
+this.attributes[i]=t[i]);else this.attributes[t]=e;return this},each:function(t){for(var e=[].slice.call(arguments,1),n=0,i=this.length;i>n;++n){e.unshift(this[n]),e.unshift(n);var s=t.apply(this[n],e);if(s===!1)break}return this},add:function(t){this.find(t.get("selector"))||this.push(t)},find:function(t){for(var e=0,n=this.length;n>e;++e)if(this[e].get("selector")===t)return this[e];return null},registerTests:function(t){var e=this.get("preEvaluator"),n="undefined"!=typeof e,i=!0;n&&(i=e.call(this,t)),i||this.set("status","inapplicable"),this.set("tests",t),this.listenTo(t,"complete",this.evaluate)},filterTests:function(t){var n=new e.lib.TestCollection,i=this.get("name");if(!i)throw new Error("Success Criteria instances require a name in order to have tests filtered.");var s=i.split(":")[1];return t.each(function(t,e){var i=e.getGuidelineCoverage("wcag");for(var a in i)i.hasOwnProperty(a)&&a===s&&n.add(e)}),n},addConclusion:function(t,n){this.get("results")[t]||(this.get("results")[t]=e.lib.Test()),
+this.get("results")[t].push(n),this.get("totals")[t]||(this.get("totals")[t]=0),++this.get("totals")[t],this.get("totals").cases||(this.get("totals").cases=0),++this.get("totals").cases},evaluate:function(t,e){if("inapplicable"!==this.get("status")){var n=this,s=this.filterTests(e);0===s.length?this.set("status","noTestCoverage"):(s.each(function(t,e){e.each(function(t,e){n.addConclusion(e.get("status"),e)})}),0===i(this.get("results"))?this.set("status","noResults"):this.set("status","tested"))}this.report()},report:function(){var t=Array.prototype.slice.call(arguments);t=[].concat(["successCriteriaEvaluated",this,this.get("tests")],t),this.dispatch.apply(this,t)},listenTo:function(t,e,n){n=n.bind(this),t.registerListener.call(t,e,n)},registerListener:function(t,e){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(e)},dispatch:function(t){if(this.listeners[t]&&this.listeners[t].length){var e=[].slice.call(arguments);this.listeners[t].forEach(function(t){t.apply(null,e)});
+}},push:[].push,sort:[].sort,splice:[].splice},n.fn.init.prototype=n.fn,n}(),e.lib.Technique=function(){function t(e,n){return new t.fn.init(e,n)}return t.fn=t.prototype={constructor:t,init:function(t,e){return this.listeners={},t?(this.attributes=e||{},this.attributes.name=t,this):this},length:0,attributes:{},each:function(t){for(var e=[].slice.call(arguments,1),n=0,i=this.length;i>n;++n)e.unshift(this[n]),e.unshift(n),t.apply(this[n],e);return this},get:function(t){return this.attributes[t]},set:function(t,e){if("object"==typeof t)for(var n in t)t.hasOwnProperty(n)&&(this.attributes[n]=t[n]);else this.attributes[t]=e;return this},addTest:function(){},report:function(t,e){window.console&&window.console.log(this.get("name"),e.status,e,e[0]&&e[0].status)},listenTo:function(t,e,n){n=n.bind(this),t.registerListener.call(t,e,n)},registerListener:function(t,e){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(e)},dispatch:function(t){if(this.listeners[t]&&this.listeners[t].length){
+var e=[].slice.call(arguments);this.listeners[t].forEach(function(t){t.apply(null,e)})}},push:[].push,sort:[].sort,splice:[].splice},t.fn.init.prototype=t.fn,t}(),e.lib.Test=function(){function n(t,e){return new n.fn.init(t,e)}function i(t){t="undefined"==typeof t?!0:t,this.each(function(e,n){n.get("status")||(t=!1)}),t?(this.testComplete=null,this.attributes.complete=!0,this.determineStatus()):this.testComplete()}function s(t,e,n){var i,s;return function(){var a=this,r=arguments,o=function(){i=null,n||(s=t.apply(a,r))},c=n&&!i;return clearTimeout(i),i=setTimeout(o,e),c&&(s=t.apply(a,r)),s}}return n.fn=n.prototype={constructor:n,init:function(t,e){return this.listeners={},this.length=0,t?(this.attributes=e||{},this.attributes.name=t,this.attributes.status="untested",this.attributes.complete=!1,this):this},length:0,attributes:null,each:function(t){for(var e=[].slice.call(arguments,1),n=0,i=this.length;i>n;++n)e.unshift(this[n]),e.unshift(n),t.apply(this[n],e);return this},get:function(e){
+if("$scope"===e){var n=this.attributes.scope,i=t(this.attributes.scope);return this.attributes[e]?this.attributes[e]:n?i:t(document)}return this.attributes[e]},set:function(t,e){var n=!1;if("object"==typeof t)for(var i in t)t.hasOwnProperty(i)&&("status"===i&&(n=!0),this.attributes[i]=t[i]);else"status"===t&&(n=!0),this.attributes[t]=e;return n&&this.resolve(),this},add:function(t){return this.listenTo(t,"resolve",this.caseResponded),this.listenTo(t,"timeout",this.caseResponded),t.status&&t.dispatch("resolve",t),this.push(t),t},invoke:function(){if(this.testComplete)throw new Error("The test "+this.get("name")+" is already running.");if(this.attributes.complete)throw new Error("The test "+this.get("name")+" has already been run.");var t=this.get("type"),n=this.get("options")||{},a=this.get("callback"),r=this;if(this.testComplete=s(i.bind(this),400),this.testComplete(!1),"custom"===t)if("function"==typeof a)try{a.call(this,e,r,e.lib.Case,n)}catch(o){window.console&&window.console.error&&window.console.error(o);
+}else{if("custom"!==t||"function"!=typeof e[a])throw new Error("The callback "+a+" cannot be invoked.");try{e[a].call(this,e,r,e.lib.Case,n)}catch(o){window.console&&window.console.error&&window.console.error(o)}}else{if("function"!=typeof e.components[t])throw new Error("The component type "+t+" is not defined.");try{e.components[t].call(this,e,r,e.lib.Case,n)}catch(o){window.console&&window.console.error&&window.console.error(o)}}return this.testComplete(),this},findByStatus:function(t){if(t){var e=new n;"string"==typeof t&&(t=[t]);for(var i=0,s=t.length;s>i;++i){var a=t[i];this.each(function(t,n){var i=n.get("status");i===a&&e.add(n)})}return e}},findCasesBySelector:function(t){var e=this.groupCasesBySelector();return e.hasOwnProperty(t)?e[t]:new n},findCaseByHtml:function(t){for(var n,i=0,s=this.length;s>i;++i)if(n=this[i],t===n.get("html"))return n;return e.lib.Case()},groupCasesBySelector:function(){var t={};return this.each(function(e,i){var s=i.get("selector");t[s]||(t[s]=new n),
+t[s].add(i)}),t},groupCasesByHtml:function(){var t={};return this.each(function(e,i){var s=i.get("html");t[s]||(t[s]=new n),t[s].add(i)}),t},getGuidelineCoverage:function(t){var e=this.get("guidelines");return e&&e[t]||{}},caseResponded:function(t,e){this.dispatch(t,this,e),"function"==typeof this.testComplete&&this.testComplete()},determineStatus:function(){var t,n=this.get("type");e.components[n]&&"function"==typeof e.components[n].postInvoke&&(t=e.components[n].postInvoke.call(this,this)),this.set(t===!0?{status:"passed"}:this.findByStatus(["cantTell"]).length===this.length?{status:"cantTell"}:this.findByStatus(["inapplicable"]).length===this.length?{status:"inapplicable"}:this.findByStatus(["failed","untested"]).length?{status:"failed"}:{status:"passed"})},resolve:function(){this.dispatch("complete",this)},testComplete:null,listenTo:function(t,e,n){n=n.bind(this),t.registerListener.call(t,e,n)},registerListener:function(t,e){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(e);
+},dispatch:function(t){if(this.listeners[t]&&this.listeners[t].length){var e=[].slice.call(arguments);this.listeners[t].forEach(function(t){t.apply(null,e)})}},push:[].push,sort:[].sort,concat:[].concat,splice:[].splice},n.fn.init.prototype=n.fn,n}(),e.lib.TestCollection=function(){function t(e){return new t.fn.init(e)}function n(){var t=!0;this.each(function(e,n){n.get("complete")||(t=!1)}),t?(this.testsComplete=null,this.dispatch("complete",this)):this.testsComplete()}function i(t,e,n){var i,s;return function(){var a=this,r=arguments,o=function(){i=null,n||(s=t.apply(a,r))},c=n&&!i;return clearTimeout(i),i=setTimeout(o,e),c&&(s=t.apply(a,r)),s}}return t.fn=t.prototype={constructor:t,init:function(t,n){if(this.listeners={},n=n||{},!t)return this;if("object"==typeof t){var i;for(var s in t)t.hasOwnProperty(s)&&(t[s].scope=t[s].scope||n.scope,i=new e.lib.Test(s,t[s]),this.listenTo(i,"results",this.report),this.push(i));return this}return this},length:0,run:function(t){var e=this;return t=t||{},
+this.each(function(n,i){t.preFilter&&e.listenTo(i,"resolve",function(e,n,i){var s=t.preFilter(e,n,i);s===!1&&(i.attributes.status="notTested",i.attributes.expected=null)}),t.caseResolve&&e.listenTo(i,"resolve",t.caseResolve),t.testComplete&&e.listenTo(i,"complete",t.testComplete)}),t.testCollectionComplete&&e.listenTo(e,"complete",t.testCollectionComplete),this.testsComplete=i(n.bind(this),500),this.each(function(t,e){e.invoke()}),this.testsComplete(),this},each:function(t){for(var e=[].slice.call(arguments,1),n=0,i=this.length;i>n;++n){e.unshift(this[n]),e.unshift(n);var s=t.apply(this[n],e);if(s===!1)break}return this},add:function(t){this.find(t.get("name"))||this.push(t)},find:function(t){for(var e=0,n=this.length;n>e;++e)if(this[e].get("name")===t)return this[e];return null},findByGuideline:function(e){var n={wcag:function(n,i){function s(e,n,i){var s=new t;return this.each(function(t,a){var r=a.get("guidelines"),o=r[e]&&r[e][n]&&r[e][n].techniques;if(o)for(var c=0,u=o.length;u>c;++c)o[c]===i&&(s.listenTo(a,"results",s.report),
+s.add(a))}),s}var a=n.id,r=i.get("name");return a&&r?s.call(this,e,a,r):void 0}};if(n[e]){var i=[].slice.call(arguments,1);return n[e].apply(this,i)}},findByStatus:function(e){if(e){var n=new t;"string"==typeof e&&(e=[e]);for(var i=0,s=e.length;s>i;++i){var a=e[i];this.each(function(t,e){var i=e.get("status");i===a&&n.add(e)})}return n}},set:function(t,n){for(var i=0,s=this.length;s>i;++i)if(this[i].get("name")===t)return this[i].set(n),this[i];var a=e.lib.Test(t,n);return this.push(a),a},testsComplete:null,report:function(){this.dispatch.apply(this,arguments)},listenTo:function(t,e,n){n=n.bind(this),t.registerListener.call(t,e,n)},registerListener:function(t,e){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(e)},dispatch:function(t){if(this.listeners[t]&&this.listeners[t].length){var e=[].slice.call(arguments);this.listeners[t].forEach(function(t){t.apply(null,e)})}},push:[].push,sort:[].sort,splice:[].splice},t.fn.init.prototype=t.fn,t}(),e.lib.WCAGGuideline=function(){
+var t=function(e){return new t.fn.init(e)};return t.fn=t.prototype={constructor:t,init:function(t){if(!t)return this;this.techniques=[];var n,i,s,a,r;if("object"==typeof t){if(t.guidelines){n=t.guidelines;for(var o in n)if(n.hasOwnProperty(o)){if(i=n[o],i.techniques&&i.techniques.length&&(s=i.techniques,delete i.techniques),i=e.lib.Section(o,i),s.length)for(var c=0,u=s.length;u>c;++c){if(a=s[c],!t.techniques[a])throw new Error("Definition for Technique "+a+" is missing from the guideline specification");r=this.findTechnique(a),r||(r=e.lib.Technique(a,t.techniques[a]),this.techniques.push(r)),i.addTechnique(r)}this.push(i)}}return this}return this},length:0,each:function(t){for(var e=[].slice.call(arguments,1),n=0,i=this.length;i>n;++n)e.unshift(this[n]),e.unshift(n),t.apply(this[n],e);return this},find:function(t){for(var e=0,n=this.length;n>e;++e)if(this[e].get("name")===t)return this[e];return null},findTechnique:function(t){for(var e=0,n=this.techniques.length;n>e;++e)if(this.techniques[e].get("name")===t)return this.techniques[e];
+return null},set:function(t,n){for(var i=0,s=this.length;s>i;++i)if(this[i].get("name")===t)return this[i].set(n),this[i];var a=e.lib.Test(t,n);return this.push(a),a},evaluate:function(){},results:function(){},push:[].push,sort:[].sort,splice:[].splice},t.fn.init.prototype=t.fn,t}(),function(t){function e(e,n,i,s){var a=n.attr("rowspan")||1,r=n.attr("scope");if("col"===r)return!0;if(-1!==c.indexOf(r))return!1;for(var o=0;o=0&&a>=0;s+=r,a+=o){var p=t(i[a][s]),f=0===r?"col":"row";if(p.is("th")){c=!0,u.push({cell:p,x:s,y:a});var g=!1;-1===o&&n(i,p,s,a)||-1===r&&e(i,p,s,a)?g=!0:t.each(h,function(e,n){
+var i=+p.attr(f+"span")||1,c=+t(n.cell).attr(f+"span")||1;i===c&&(-1===o&&n.x===s||-1===r&&n.y===a)&&(g=!0)}),g===!1&&(l=l.add(p))}else p.is("td")&&c===!0&&(c=!1,h.push(u),u=t())}return l}function s(e){var n=e.closest("table"),i=e.attr("headers").split(/\s/),s=t();return t.each(i,function(e,i){s=s.add(t("th#"+i+", td#"+i,n))}),s}function a(t,e){for(var n,i=0,s=0;void 0===n;){if(void 0===t[s])return;t[s][i]===e[0]?n=i:i+1===t[s].length?(s+=1,i=0):i+=1}return{x:n,y:s}}function r(e,n){var s,r=t(),o=a(n,e),c=+e.attr("rowspan")||1,u=+e.attr("colspan")||1;for(s=0;u>s;s++)r=r.add(i(n,o.x+s,o.y,0,-1));for(s=0;c>s;s++)r=r.add(i(n,o.x,o.y+s,-1,0));return r}function o(e,n){var i=a(n,e),s=t();e.closest("thead, tbody, tfoot").find("th[scope=rowgroup]").each(function(){var e=a(n,t(this));e.x<=i.x&&e.y<=i.y&&(s=s.add(this))})}var c=["row","col","rowgroup","colgroup"];t.fn.getTableMap=function(){var e=[];return this.find("tr").each(function(n){"undefined"==typeof e[n]&&(e[n]=[]);var i=e[n];t(this).children().each(function(){
+var s,a,r,o=t(this),c=+o.attr("rowspan")||1,u=+o.attr("colspan")||1;for(a=0,r=i.length;r>=a;a+=1)void 0===s&&void 0===i[a]&&(s=a);for(a=0,r=u*c;r>a;a+=1)void 0===e[n+~~(a/u)]&&(e[n+~~(a/u)]=[]),e[n+~~(a/u)][s+a%u]=this})}),e},t.fn.tableHeaders=function(){var e=t();return this.each(function(){var n=t(this);if(!n.is(":not(td, th)"))if(n.is("[headers]"))e=e.add(s(n));else{var i=n.closest("table").getTableMap();e=e.add(r(n,i)).add(o(n,i))}}),e.not(":empty").not(this)}}(jQuery),e.lib.wcag2=function(){function n(e){e.wcag2Structure&&e.accessibilityTests&&e.preconditionTests?i(e,e.wcag2Structure,e.accessibilityTests,e.preconditionTests):t.when(t.ajax(e.jsonPath+"/wcag2.json",a),t.ajax(e.jsonPath+"/tests.json",a),t.ajax(e.jsonPath+"/preconditions.json",a)).done(function(t,n,s){i(e,t[0],n[0],s[0])})}function i(n,i,a,r){var o,c,u,l=[];o=t.map(i,function(t){return new e.lib.wcag2.Criterion(t,a,r,n.subject)}),t.each(o,function(t,e){l.push.apply(l,e.getTests())}),u=[],c=[],t.each(l,function(t,e){-1===u.indexOf(e.title.en)&&(u.push(e.title.en),
+c.push(e))}),t(e.html).quail({accessibilityTests:c,testCollectionComplete:s(o,n.testCollectionComplete)})}function s(e,n){return function(i,s){"complete"===i&&(s=t.map(e,function(t){return t.getResult(s)})),n(i,s)}}var a={async:!1,dataType:"json"};return{run:n}}(),e.guidelines.wcag.successCriteria["1.1.1"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.1.1",preEvaluator:e});return n.techniques={},n.failures={F3:"Using CSS to include images that convey important information",F13:"Having a text alternative that does not include information that is conveyed by color differences in the image",F20:"Not updating text alternatives when changes to non-text content occur",F30:"Using text alternatives that are not alternatives (e.g., filenames or placeholder text)",F38:"Not marking up decorative images in HTML in a way that allows assistive technology to ignore them",F39:'Providing a text alternative that is not null (e.g., alt="spacer" or alt="image") for images that should be ignored by assistive technology',
+F65:'Omitting the alt attribute or text alternative on img elements, area elements, and input elements of type "image"',F67:"Providing long descriptions for non-text content that does not serve the same purpose or does not present the same information",F71:"Using text look-alikes to represent text without providing a text alternative",F72:"Using ASCII art without providing a text alternative"},n}(e),e.guidelines.wcag.successCriteria["1.2.1"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.2.1",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["1.2.2"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.2.2",preEvaluator:e});return n.techniques={G93:"Providing open (always visible) captions",G87:"Providing closed captions"},n.failures={F74:"Not labeling a synchronized media alternative to text as an alternative",F75:"Providing synchronized media without captions when the synchronized media presents more information than is presented on the page",
+F8:"Captions omitting some dialogue or important sound effects"},n}(e),e.guidelines.wcag.successCriteria["1.2.3"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.2.3",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["1.2.4"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.2.4",preEvaluator:e});return n.techniques={G9:"Creating captions for live synchronized media",G93:"Providing open (always visible) captions",G87:"Providing closed captions using any readily available media format that has a video player that supports closed captioning"},n.failures={},n}(e),e.guidelines.wcag.successCriteria["1.2.5"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.2.5",preEvaluator:e});return n.techniques={G78:"Providing a second, user-selectable, audio track that includes audio descriptions",G173:"Providing a version of a movie with audio descriptions","SC1.2.8":"Providing a movie with extended audio descriptions",
+G8:"Providing a movie with extended audio descriptions",G203:"Using a static text alternative to describe a talking head video"},n.failures={},n}(e),e.guidelines.wcag.successCriteria["1.2.7"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.2.7",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["1.2.8"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.2.8",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["1.2.9"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.2.9",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["1.3.1"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.3.1",preEvaluator:e});return n.techniques={G115:"Using semantic elements to mark up structure AND H49: Using semantic markup to mark emphasized or special text",G117:"Using text to convey information that is conveyed by variations in presentation of text",
+G140:"Separating information and structure from presentation to enable different presentations",G138:"Using semantic markup whenever color cues are used",H48:"Using ol, ul and dl for lists or groups of links",H42:"Using h1-h6 to identify headings",SCR21:"Using functions of the Document Object Model (DOM) to add content to a page (Scripting)",H51:"Using table markup to present tabular information",H39:"Using caption elements to associate data table captions with data tables",H73:"Using the summary attribute of the table element to give an overview of data tables",H63:"Using the scope attribute to associate header cells and data cells in data tables",H43:"Using id and headers attributes to associate data cells with header cells in data tables",H44:"Using label elements to associate text labels with form controls",H65:"Using the title attribute to identify form controls when the label element cannot be used",H71:"Providing a description for groups of form controls using fieldset and legend elements",
+H85:"Using OPTGROUP to group OPTION elements inside a SELECT",ARIA11:"Using ARIA landmarks to identify regions of a page (ARIA)",ARIA12:"Using role=heading to identify headings (ARIA)",ARIA13:"Using aria-labelledby to name regions and landmarks (ARIA)",ARIA16:"Using aria-labelledby to provide a name for user interface controls (ARIA)",ARIA17:"Using grouping roles to identify related form controls (ARIA)"},n.failures={F2:"Using changes in text presentation to convey information without using the appropriate markup or text",F17:"Insufficient information in DOM to determine one-to-one relationships (e.g., between labels with same id) in HTML",F42:"Using scripting events to emulate links in a way that is not programmatically determinable",F43:"Using structural markup in a way that does not represent relationships in the content",F87:"Inserting non-decorative content by using :before and :after pseudo-elements and the content property in CSS",F46:"Using th elements, caption elements, or non-empty summary attributes in layout tables",
+F48:"Using the pre element to markup tabular information",F90:"Incorrectly associating table headers and content via the headers and id attributes",F91:"Not correctly marking up table headers",F33:"Using white space characters to create multiple columns in plain text content",F34:"Using white space characters to format tables in plain text content",F68:"Association of label and user interface controls not being programmatically determinable"},n}(e),e.guidelines.wcag.successCriteria["1.3.2"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.3.2",preEvaluator:e});return n.techniques={G57:"Ordering the content in a meaningful sequence (scope: for all the content in the Web page)",H34:"Using a Unicode right-to-left mark (RLM) or left-to-right mark (LRM) to mix text direction inline (languageUnicodeDirection)",H56:"Using the dir attribute on an inline element to resolve problems with nested directional runs",C6:"Positioning content based on structural markup (CSS)",
+C8:"Using CSS letter-spacing to control spacing within a word",C27:"Making the DOM order match the visual order (CSS)"},n.failures={F49:"Using an HTML layout table that does not make sense when linearized",F32:"Using white space characters to control spacing within a word (whiteSpaceInWord)",F1:"Changing the meaning of content by positioning information with CSS",F34:"Using white space characters to format tables in plain text content (tabularDataIsInTable)",F33:"Using white space characters to create multiple columns in plain text content (tabularDataIsInTable)"},n}(e),e.guidelines.wcag.successCriteria["1.3.3"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.3.3",preEvaluator:e});return n.techniques={G96:"Providing textual identification of items that otherwise rely only on sensory information to be understood"},n.failures={F14:"Identifying content only by its shape or location",F26:"Using a graphical symbol alone to convey information"},n}(e),e.guidelines.wcag.successCriteria["1.4.1"]=function(t){
+function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.4.1",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["1.4.2"]=function(e){function n(){return!!t("audio, video, object, embed").length}var i=e.lib.SuccessCriteria({name:"wcag:1.4.2",preEvaluator:n});return i.techniques={G60:"Playing a sound that turns off automatically within three seconds",G170:"Providing a control near the beginning of the Web page that turns off sounds that play automatically",G171:"Playing sounds only on user request"},i.failures={F23:"Playing a sound longer than 3 seconds where there is no mechanism to turn it off"},i}(e),e.guidelines.wcag.successCriteria["1.4.3"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.4.3",preEvaluator:e});return n.techniques={G148:"Not specifying background color, not specifying text color, and not using technology features that change those defaults",G174:"Providing a control with a sufficient contrast ratio that allows users to switch to a presentation that uses sufficient contrast",
+G18:"Ensuring that a contrast ratio of at least 4.5:1 exists between text (and images of text) and background behind the text for situation A AND G145: Ensuring that a contrast ratio of at least 3:1 exists between text (and images of text) and background behind the text for situation B"},n.failures={F24:"Specifying foreground colors without specifying background colors or vice versa",F83:"Using background images that do not provide sufficient contrast with foreground text (or images of text)"},n}(e),e.guidelines.wcag.successCriteria["1.4.4"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.4.4",preEvaluator:e});return n.techniques={G142:"Using a technology that has commonly-available user agents that support zoom",C12:"Using percent for font sizes",C13:"Using named font sizes",C14:"Using em units for font, sizes",SCR34:"Calculating size and ,position in a way that scales with text size (Scripting)",G146:"Using liquid layout",G178:"Providing controls on the Web page that allow users to incrementally change the size of all text on the page up to 200 percent",
+G179:"Ensuring that there is no loss of content or functionality when the text resizes and text containers do not change their width"},n.failures={F69:"Resizing visually rendered text up to 200 percent causes the text, image or controls to be clipped, truncated or obscured",F80:"Text-based form controls do not resize when visually rendered text is resized up to 200%"},n}(e),e.guidelines.wcag.successCriteria["1.4.5"]=function(t){function e(){return!!document.querySelectorAll("img, map").length}var n=t.lib.SuccessCriteria({name:"wcag:1.4.5",preEvaluator:e});return n.techniques={C22:"Using CSS to control visual presentation of text (CSS)",C30:"Using CSS to replace text with images of text and providing user interface controls to switch",G140:"Separating information and structure from presentation to enable different presentations"},n.failures={},n}(e),e.guidelines.wcag.successCriteria["1.4.6"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.4.6",preEvaluator:e});
+return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["1.4.7"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.4.7",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["1.4.8"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.4.8",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["1.4.9"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:1.4.9",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.1.1"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.1.1",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.1.2"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.1.2",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.1.3"]=function(t){
+function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.1.3",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.2.1"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.2.1",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.2.2"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.2.2",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.2.3"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.2.3",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.2.4"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.2.4",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.2.5"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.2.5",preEvaluator:e
+});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.3.1"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.3.1",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.3.2"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.3.2",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.4.1"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.4.1",preEvaluator:e});return n.techniques={G1:"Adding a link at the top of each page that goes directly to the main content area",G123:"Adding a link at the beginning of a block of repeated content to go to the end of the block",G124:"Adding links at the top of the page to each area of the content",H69:"Providing heading elements at the beginning of each section of content",H70:"Using frame elements to group blocks of repeated material AND H64: Using the title attribute of the frame and iframe elements",
+SCR28:"Using an expandable and collapsible menu to bypass block of content"},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.4.10"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.4.10",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.4.2"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.4.2",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.4.3"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.4.3",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.4.4"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.4.4",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.4.5"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.4.5",preEvaluator:e});return n.techniques={},n.failures={},
+n}(e),e.guidelines.wcag.successCriteria["2.4.6"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.4.6",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.4.7"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.4.7",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.4.8"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.4.8",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["2.4.9"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:2.4.9",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["3.1.1"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:3.1.1",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["3.1.2"]=function(t){function e(){return!0;
+}var n=t.lib.SuccessCriteria({name:"wcag:3.1.2",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["3.1.3"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:3.1.3",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["3.1.4"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:3.1.4",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["3.1.5"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:3.1.5",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["3.1.6"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:3.1.6",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["3.2.1"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:3.2.1",preEvaluator:e});return n.techniques={
+G107:'Using "activate" rather than "focus" as a trigger for changes of context'},n.failures={F52:"Opening a new window as soon as a new page is loaded",F55:"Using script to remove focus when focus is received"},n}(e),e.guidelines.wcag.successCriteria["3.2.2"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:3.2.2",preEvaluator:e});return n.techniques={G80:"Providing a submit button to initiate a change of context",H32:"Providing submit buttons",H84:"Using a button with a select element to perform an action",G13:"Describing what will happen before a change to a form control that causes a change of context to occur is made",SCR19:"Using an onchange event on a select element without causing a change of context"},n.failures={F36:"Automatically submitting a form and presenting new content without prior warning when the last field in the form is given a value",F37:"Launching a new window without prior warning when the status of a radio button, check box or select list is changed",
+F76:"Providing instruction material about the change of context by change of setting in a user interface element at a location that users may bypass"},n}(e),e.guidelines.wcag.successCriteria["3.2.3"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:3.2.3",preEvaluator:e});return n.techniques={G61:"Presenting repeated components in the same relative order each time they appear"},n.failures={F66:"Presenting navigation links in a different relative order on different pages"},n}(e),e.guidelines.wcag.successCriteria["3.2.4"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:3.2.4",preEvaluator:e});return n.techniques={G197:"Using labels, names, and text alternatives consistently for content that has the same functionality AND following the sufficient techniques for Success Criterion 1.1.1 and sufficient techniques for Success Criterion 4.1.2 for providing labels, names, and text alternatives."},n.failures={F31:"Using two different labels for the same function on different Web pages within a set of Web pages"
+},n}(e),e.guidelines.wcag.successCriteria["3.2.5"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:3.2.5",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["3.3.1"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:3.3.1",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["3.3.2"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:3.3.2",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["3.3.3"]=function(t){function e(){function t(t){return!!this.querySelectorAll('[type="'+t+'"]').length}function e(t){var e=Object.keys(t)[0];return!!this.querySelectorAll("["+e+'="'+t[e]+'"]').length}var n=["checkbox","color","date","datetime","datetime-local","email","file","hidden","month","number","password","radio","range","search","tel","time","url","week"],i=[{required:"required"},{"aria-required":"true"
+}];return document.querySelectorAll("form").length?n.some(t,document)||i.some(e,document)?!0:void 0:!1}var n=t.lib.SuccessCriteria({name:"wcag:3.3.3",preEvaluator:e});return n.techniques={G83:"Providing text descriptions to identify required fields that were not completed",ARIA2:"Identifying a required field with the aria-required property",ARIA18:"Using aria-alertdialog to Identify Errors (ARIA)",G85:"Providing a text description when user input falls outside the required format or values",G177:"Providing suggested correction text",SCR18:"Providing client-side validation and alert (Scripting)",SCR32:"Providing client-side validation and adding error text via the DOM (Scripting)",G84:"Providing a text description when the user provides information that is not in the list of allowed values"},n.failures={},n}(e),e.guidelines.wcag.successCriteria["3.3.4"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:3.3.4",preEvaluator:e});return n.techniques={},n.failures={},n;
+}(e),e.guidelines.wcag.successCriteria["3.3.5"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:3.3.5",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["3.3.6"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:3.3.6",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["4.1.1"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:4.1.1",preEvaluator:e});return n.techniques={},n.failures={},n}(e),e.guidelines.wcag.successCriteria["4.1.2"]=function(t){function e(){return!0}var n=t.lib.SuccessCriteria({name:"wcag:4.1.2",preEvaluator:e});return n.techniques={ARIA14:"Using aria-label to provide an invisible label where a visible label cannot be used",ARIA16:"Using aria-labelledby to provide a name for user interface controls",G108:"Using markup features to expose the name and role, allow user-settable properties to be directly set, and provide notification of changes using technology-specific techniques below:",
+H91:"Using HTML form controls and links",H44:"Using label elements to associate text labels with form controls",H64:"Using the title attribute of the frame and iframe elements",H65:"Using the title attribute to identify form controls when the label element cannot be used",H88:"Using HTML according to spec"},n.failures={F59:"Using script to make div or span a user interface control in HTML without providing a role for the control (This failure may be solved in the future using DHTML roadmap techniques.)",F20:"Not updating text alternatives when changes to non-text content occur",F68:"Association of label and user interface controls not being programmatically determined",F79:"Focus state of a user interface component not being programmatically determinable or no notification of change of focus state available",F86:"Not providing names for each part of a multi-part form field, such as a US telephone number",F89:"Using null alt on an image where the image is the only content in a link"},n}(e),
+e.lib.wcag2.Criterion=function(){function n(n,i){var s=e.lib.wcag2.EarlAssertion.getResultPriority,a={result:i};return t.each(n,function(t,e){s(a)0&&(s.hasPart=a),s},c.getTests=function(){var e=[];return t.each(o,function(t,n){e.push.apply(e,n.tests)}),e},c}return i}(),e.lib.wcag2.EarlAssertion=function(){function e(e){t.extend(this,e,s),this.outcome=t.extend({},this.outcome)}var n,i=["untested","inapplicable","passed","cantTell","failed"],s={type:"assertion",
+subject:n,assertedBy:{type:"earl:Software",name:"QuailJS"},mode:"automated"};return window&&window.location&&(n=window.location.href),e.getResultPriority=function(t){return"object"==typeof t&&(t=t.outcome?t.outcome.result:t.result),i.indexOf(t)},e}(),e.lib.wcag2.TestAggregator=function(){function n(e,n){t.each(e,function(t,e){e.each(function(){n.call(this,e,this)})})}function i(e){var n=[],i=[];return t.each(e,function(t,e){var n=[];e.each(function(){n.push(this.get("element")),u.add(this)}),i.push(n)}),t.each(i,function(e,i){if(0===e)return void(n=i);var s=[];t.each(i,function(t,e){-1!==n.indexOf(e)&&s.push(e)}),n=s}),n}function s(t){var e=[];return n(t,function(t,n){var i=n.get("element");-1===e.indexOf(i)&&(e.push(i),u.add(n))}),e}function a(n,i){var s=[];return t.each(n,function(t,n){var a=new e.lib.wcag2.EarlAssertion(i);n&&(a.outcome.pointer=u.getPointer(n)),s.push(a)}),s}function r(t,s){var r=jQuery.unique(i(s)),o=a(jQuery.unique(r),{testCase:t.id,outcome:{result:"failed"}});return n(s,function(n,i){
+var s=i.get("status"),a=e.lib.wcag2.EarlAssertion.getResultPriority,c=o[r.indexOf(i.get("element"))];if(t[s]&&(s=t[s]),c&&a(c)>=a(s)){var u=c.outcome.pointer;c.outcome={result:s,info:n.get("title")},u&&(c.outcome.pointer=u)}}),o}function o(t,i){var r=s(i),o=a(r,{testCase:t.id,outcome:{result:"untested"}});return n(i,function(n,i){var s=i.get("status"),a=e.lib.wcag2.EarlAssertion.getResultPriority,c=o[r.indexOf(i.get("element"))];t[s]&&(s=t[s]),c&&a(c)= 0 && year < 100 ) {
+ // Year 70 and greater will be considered 19xx.
+ if ( year >= 70 ) {
+ year += 1900;
+ } else {
+ // Otherwise we assume it's 20xx.
+ year += 2000;
+ }
+ }
+
+ // Cast day to Number, to remove leading 0.
+ return [ Number( dateObj.day ), monthName, year ].join( ' ' );
+ };
+
+ DateUnfold.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'de/DateUnfold', DateUnfold );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/de/ElementRemove.js b/plugins/ckeditor/a11ychecker/quickfix/de/ElementRemove.js
new file mode 100644
index 0000000..c0be413
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/de/ElementRemove.js
@@ -0,0 +1,43 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'de',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * The ultimate fix for unsolvable problem - removing an element.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class ElementRemove
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue
+ */
+ function ElementRemove( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ ElementRemove.prototype = new QuickFix();
+ ElementRemove.prototype.constructor = ElementRemove;
+
+ ElementRemove.prototype.display = function( form ) {
+ form.setInputs( {} );
+ };
+
+ ElementRemove.prototype.fix = function( formAttributes, callback ) {
+ this.issue.element.remove();
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ ElementRemove.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'de/ElementRemove', ElementRemove );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/de/ElementReplace.js b/plugins/ckeditor/a11ychecker/quickfix/de/ElementReplace.js
new file mode 100644
index 0000000..e99c99f
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/de/ElementReplace.js
@@ -0,0 +1,59 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'de',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * Replaces provided element with element that a different tag name, preserving its children.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class ElementReplace
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue
+ */
+ function ElementReplace( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ ElementReplace.prototype = new QuickFix();
+ ElementReplace.prototype.constructor = ElementReplace;
+
+ /**
+ * Returns the name of the tag that issue.element should be converted to.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.ElementReplace
+ * @param {Object} formAttributes Form attributes from {@link #fix}.
+ * @returns {String}
+ */
+ ElementReplace.prototype.getTargetName = function( formAttributes ) {
+ return 'h1';
+ };
+
+ ElementReplace.prototype.display = function( form ) {
+ form.setInputs( {} );
+ };
+
+ ElementReplace.prototype.fix = function( formAttributes, callback ) {
+ var newElement = new CKEDITOR.dom.element( this.getTargetName( formAttributes ) );
+
+ newElement.replace( this.issue.element );
+ this.issue.element.moveChildren( newElement );
+
+ this.issue.element = newElement;
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ ElementReplace.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'de/ElementReplace', ElementReplace );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/de/ImgAlt.js b/plugins/ckeditor/a11ychecker/quickfix/de/ImgAlt.js
new file mode 100644
index 0000000..2bb129a
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/de/ImgAlt.js
@@ -0,0 +1,89 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'de',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+
+ var emptyWhitespaceRegExp = /^[\s\n\r]+$/g;
+
+ /**
+ * Fixes the image with missing alt attribute.
+ *
+ * @constructor
+ */
+ function ImgAlt( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ /**
+ * Maximal count of characters in the alt. It might be changed to `0` to prevent
+ * length validation.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.AttributeRename
+ * @static
+ */
+ ImgAlt.altLengthLimit = 100;
+
+ ImgAlt.prototype = new QuickFix();
+ ImgAlt.prototype.constructor = ImgAlt;
+
+ ImgAlt.prototype.display = function( form ) {
+ form.setInputs( {
+ alt: {
+ type: 'text',
+ label: this.lang.altLabel,
+ value: this.issue.element.getAttribute( 'alt' ) || ''
+ }
+ } );
+ };
+
+ ImgAlt.prototype.fix = function( formAttributes, callback ) {
+ this.issue.element.setAttribute( 'alt', formAttributes.alt );
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ ImgAlt.prototype.validate = function( formAttributes ) {
+ var ret = [],
+ proposedAlt = formAttributes.alt + '',
+ imgElem = this.issue && this.issue.element,
+ lang = this.lang;
+
+ // Test if the alt has only whitespaces.
+ if ( proposedAlt.match( emptyWhitespaceRegExp ) ) {
+ ret.push( lang.errorWhitespace );
+ }
+
+ // Testing against exceeding max length.
+ if ( ImgAlt.altLengthLimit && proposedAlt.length > ImgAlt.altLengthLimit ) {
+ var errorTemplate = new CKEDITOR.template( lang.errorTooLong );
+
+ ret.push( errorTemplate.output( {
+ limit: ImgAlt.altLengthLimit,
+ length: proposedAlt.length
+ } ) );
+ }
+
+ if ( imgElem ) {
+ var fileName = String( imgElem.getAttribute( 'src' ) ).split( '/' ).pop();
+ if ( fileName == proposedAlt ) {
+ ret.push( lang.errorSameAsFileName );
+ }
+ }
+
+ return ret;
+ };
+
+ ImgAlt.prototype.lang = {"altLabel":"Alternativtext","errorTooLong":"Der Alternativtext ist zu lang. Er sollte {limit} Zeichen lang sein, ist aber aktuell {length} Zeichen lang","errorWhitespace":"Der Alternativtext kann nicht nur Leerzeichen enthalten","errorSameAsFileName":"Der Alternativtext sollte nicht dem Dateinamen entsprechen"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'de/ImgAlt', ImgAlt );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/de/ImgAltNonEmpty.js b/plugins/ckeditor/a11ychecker/quickfix/de/ImgAltNonEmpty.js
new file mode 100644
index 0000000..cc09de6
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/de/ImgAltNonEmpty.js
@@ -0,0 +1,44 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'de',
+ name: 'ImgAlt',
+ callback: function( ImgAlt ) {
+
+ /**
+ * Fixes the image with missing alt attribute, requiring non-empty alt.
+ *
+ * @constructor
+ */
+ function ImgAltNonEmpty( issue ) {
+ ImgAlt.call( this, issue );
+ }
+
+ ImgAltNonEmpty.prototype = new ImgAlt();
+ ImgAltNonEmpty.prototype.constructor = ImgAltNonEmpty;
+
+ ImgAltNonEmpty.prototype.validate = function( formAttributes ) {
+ var ret = [],
+ proposedAlt = formAttributes.alt + '';
+
+ if ( !proposedAlt ) {
+ ret.push( this.lang.errorEmpty );
+ }
+
+ if ( !ret.length ) {
+ ret = ImgAlt.prototype.validate.call( this, formAttributes );
+ }
+
+ return ret;
+ };
+
+ ImgAltNonEmpty.prototype.lang = {"altLabel":"Alternativtext","errorTooLong":"Der Alternativtext ist zu lang. Er sollte {limit} Zeichen lang sein, ist aber aktuell {length} Zeichen lang","errorWhitespace":"Der Alternativtext kann nicht nur Leerzeichen enthalten","errorSameAsFileName":"Der Alternativtext sollte nicht dem Dateinamen entsprechen","errorEmpty":"Der Alternativtext sollte nicht leer sein"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'de/ImgAltNonEmpty', ImgAltNonEmpty );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/de/LocalizedRepository.js b/plugins/ckeditor/a11ychecker/quickfix/de/LocalizedRepository.js
new file mode 100644
index 0000000..6c23482
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/de/LocalizedRepository.js
@@ -0,0 +1,174 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+define( [ 'quickfix/Repository' ], function( Repository ) {
+ 'use strict';
+
+ /**
+ * This type adds localization support for repository.
+ *
+ * @mixins CKEDITOR.event
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @constructor
+ * @param {String} basePath A path to the directory where QuickFix classes are
+ * stored.
+ */
+ function LocalizedRepository( basePath ) {
+ Repository.call( this, basePath );
+ }
+
+ LocalizedRepository.prototype = new Repository();
+ LocalizedRepository.prototype.constructor = LocalizedRepository;
+
+ LocalizedRepository.prototype._langDictionary = {};
+
+ // An array of arguments from calls that were deferred.
+ var deferredGetCalls = {},
+ languagesRequested = [];
+
+ /**
+ * See {@link CKEDITOR.plugins.a11ychecker.quickFix.Repository#get}. This implementation
+ * adds only `options.langCode` param:
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.LocalizedRepository
+ * @param {Object} options
+ * @param {String} options.langCode Language code of quickFix to be loaded.
+ * @returns {Function}
+ */
+ LocalizedRepository.prototype.get = function( options ) {
+ options.langCode = options.langCode || 'en';
+
+ if ( this.deferGetCall( options.langCode, arguments ) ) {
+ // Call should be deferred, because no lang is available yet.
+ return;
+ }
+
+ if ( !CKEDITOR.plugins.a11ychecker.dev ) {
+ // In case of release code we'll do a trick here.
+ // Each class will be represented as '/' string, that way we
+ // can load multiple language combination with given class.
+ options.name = options.langCode + '/' + options.name;
+ }
+
+ // If lang is available call to the base class.
+ return Repository.prototype.get.call( this, options );
+ };
+
+ /**
+ * Similar to {@link #get} but returns localized instance rather than class.
+ *
+ * Please note that options.callback is mandatory.
+ *
+ * @todo: this method should be also available in generic class.
+ */
+ LocalizedRepository.prototype.getInstance = function( options ) {
+ options = options || {};
+ var name = options.name,
+ langCode = options.langCode || 'en',
+ that = this;
+
+ this.get( {
+ name: name,
+ callback: function( QuickFixType ) {
+ // This callback is guaranteed to be called when dictionary for langCode is fetched.
+ var instance = new QuickFixType( options.issue );
+
+ if ( CKEDITOR.plugins.a11ychecker.dev ) {
+ // We only need to assign lang for dev version, built class will already have this property.
+ instance.lang = that._langDictionary[ langCode ][ name ];
+ }
+
+ options.callback( instance );
+ },
+ langCode: langCode
+ } );
+ };
+
+
+ /**
+ * If needed will defer {@link #get} call.
+ *
+ * @returns {Boolean} `true` if call was deferred, `false` otherwise.
+ */
+ LocalizedRepository.prototype.deferGetCall = function( langCode, getArguments ) {
+ var indexOf = CKEDITOR.tools.indexOf;
+ if ( !CKEDITOR.plugins.a11ychecker.dev || this._langDictionary[ langCode ] ) {
+ // Deferring is always disabled in built version, and if _langDictionary is already
+ // loaded.
+ return false;
+ }
+
+ this._addDeferredGet( langCode, getArguments );
+
+ if ( indexOf( languagesRequested, langCode ) === -1 ) {
+ // This particular language was not requested yet.
+ languagesRequested.push( langCode );
+ CKEDITOR.scriptLoader.load( this.basePath + 'lang/' + langCode + '.js' );
+ }
+
+ return true;
+ };
+
+ /**
+ * Registers a class of given QuickFix.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.LocalizedRepository
+ * @param {String} name QuickFix name.
+ * @param {Function} cls QuickFix type.
+ */
+ LocalizedRepository.prototype.add = function( name, cls ) {
+ return Repository.prototype.add.call( this, name, cls );
+ };
+
+ /**
+ * Method to register language dictionary for developer version.
+ *
+ * In built version languages are already inlined into a QuickFix class file, so there's
+ * no need to execute it.
+ *
+ * @param {Object} dictionary
+ */
+ LocalizedRepository.prototype.lang = function( langCode, dictionary ) {
+ this._langDictionary[ langCode ] = dictionary;
+
+ var getQueue = deferredGetCalls[ langCode ];
+
+ if ( !getQueue ) {
+ // No get calls were queued for that language.
+ return;
+ }
+
+ // All deferred gets should be called in reversed order.
+ for ( var i = getQueue.length - 1; i >= 0; i-- ) {
+ this.get.apply( this, getQueue[ i ] );
+ }
+ };
+
+ LocalizedRepository.prototype._addDeferredGet = function( langCode, getArguments ) {
+ if ( deferredGetCalls[ langCode ] ) {
+ deferredGetCalls[ langCode ].push( getArguments );
+ } else {
+ deferredGetCalls[ langCode ] = [ getArguments ];
+ }
+ };
+
+
+ /**
+ * Function created for tests, returns count of deferred get functions.
+ *
+ * @returns {Number}
+ */
+ LocalizedRepository.prototype._getDeferredGetCount = function( langCode ) {
+ return deferredGetCalls[ langCode ] ? deferredGetCalls[ langCode ].length : 0;
+ };
+
+ /**
+ * Function created for tests, clears deferred get queue.
+ */
+ LocalizedRepository.prototype._clearDeferredGetQueue = function() {
+ deferredGetCalls = {};
+ };
+
+ return LocalizedRepository;
+} );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/de/ParagraphToHeader.js b/plugins/ckeditor/a11ychecker/quickfix/de/ParagraphToHeader.js
new file mode 100644
index 0000000..ff7c804
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/de/ParagraphToHeader.js
@@ -0,0 +1,168 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'de',
+ name: 'ElementReplace',
+ callback: function( ElementReplace ) {
+ /**
+ * Replaces provided element with element that a different tag name, preserving its children.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class ParagraphToHeader
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue
+ */
+ function ParagraphToHeader( issue ) {
+ ElementReplace.call( this, issue );
+ }
+
+ ParagraphToHeader.prototype = new ElementReplace();
+ ParagraphToHeader.prototype.constructor = ParagraphToHeader;
+
+ ParagraphToHeader.prototype.getTargetName = function( formAttributes ) {
+ return formAttributes.level;
+ };
+
+ ParagraphToHeader.prototype.display = function( form, editor ) {
+
+ var levelDict = this._getFormHeaderLeves( editor );
+
+ form.setInputs( {
+ level: {
+ type: 'select',
+ label: this.lang.levelLabel,
+ value: 'h' + this._getPreferredLevel( editor ),
+ options: levelDict
+ }
+ } );
+ };
+
+ ParagraphToHeader.prototype.fix = function( formAttributes, callback ) {
+ var that = this;
+ ElementReplace.prototype.fix.call( this, formAttributes, function() {
+ that._removeBoldTag();
+ callback( that );
+ } );
+ };
+
+ /**
+ * Determines preferred heading level for the header that should be cerated.
+ *
+ * @private
+ * @param {CKEDITOR.editor} editor
+ * @returns {Number} Number ranging from `1` to `6`.
+ */
+ ParagraphToHeader.prototype._getPreferredLevel = function( editor ) {
+ var ret = 1,
+ editable = editor.editable(),
+ headerTagRegExp = /^h[1-6]$/i,
+ range = new CKEDITOR.dom.range( editable.getDocument() ),
+ walker,
+ prevElement;
+
+ range.setStartAt( editable, CKEDITOR.POSITION_AFTER_START );
+ range.setEndAt( this.issue.element, CKEDITOR.POSITION_BEFORE_START );
+ walker = new CKEDITOR.dom.walker( range );
+
+ while ( ( prevElement = walker.previous() ) ) {
+ if ( prevElement.getName && prevElement.getName().match( headerTagRegExp ) ) {
+ ret = Number( prevElement.getName()[ 1 ] ) + 1;
+ break;
+ }
+ }
+
+ // WE can't return a higher value than 7.
+ return Math.min( ret, 6 );
+ };
+
+ /**
+ * This method check if issue element contains `` element only as a first and the only child.
+ * If so we'll remove it, but move its children to the `issue.element`.
+ */
+ ParagraphToHeader.prototype._removeBoldTag = function() {
+ var isElementEvaluator = function( el ) {
+ return el.type === CKEDITOR.NODE_ELEMENT;
+ },
+ elem = this.issue.element,
+ innerElement = elem.getFirst( isElementEvaluator ),
+ // If first child element is at the same time last element child, then it means it has only this element.
+ hasSingleElement = innerElement && innerElement.equals( elem.getLast( isElementEvaluator ) ),
+ suspiciousTagNames = [ 'strong', 'b' ];
+
+ if ( hasSingleElement && CKEDITOR.tools.indexOf( suspiciousTagNames, innerElement.getName() ) !== -1 ) {
+ innerElement.moveChildren( elem );
+ innerElement.remove();
+ }
+ };
+
+ /**
+ * Returns minimal and maximal possible header levels for given editor.
+ *
+ * Result will be based on ACF and `config.format_tags`.
+ *
+ * @param {CKEDITOR.editor}
+ * @return {Object} Allowed header level boundaries.
+ * @return {Number} return.min Minimal allowed level.
+ * @return {Number} return.email Maximal allowed level.
+ */
+ ParagraphToHeader.prototype._getPossibleLevels = function( editor ) {
+ var tags = ( editor.config.format_tags || '' ).split( ';' ),
+ ret = {
+ min: 1,
+ max: 6
+ },
+ i;
+
+ // Filtering tags.
+ for ( i = tags.length - 1; i >= 0; i-- ) {
+ // If given tag is not header tag or if it's not allowed by the ACF.
+ if ( !tags[ i ].match( /^h[1-6]$/i ) || !editor.filter.check( tags[ i ] ) ) {
+ tags.splice( i, 1 );
+ } else {
+ tags[ i ] = Number( tags[ i ][ 1 ] );
+ }
+ }
+
+ if ( tags.length ) {
+ // Note if IE8 has to be supported we need to inline sorting here.
+ tags.sort();
+
+ ret.min = tags[ 0 ];
+ ret.max = tags[ tags.length - 1 ];
+ }
+
+ return ret;
+ };
+
+ /**
+ * Returns options dictionary that should be put in form header level select.
+ *
+ * @param {CKEDITOR.editor} editor
+ */
+ ParagraphToHeader.prototype._getFormHeaderLeves = function( editor ) {
+ var dict = {},
+ boundaries = this._getPossibleLevels( editor ),
+ preferredLevel = this._getPreferredLevel( editor );
+
+ for ( var i = boundaries.min; i <= boundaries.max; i++ ) {
+ dict[ 'h' + i ] = 'H' + i;
+ }
+
+ if ( dict[ 'h' + preferredLevel ] ) {
+ dict[ 'h' + preferredLevel ] += ( ' ' + this.lang.suggested );
+ }
+
+ return dict;
+ };
+
+
+ ParagraphToHeader.prototype.lang = {"levelLabel":"Überschriftenebene","suggested":"(Vorschlag)"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'de/ParagraphToHeader', ParagraphToHeader );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/de/QuickFix.js b/plugins/ckeditor/a11ychecker/quickfix/de/QuickFix.js
new file mode 100644
index 0000000..e05c0ca
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/de/QuickFix.js
@@ -0,0 +1,90 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+(function() {
+ 'use strict';
+
+ /**
+ * QuickFix type for the QuickFix objects.
+ *
+ * # Overview
+ *
+ * It encapsulates logic responsible for fixing Accessibility issue.
+ *
+ * ## Working with QuickFix objects
+ *
+ * ### Adding controls to the QuickFix form
+ *
+ * Controls can be added in {@link #display} method using {@link CKEDITOR.plugins.a11ychecker.ViewerForm}
+ * methods.
+ *
+ * ### Executing the fix
+ *
+ * The fixing logic is placed in {@link #fix} method, so you need to simply call it when
+ * you're sure to apply the fix.
+ *
+ * @since 4.6.0
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class QuickFix
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function QuickFix( issue ) {
+ this.issue = issue;
+ }
+
+ QuickFix.prototype = {
+ /**
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.QuickFix
+ * @property {CKEDITOR.plugins.a11ychecker.Issue} issue Issue object that QuickFix was created for.
+ */
+ issue: null
+ };
+
+ QuickFix.prototype.constructor = QuickFix;
+
+ QuickFix.prototype.display = function( form, editor ) {
+ };
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ QuickFix.prototype.fix = function( formAttributes, callback ) {
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ /**
+ * Method used to validate data placed in form.
+ *
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @returns {String[]} Array of error messages. If array is empty, then it means no errors ocurred.
+ */
+ QuickFix.prototype.validate = function( formAttributes ) {
+ return [];
+ };
+
+ /**
+ * A method called to mark the selection on object before quickfix is applied.
+ *
+ * @param {CKEDITOR.dom.selection} selection Editor selection.
+ */
+ QuickFix.prototype.markSelection = function( editor, selection ) {
+ var rng = editor.createRange();
+ rng.setStartBefore( this.issue.element );
+ rng.setEndAfter( this.issue.element );
+ selection.selectRanges( [ rng ] );
+ };
+
+ QuickFix.prototype.lang = {};
+
+ QuickFix.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'de/QuickFix', QuickFix );
+}());
diff --git a/plugins/ckeditor/a11ychecker/quickfix/de/TableHeaders.js b/plugins/ckeditor/a11ychecker/quickfix/de/TableHeaders.js
new file mode 100644
index 0000000..f3830c9
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/de/TableHeaders.js
@@ -0,0 +1,98 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'de',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * QuickFix adding a caption in the `table` element.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class TableHeaders
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function TableHeaders( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ TableHeaders.prototype = new QuickFix();
+
+ TableHeaders.prototype.constructor = TableHeaders;
+
+ TableHeaders.prototype.display = function( form ) {
+ var lang = this.lang;
+
+ form.setInputs( {
+ position: {
+ type: 'select',
+ label: lang.positionLabel,
+ value: 'row',
+ options: {
+ 'both': lang.positionBoth,
+ 'row': lang.positionHorizontally,
+ 'col': lang.positionVertically
+ }
+ }
+ } );
+ };
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ TableHeaders.prototype.fix = function( formAttributes, callback ) {
+ var table = this.issue.element,
+ headers = formAttributes.position,
+ newCell,
+ row,
+ i;
+ // Following code copied from CKEditor plugins/table/dialogs/table.js file.
+
+ // Should we make all first cells in a row TH?
+ if ( headers == 'col' || headers == 'both' ) {
+ for ( row = 0; row < table.$.rows.length; row++ ) {
+ if ( !table.$.rows[ row ].cells.length ) {
+ continue;
+ }
+
+ newCell = new CKEDITOR.dom.element( table.$.rows[ row ].cells[ 0 ] );
+ newCell.renameNode( 'th' );
+ newCell.setAttribute( 'scope', 'row' );
+ }
+ }
+
+ if ( !table.$.tHead && ( headers == 'row' || headers == 'both' ) ) {
+ var thead = new CKEDITOR.dom.element( table.$.createTHead() );
+ var tbody = table.getElementsByTag( 'tbody' ).getItem( 0 );
+ var theRow = tbody.getElementsByTag( 'tr' ).getItem( 0 );
+
+ // Change TD to TH:
+ for ( i = 0; i < theRow.getChildCount(); i++ ) {
+ var th = theRow.getChild( i );
+ // Skip bookmark nodes. (#6155)
+ if ( th.type == CKEDITOR.NODE_ELEMENT && !th.data( 'cke-bookmark' ) ) {
+ th.renameNode( 'th' );
+ th.setAttribute( 'scope', 'col' );
+ }
+ }
+ thead.append( theRow.remove() );
+ }
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ TableHeaders.prototype.lang = {"positionLabel":"Position","positionHorizontally":"Horizontal","positionVertically":"Vertikal","positionBoth":"Beide"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'de/TableHeaders', TableHeaders );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/en/AddTableCaption.js b/plugins/ckeditor/a11ychecker/quickfix/en/AddTableCaption.js
new file mode 100644
index 0000000..ca1456c
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/en/AddTableCaption.js
@@ -0,0 +1,75 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'en',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+
+ var emptyWhitespaceRegExp = /^[\s\n\r]+$/g;
+
+ /**
+ * QuickFix adding a caption in the `table` element.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class AddTableCaption
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function AddTableCaption( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ AddTableCaption.prototype = new QuickFix();
+
+ AddTableCaption.prototype.constructor = AddTableCaption;
+
+ AddTableCaption.prototype.display = function( form ) {
+ form.setInputs( {
+ caption: {
+ type: 'text',
+ label: this.lang.captionLabel
+ }
+ } );
+ };
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ AddTableCaption.prototype.fix = function( formAttributes, callback ) {
+ var issueElement = this.issue.element,
+ caption = issueElement.getDocument().createElement( 'caption' );
+
+ caption.setHtml( formAttributes.caption );
+ // Prepend the caption.
+ issueElement.append( caption, true );
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ AddTableCaption.prototype.validate = function( formAttributes ) {
+ var proposedCaption = formAttributes.caption,
+ ret = [];
+
+ // Test if the caption has only whitespaces.
+ if ( !proposedCaption || proposedCaption.match( emptyWhitespaceRegExp ) ) {
+ ret.push( this.lang.errorEmpty );
+ }
+
+ return ret;
+ };
+
+ AddTableCaption.prototype.lang = {"captionLabel":"Caption","errorEmpty":"Caption text can not be empty"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'en/AddTableCaption', AddTableCaption );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/en/AnchorsMerge.js b/plugins/ckeditor/a11ychecker/quickfix/en/AnchorsMerge.js
new file mode 100644
index 0000000..7dc73f6
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/en/AnchorsMerge.js
@@ -0,0 +1,80 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'en',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * QuickFix merging two or more sibling anchors with the same href.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class AnchorsMerge
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function AnchorsMerge( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ AnchorsMerge.prototype = new QuickFix();
+
+ AnchorsMerge.prototype.constructor = AnchorsMerge;
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ AnchorsMerge.prototype.fix = function( formAttributes, callback ) {
+ var issueElement = this.issue.element,
+ nextSibling = issueElement.getNext(),
+ initialHref = issueElement.getAttribute( 'href' ),
+ extraInnerHtml = '',
+ isWhitespace = function( node ) {
+ return node.type === CKEDITOR.NODE_TEXT && node.getText().match( /^[\s]*$/ );
+ },
+ iterationAllowed = function( node ) {
+ if ( !node ) {
+ return false;
+ }
+
+ // We only allow anchors that have the same href as the initial one
+ return ( node.getName && node.getName() == 'a' && nextSibling.getAttribute( 'href' ) == initialHref ) ||
+ isWhitespace( node ); // Or whitespace text nodes.
+ },
+ curNode;
+
+ while ( iterationAllowed( nextSibling ) ) {
+ curNode = nextSibling;
+
+ // This html will be added later on to the first anchor.
+ extraInnerHtml += isWhitespace( curNode ) ? curNode.getText() : curNode.getHtml();
+
+ // Prepare nextSibling var for next iteration.
+ nextSibling = curNode.getNext();
+
+ // And we can remove element safely.
+ curNode.remove();
+ }
+
+ // Adding extra html to first anchor.
+ if ( extraInnerHtml ) {
+ issueElement.setHtml( issueElement.getHtml() + extraInnerHtml );
+ }
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ AnchorsMerge.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'en/AnchorsMerge', AnchorsMerge );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/en/AttributeRename.js b/plugins/ckeditor/a11ychecker/quickfix/en/AttributeRename.js
new file mode 100644
index 0000000..f6501d0
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/en/AttributeRename.js
@@ -0,0 +1,86 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'en',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * QuickFix renaming an attribute {@link #attributeName} to another name
+ * {@link #attributeTargetName}.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class AttributeRename
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function AttributeRename( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ AttributeRename.prototype = new QuickFix();
+
+ AttributeRename.prototype.constructor = AttributeRename;
+
+ /**
+ * Name of the attribute to be renamed.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.AttributeRename
+ */
+ AttributeRename.prototype.attributeName = 'title';
+
+ /**
+ * A desired name for the attribute.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.AttributeRename
+ */
+ AttributeRename.prototype.attributeTargetName = 'alt';
+
+ /**
+ * Gets the proposed new value of the target attribute.
+ *
+ * @returns {String}
+ */
+ AttributeRename.prototype.getProposedValue = function() {
+ return this.issue.element.getAttribute( this.attributeName ) || '';
+ };
+
+ AttributeRename.prototype.display = function( form ) {
+ form.setInputs( {
+ value: {
+ type: 'text',
+ label: 'Value',
+ value: this.getProposedValue()
+ }
+ } );
+ };
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ AttributeRename.prototype.fix = function( formAttributes, callback ) {
+ var issueElement = this.issue.element,
+ desiredValue = formAttributes.value;
+
+ // Set desired attribute value.
+ issueElement.setAttribute( this.attributeTargetName, desiredValue );
+ // Unset the old attribute.
+ issueElement.removeAttribute( this.attributeName );
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ AttributeRename.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'en/AttributeRename', AttributeRename );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/en/AttributeRenameDefault.js b/plugins/ckeditor/a11ychecker/quickfix/en/AttributeRenameDefault.js
new file mode 100644
index 0000000..6740820
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/en/AttributeRenameDefault.js
@@ -0,0 +1,40 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'en',
+ name: 'AttributeRename',
+ callback: function( AttributeRename ) {
+ /**
+ * QuickFix renaming an attribute {@link #attributeName} to another name
+ * {@link #attributeTargetName} using a proposed default value
+ * based on the value of {@link #attributeTargetName}.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class AttributeRenameDefault
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function AttributeRenameDefault( issue ) {
+ AttributeRename.call( this, issue );
+ }
+
+ AttributeRenameDefault.prototype = new AttributeRename();
+
+ AttributeRenameDefault.prototype.constructor = AttributeRenameDefault;
+
+ AttributeRenameDefault.prototype.getProposedValue = function() {
+ var element = this.issue.element;
+ return element.getAttribute( this.attributeTargetName ) ||
+ element.getAttribute( this.attributeName ) || '';
+ };
+
+ AttributeRenameDefault.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'en/AttributeRenameDefault', AttributeRenameDefault );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/en/DateUnfold.js b/plugins/ckeditor/a11ychecker/quickfix/en/DateUnfold.js
new file mode 100644
index 0000000..7effe93
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/en/DateUnfold.js
@@ -0,0 +1,133 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'en',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ // List of month names.
+ var monthNames = {
+ en: [
+ 'January',
+ 'February',
+ 'March',
+ 'April',
+ 'May',
+ 'June',
+ 'July',
+ 'August',
+ 'September',
+ 'October',
+ 'November',
+ 'December'
+ ]
+ };
+
+ /**
+ * QuickFix converting short dates to more verbose format. Eg. convert 21-3-2030
+ * to 21 March 2030.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class DateUnfold
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function DateUnfold( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ DateUnfold.prototype = new QuickFix();
+
+ DateUnfold.prototype.constructor = DateUnfold;
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ DateUnfold.prototype.fix = function( formAttributes, callback ) {
+ var issueElement = this.issue.element,
+ innerText = issueElement.getText(),
+ that = this;
+
+ innerText = innerText.replace( /(\d{1,2}[.\/-]\d{1,2}[.\/-]\d{2,4})/g, function( occur ) {
+ var extractedDate = that.parseDate( occur );
+
+ return that.getFriendlyDate( extractedDate );
+ } );
+
+ issueElement.setText( innerText );
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ /**
+ * Parses given "short" data. Returns an object with 1-based values.
+ *
+ * Eg. 21.03.2020 would be parsed to:
+ *
+ * {
+ * day: "21",
+ * month: "03",
+ * year: "2020"
+ * }
+ *
+ * @returns {Object} An object containing properties:
+ * * day
+ * * month
+ * * year
+ */
+ DateUnfold.prototype.parseDate = function( dateString ) {
+ var ret = dateString.split( /[.\-\/]+/ );
+
+ return {
+ day: ret[ 0 ],
+ month: ret[ 1 ],
+ year: ret[ 2 ]
+ };
+ };
+
+ /**
+ * var ret = dateFix.getFriendlyDate( {
+ * day: "21",
+ * month: "03",
+ * year: "2020"
+ * } );
+ *
+ * // ret === "21 March 2020"
+ *
+ * @param {Object} An object returned by {@link #parseDate}
+ * @returns {String} A human-friendly date representation.
+ */
+ DateUnfold.prototype.getFriendlyDate = function( dateObj ) {
+ // month - 1 because monthNames is 0-based array.
+ var monthName = monthNames.en[ Number( dateObj.month - 1 ) ],
+ year = Number( dateObj.year );
+
+ // In case of 2 digit year value, lets fix it.
+ if ( year >= 0 && year < 100 ) {
+ // Year 70 and greater will be considered 19xx.
+ if ( year >= 70 ) {
+ year += 1900;
+ } else {
+ // Otherwise we assume it's 20xx.
+ year += 2000;
+ }
+ }
+
+ // Cast day to Number, to remove leading 0.
+ return [ Number( dateObj.day ), monthName, year ].join( ' ' );
+ };
+
+ DateUnfold.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'en/DateUnfold', DateUnfold );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/en/ElementRemove.js b/plugins/ckeditor/a11ychecker/quickfix/en/ElementRemove.js
new file mode 100644
index 0000000..d3d135e
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/en/ElementRemove.js
@@ -0,0 +1,43 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'en',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * The ultimate fix for unsolvable problem - removing an element.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class ElementRemove
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue
+ */
+ function ElementRemove( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ ElementRemove.prototype = new QuickFix();
+ ElementRemove.prototype.constructor = ElementRemove;
+
+ ElementRemove.prototype.display = function( form ) {
+ form.setInputs( {} );
+ };
+
+ ElementRemove.prototype.fix = function( formAttributes, callback ) {
+ this.issue.element.remove();
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ ElementRemove.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'en/ElementRemove', ElementRemove );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/en/ElementReplace.js b/plugins/ckeditor/a11ychecker/quickfix/en/ElementReplace.js
new file mode 100644
index 0000000..3f60e12
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/en/ElementReplace.js
@@ -0,0 +1,59 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'en',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * Replaces provided element with element that a different tag name, preserving its children.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class ElementReplace
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue
+ */
+ function ElementReplace( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ ElementReplace.prototype = new QuickFix();
+ ElementReplace.prototype.constructor = ElementReplace;
+
+ /**
+ * Returns the name of the tag that issue.element should be converted to.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.ElementReplace
+ * @param {Object} formAttributes Form attributes from {@link #fix}.
+ * @returns {String}
+ */
+ ElementReplace.prototype.getTargetName = function( formAttributes ) {
+ return 'h1';
+ };
+
+ ElementReplace.prototype.display = function( form ) {
+ form.setInputs( {} );
+ };
+
+ ElementReplace.prototype.fix = function( formAttributes, callback ) {
+ var newElement = new CKEDITOR.dom.element( this.getTargetName( formAttributes ) );
+
+ newElement.replace( this.issue.element );
+ this.issue.element.moveChildren( newElement );
+
+ this.issue.element = newElement;
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ ElementReplace.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'en/ElementReplace', ElementReplace );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/en/ImgAlt.js b/plugins/ckeditor/a11ychecker/quickfix/en/ImgAlt.js
new file mode 100644
index 0000000..2ea8023
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/en/ImgAlt.js
@@ -0,0 +1,89 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'en',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+
+ var emptyWhitespaceRegExp = /^[\s\n\r]+$/g;
+
+ /**
+ * Fixes the image with missing alt attribute.
+ *
+ * @constructor
+ */
+ function ImgAlt( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ /**
+ * Maximal count of characters in the alt. It might be changed to `0` to prevent
+ * length validation.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.AttributeRename
+ * @static
+ */
+ ImgAlt.altLengthLimit = 100;
+
+ ImgAlt.prototype = new QuickFix();
+ ImgAlt.prototype.constructor = ImgAlt;
+
+ ImgAlt.prototype.display = function( form ) {
+ form.setInputs( {
+ alt: {
+ type: 'text',
+ label: this.lang.altLabel,
+ value: this.issue.element.getAttribute( 'alt' ) || ''
+ }
+ } );
+ };
+
+ ImgAlt.prototype.fix = function( formAttributes, callback ) {
+ this.issue.element.setAttribute( 'alt', formAttributes.alt );
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ ImgAlt.prototype.validate = function( formAttributes ) {
+ var ret = [],
+ proposedAlt = formAttributes.alt + '',
+ imgElem = this.issue && this.issue.element,
+ lang = this.lang;
+
+ // Test if the alt has only whitespaces.
+ if ( proposedAlt.match( emptyWhitespaceRegExp ) ) {
+ ret.push( lang.errorWhitespace );
+ }
+
+ // Testing against exceeding max length.
+ if ( ImgAlt.altLengthLimit && proposedAlt.length > ImgAlt.altLengthLimit ) {
+ var errorTemplate = new CKEDITOR.template( lang.errorTooLong );
+
+ ret.push( errorTemplate.output( {
+ limit: ImgAlt.altLengthLimit,
+ length: proposedAlt.length
+ } ) );
+ }
+
+ if ( imgElem ) {
+ var fileName = String( imgElem.getAttribute( 'src' ) ).split( '/' ).pop();
+ if ( fileName == proposedAlt ) {
+ ret.push( lang.errorSameAsFileName );
+ }
+ }
+
+ return ret;
+ };
+
+ ImgAlt.prototype.lang = {"altLabel":"Alternative text","errorTooLong":"Alternative text is too long. It should be up to {limit} characters while your has {length}","errorWhitespace":"Alternative text can not only contain whitespace characters","errorSameAsFileName":"Image alt should not be the same as the file name"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'en/ImgAlt', ImgAlt );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/en/ImgAltNonEmpty.js b/plugins/ckeditor/a11ychecker/quickfix/en/ImgAltNonEmpty.js
new file mode 100644
index 0000000..0af9b4c
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/en/ImgAltNonEmpty.js
@@ -0,0 +1,44 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'en',
+ name: 'ImgAlt',
+ callback: function( ImgAlt ) {
+
+ /**
+ * Fixes the image with missing alt attribute, requiring non-empty alt.
+ *
+ * @constructor
+ */
+ function ImgAltNonEmpty( issue ) {
+ ImgAlt.call( this, issue );
+ }
+
+ ImgAltNonEmpty.prototype = new ImgAlt();
+ ImgAltNonEmpty.prototype.constructor = ImgAltNonEmpty;
+
+ ImgAltNonEmpty.prototype.validate = function( formAttributes ) {
+ var ret = [],
+ proposedAlt = formAttributes.alt + '';
+
+ if ( !proposedAlt ) {
+ ret.push( this.lang.errorEmpty );
+ }
+
+ if ( !ret.length ) {
+ ret = ImgAlt.prototype.validate.call( this, formAttributes );
+ }
+
+ return ret;
+ };
+
+ ImgAltNonEmpty.prototype.lang = {"altLabel":"Alternative text","errorTooLong":"Alternative text is too long. It should be up to {limit} characters while your has {length}","errorWhitespace":"Alternative text can not only contain whitespace characters","errorSameAsFileName":"Image alt should not be the same as the file name","errorEmpty":"Alternative text can not be empty"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'en/ImgAltNonEmpty', ImgAltNonEmpty );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/en/LocalizedRepository.js b/plugins/ckeditor/a11ychecker/quickfix/en/LocalizedRepository.js
new file mode 100644
index 0000000..6c23482
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/en/LocalizedRepository.js
@@ -0,0 +1,174 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+define( [ 'quickfix/Repository' ], function( Repository ) {
+ 'use strict';
+
+ /**
+ * This type adds localization support for repository.
+ *
+ * @mixins CKEDITOR.event
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @constructor
+ * @param {String} basePath A path to the directory where QuickFix classes are
+ * stored.
+ */
+ function LocalizedRepository( basePath ) {
+ Repository.call( this, basePath );
+ }
+
+ LocalizedRepository.prototype = new Repository();
+ LocalizedRepository.prototype.constructor = LocalizedRepository;
+
+ LocalizedRepository.prototype._langDictionary = {};
+
+ // An array of arguments from calls that were deferred.
+ var deferredGetCalls = {},
+ languagesRequested = [];
+
+ /**
+ * See {@link CKEDITOR.plugins.a11ychecker.quickFix.Repository#get}. This implementation
+ * adds only `options.langCode` param:
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.LocalizedRepository
+ * @param {Object} options
+ * @param {String} options.langCode Language code of quickFix to be loaded.
+ * @returns {Function}
+ */
+ LocalizedRepository.prototype.get = function( options ) {
+ options.langCode = options.langCode || 'en';
+
+ if ( this.deferGetCall( options.langCode, arguments ) ) {
+ // Call should be deferred, because no lang is available yet.
+ return;
+ }
+
+ if ( !CKEDITOR.plugins.a11ychecker.dev ) {
+ // In case of release code we'll do a trick here.
+ // Each class will be represented as '/' string, that way we
+ // can load multiple language combination with given class.
+ options.name = options.langCode + '/' + options.name;
+ }
+
+ // If lang is available call to the base class.
+ return Repository.prototype.get.call( this, options );
+ };
+
+ /**
+ * Similar to {@link #get} but returns localized instance rather than class.
+ *
+ * Please note that options.callback is mandatory.
+ *
+ * @todo: this method should be also available in generic class.
+ */
+ LocalizedRepository.prototype.getInstance = function( options ) {
+ options = options || {};
+ var name = options.name,
+ langCode = options.langCode || 'en',
+ that = this;
+
+ this.get( {
+ name: name,
+ callback: function( QuickFixType ) {
+ // This callback is guaranteed to be called when dictionary for langCode is fetched.
+ var instance = new QuickFixType( options.issue );
+
+ if ( CKEDITOR.plugins.a11ychecker.dev ) {
+ // We only need to assign lang for dev version, built class will already have this property.
+ instance.lang = that._langDictionary[ langCode ][ name ];
+ }
+
+ options.callback( instance );
+ },
+ langCode: langCode
+ } );
+ };
+
+
+ /**
+ * If needed will defer {@link #get} call.
+ *
+ * @returns {Boolean} `true` if call was deferred, `false` otherwise.
+ */
+ LocalizedRepository.prototype.deferGetCall = function( langCode, getArguments ) {
+ var indexOf = CKEDITOR.tools.indexOf;
+ if ( !CKEDITOR.plugins.a11ychecker.dev || this._langDictionary[ langCode ] ) {
+ // Deferring is always disabled in built version, and if _langDictionary is already
+ // loaded.
+ return false;
+ }
+
+ this._addDeferredGet( langCode, getArguments );
+
+ if ( indexOf( languagesRequested, langCode ) === -1 ) {
+ // This particular language was not requested yet.
+ languagesRequested.push( langCode );
+ CKEDITOR.scriptLoader.load( this.basePath + 'lang/' + langCode + '.js' );
+ }
+
+ return true;
+ };
+
+ /**
+ * Registers a class of given QuickFix.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.LocalizedRepository
+ * @param {String} name QuickFix name.
+ * @param {Function} cls QuickFix type.
+ */
+ LocalizedRepository.prototype.add = function( name, cls ) {
+ return Repository.prototype.add.call( this, name, cls );
+ };
+
+ /**
+ * Method to register language dictionary for developer version.
+ *
+ * In built version languages are already inlined into a QuickFix class file, so there's
+ * no need to execute it.
+ *
+ * @param {Object} dictionary
+ */
+ LocalizedRepository.prototype.lang = function( langCode, dictionary ) {
+ this._langDictionary[ langCode ] = dictionary;
+
+ var getQueue = deferredGetCalls[ langCode ];
+
+ if ( !getQueue ) {
+ // No get calls were queued for that language.
+ return;
+ }
+
+ // All deferred gets should be called in reversed order.
+ for ( var i = getQueue.length - 1; i >= 0; i-- ) {
+ this.get.apply( this, getQueue[ i ] );
+ }
+ };
+
+ LocalizedRepository.prototype._addDeferredGet = function( langCode, getArguments ) {
+ if ( deferredGetCalls[ langCode ] ) {
+ deferredGetCalls[ langCode ].push( getArguments );
+ } else {
+ deferredGetCalls[ langCode ] = [ getArguments ];
+ }
+ };
+
+
+ /**
+ * Function created for tests, returns count of deferred get functions.
+ *
+ * @returns {Number}
+ */
+ LocalizedRepository.prototype._getDeferredGetCount = function( langCode ) {
+ return deferredGetCalls[ langCode ] ? deferredGetCalls[ langCode ].length : 0;
+ };
+
+ /**
+ * Function created for tests, clears deferred get queue.
+ */
+ LocalizedRepository.prototype._clearDeferredGetQueue = function() {
+ deferredGetCalls = {};
+ };
+
+ return LocalizedRepository;
+} );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/en/ParagraphToHeader.js b/plugins/ckeditor/a11ychecker/quickfix/en/ParagraphToHeader.js
new file mode 100644
index 0000000..892d075
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/en/ParagraphToHeader.js
@@ -0,0 +1,168 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'en',
+ name: 'ElementReplace',
+ callback: function( ElementReplace ) {
+ /**
+ * Replaces provided element with element that a different tag name, preserving its children.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class ParagraphToHeader
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue
+ */
+ function ParagraphToHeader( issue ) {
+ ElementReplace.call( this, issue );
+ }
+
+ ParagraphToHeader.prototype = new ElementReplace();
+ ParagraphToHeader.prototype.constructor = ParagraphToHeader;
+
+ ParagraphToHeader.prototype.getTargetName = function( formAttributes ) {
+ return formAttributes.level;
+ };
+
+ ParagraphToHeader.prototype.display = function( form, editor ) {
+
+ var levelDict = this._getFormHeaderLeves( editor );
+
+ form.setInputs( {
+ level: {
+ type: 'select',
+ label: this.lang.levelLabel,
+ value: 'h' + this._getPreferredLevel( editor ),
+ options: levelDict
+ }
+ } );
+ };
+
+ ParagraphToHeader.prototype.fix = function( formAttributes, callback ) {
+ var that = this;
+ ElementReplace.prototype.fix.call( this, formAttributes, function() {
+ that._removeBoldTag();
+ callback( that );
+ } );
+ };
+
+ /**
+ * Determines preferred heading level for the header that should be cerated.
+ *
+ * @private
+ * @param {CKEDITOR.editor} editor
+ * @returns {Number} Number ranging from `1` to `6`.
+ */
+ ParagraphToHeader.prototype._getPreferredLevel = function( editor ) {
+ var ret = 1,
+ editable = editor.editable(),
+ headerTagRegExp = /^h[1-6]$/i,
+ range = new CKEDITOR.dom.range( editable.getDocument() ),
+ walker,
+ prevElement;
+
+ range.setStartAt( editable, CKEDITOR.POSITION_AFTER_START );
+ range.setEndAt( this.issue.element, CKEDITOR.POSITION_BEFORE_START );
+ walker = new CKEDITOR.dom.walker( range );
+
+ while ( ( prevElement = walker.previous() ) ) {
+ if ( prevElement.getName && prevElement.getName().match( headerTagRegExp ) ) {
+ ret = Number( prevElement.getName()[ 1 ] ) + 1;
+ break;
+ }
+ }
+
+ // WE can't return a higher value than 7.
+ return Math.min( ret, 6 );
+ };
+
+ /**
+ * This method check if issue element contains `` element only as a first and the only child.
+ * If so we'll remove it, but move its children to the `issue.element`.
+ */
+ ParagraphToHeader.prototype._removeBoldTag = function() {
+ var isElementEvaluator = function( el ) {
+ return el.type === CKEDITOR.NODE_ELEMENT;
+ },
+ elem = this.issue.element,
+ innerElement = elem.getFirst( isElementEvaluator ),
+ // If first child element is at the same time last element child, then it means it has only this element.
+ hasSingleElement = innerElement && innerElement.equals( elem.getLast( isElementEvaluator ) ),
+ suspiciousTagNames = [ 'strong', 'b' ];
+
+ if ( hasSingleElement && CKEDITOR.tools.indexOf( suspiciousTagNames, innerElement.getName() ) !== -1 ) {
+ innerElement.moveChildren( elem );
+ innerElement.remove();
+ }
+ };
+
+ /**
+ * Returns minimal and maximal possible header levels for given editor.
+ *
+ * Result will be based on ACF and `config.format_tags`.
+ *
+ * @param {CKEDITOR.editor}
+ * @return {Object} Allowed header level boundaries.
+ * @return {Number} return.min Minimal allowed level.
+ * @return {Number} return.email Maximal allowed level.
+ */
+ ParagraphToHeader.prototype._getPossibleLevels = function( editor ) {
+ var tags = ( editor.config.format_tags || '' ).split( ';' ),
+ ret = {
+ min: 1,
+ max: 6
+ },
+ i;
+
+ // Filtering tags.
+ for ( i = tags.length - 1; i >= 0; i-- ) {
+ // If given tag is not header tag or if it's not allowed by the ACF.
+ if ( !tags[ i ].match( /^h[1-6]$/i ) || !editor.filter.check( tags[ i ] ) ) {
+ tags.splice( i, 1 );
+ } else {
+ tags[ i ] = Number( tags[ i ][ 1 ] );
+ }
+ }
+
+ if ( tags.length ) {
+ // Note if IE8 has to be supported we need to inline sorting here.
+ tags.sort();
+
+ ret.min = tags[ 0 ];
+ ret.max = tags[ tags.length - 1 ];
+ }
+
+ return ret;
+ };
+
+ /**
+ * Returns options dictionary that should be put in form header level select.
+ *
+ * @param {CKEDITOR.editor} editor
+ */
+ ParagraphToHeader.prototype._getFormHeaderLeves = function( editor ) {
+ var dict = {},
+ boundaries = this._getPossibleLevels( editor ),
+ preferredLevel = this._getPreferredLevel( editor );
+
+ for ( var i = boundaries.min; i <= boundaries.max; i++ ) {
+ dict[ 'h' + i ] = 'H' + i;
+ }
+
+ if ( dict[ 'h' + preferredLevel ] ) {
+ dict[ 'h' + preferredLevel ] += ( ' ' + this.lang.suggested );
+ }
+
+ return dict;
+ };
+
+
+ ParagraphToHeader.prototype.lang = {"levelLabel":"Header level","suggested":"(Suggested)"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'en/ParagraphToHeader', ParagraphToHeader );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/en/QuickFix.js b/plugins/ckeditor/a11ychecker/quickfix/en/QuickFix.js
new file mode 100644
index 0000000..ed2e47b
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/en/QuickFix.js
@@ -0,0 +1,90 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+(function() {
+ 'use strict';
+
+ /**
+ * QuickFix type for the QuickFix objects.
+ *
+ * # Overview
+ *
+ * It encapsulates logic responsible for fixing Accessibility issue.
+ *
+ * ## Working with QuickFix objects
+ *
+ * ### Adding controls to the QuickFix form
+ *
+ * Controls can be added in {@link #display} method using {@link CKEDITOR.plugins.a11ychecker.ViewerForm}
+ * methods.
+ *
+ * ### Executing the fix
+ *
+ * The fixing logic is placed in {@link #fix} method, so you need to simply call it when
+ * you're sure to apply the fix.
+ *
+ * @since 4.6.0
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class QuickFix
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function QuickFix( issue ) {
+ this.issue = issue;
+ }
+
+ QuickFix.prototype = {
+ /**
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.QuickFix
+ * @property {CKEDITOR.plugins.a11ychecker.Issue} issue Issue object that QuickFix was created for.
+ */
+ issue: null
+ };
+
+ QuickFix.prototype.constructor = QuickFix;
+
+ QuickFix.prototype.display = function( form, editor ) {
+ };
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ QuickFix.prototype.fix = function( formAttributes, callback ) {
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ /**
+ * Method used to validate data placed in form.
+ *
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @returns {String[]} Array of error messages. If array is empty, then it means no errors ocurred.
+ */
+ QuickFix.prototype.validate = function( formAttributes ) {
+ return [];
+ };
+
+ /**
+ * A method called to mark the selection on object before quickfix is applied.
+ *
+ * @param {CKEDITOR.dom.selection} selection Editor selection.
+ */
+ QuickFix.prototype.markSelection = function( editor, selection ) {
+ var rng = editor.createRange();
+ rng.setStartBefore( this.issue.element );
+ rng.setEndAfter( this.issue.element );
+ selection.selectRanges( [ rng ] );
+ };
+
+ QuickFix.prototype.lang = {};
+
+ QuickFix.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'en/QuickFix', QuickFix );
+}());
diff --git a/plugins/ckeditor/a11ychecker/quickfix/en/TableHeaders.js b/plugins/ckeditor/a11ychecker/quickfix/en/TableHeaders.js
new file mode 100644
index 0000000..3840b30
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/en/TableHeaders.js
@@ -0,0 +1,98 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'en',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * QuickFix adding a caption in the `table` element.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class TableHeaders
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function TableHeaders( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ TableHeaders.prototype = new QuickFix();
+
+ TableHeaders.prototype.constructor = TableHeaders;
+
+ TableHeaders.prototype.display = function( form ) {
+ var lang = this.lang;
+
+ form.setInputs( {
+ position: {
+ type: 'select',
+ label: lang.positionLabel,
+ value: 'row',
+ options: {
+ 'both': lang.positionBoth,
+ 'row': lang.positionHorizontally,
+ 'col': lang.positionVertically
+ }
+ }
+ } );
+ };
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ TableHeaders.prototype.fix = function( formAttributes, callback ) {
+ var table = this.issue.element,
+ headers = formAttributes.position,
+ newCell,
+ row,
+ i;
+ // Following code copied from CKEditor plugins/table/dialogs/table.js file.
+
+ // Should we make all first cells in a row TH?
+ if ( headers == 'col' || headers == 'both' ) {
+ for ( row = 0; row < table.$.rows.length; row++ ) {
+ if ( !table.$.rows[ row ].cells.length ) {
+ continue;
+ }
+
+ newCell = new CKEDITOR.dom.element( table.$.rows[ row ].cells[ 0 ] );
+ newCell.renameNode( 'th' );
+ newCell.setAttribute( 'scope', 'row' );
+ }
+ }
+
+ if ( !table.$.tHead && ( headers == 'row' || headers == 'both' ) ) {
+ var thead = new CKEDITOR.dom.element( table.$.createTHead() );
+ var tbody = table.getElementsByTag( 'tbody' ).getItem( 0 );
+ var theRow = tbody.getElementsByTag( 'tr' ).getItem( 0 );
+
+ // Change TD to TH:
+ for ( i = 0; i < theRow.getChildCount(); i++ ) {
+ var th = theRow.getChild( i );
+ // Skip bookmark nodes. (#6155)
+ if ( th.type == CKEDITOR.NODE_ELEMENT && !th.data( 'cke-bookmark' ) ) {
+ th.renameNode( 'th' );
+ th.setAttribute( 'scope', 'col' );
+ }
+ }
+ thead.append( theRow.remove() );
+ }
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ TableHeaders.prototype.lang = {"positionLabel":"Position","positionHorizontally":"Horizontally","positionVertically":"Vertically","positionBoth":"Both"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'en/TableHeaders', TableHeaders );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/nl/AddTableCaption.js b/plugins/ckeditor/a11ychecker/quickfix/nl/AddTableCaption.js
new file mode 100644
index 0000000..ae5f873
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/nl/AddTableCaption.js
@@ -0,0 +1,75 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'nl',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+
+ var emptyWhitespaceRegExp = /^[\s\n\r]+$/g;
+
+ /**
+ * QuickFix adding a caption in the `table` element.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class AddTableCaption
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function AddTableCaption( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ AddTableCaption.prototype = new QuickFix();
+
+ AddTableCaption.prototype.constructor = AddTableCaption;
+
+ AddTableCaption.prototype.display = function( form ) {
+ form.setInputs( {
+ caption: {
+ type: 'text',
+ label: this.lang.captionLabel
+ }
+ } );
+ };
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ AddTableCaption.prototype.fix = function( formAttributes, callback ) {
+ var issueElement = this.issue.element,
+ caption = issueElement.getDocument().createElement( 'caption' );
+
+ caption.setHtml( formAttributes.caption );
+ // Prepend the caption.
+ issueElement.append( caption, true );
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ AddTableCaption.prototype.validate = function( formAttributes ) {
+ var proposedCaption = formAttributes.caption,
+ ret = [];
+
+ // Test if the caption has only whitespaces.
+ if ( !proposedCaption || proposedCaption.match( emptyWhitespaceRegExp ) ) {
+ ret.push( this.lang.errorEmpty );
+ }
+
+ return ret;
+ };
+
+ AddTableCaption.prototype.lang = {"captionLabel":"Caption","errorEmpty":"Caption (bijschtift) tekst mag niet leeg zijn"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'nl/AddTableCaption', AddTableCaption );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/nl/AnchorsMerge.js b/plugins/ckeditor/a11ychecker/quickfix/nl/AnchorsMerge.js
new file mode 100644
index 0000000..95b9d00
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/nl/AnchorsMerge.js
@@ -0,0 +1,80 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'nl',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * QuickFix merging two or more sibling anchors with the same href.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class AnchorsMerge
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function AnchorsMerge( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ AnchorsMerge.prototype = new QuickFix();
+
+ AnchorsMerge.prototype.constructor = AnchorsMerge;
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ AnchorsMerge.prototype.fix = function( formAttributes, callback ) {
+ var issueElement = this.issue.element,
+ nextSibling = issueElement.getNext(),
+ initialHref = issueElement.getAttribute( 'href' ),
+ extraInnerHtml = '',
+ isWhitespace = function( node ) {
+ return node.type === CKEDITOR.NODE_TEXT && node.getText().match( /^[\s]*$/ );
+ },
+ iterationAllowed = function( node ) {
+ if ( !node ) {
+ return false;
+ }
+
+ // We only allow anchors that have the same href as the initial one
+ return ( node.getName && node.getName() == 'a' && nextSibling.getAttribute( 'href' ) == initialHref ) ||
+ isWhitespace( node ); // Or whitespace text nodes.
+ },
+ curNode;
+
+ while ( iterationAllowed( nextSibling ) ) {
+ curNode = nextSibling;
+
+ // This html will be added later on to the first anchor.
+ extraInnerHtml += isWhitespace( curNode ) ? curNode.getText() : curNode.getHtml();
+
+ // Prepare nextSibling var for next iteration.
+ nextSibling = curNode.getNext();
+
+ // And we can remove element safely.
+ curNode.remove();
+ }
+
+ // Adding extra html to first anchor.
+ if ( extraInnerHtml ) {
+ issueElement.setHtml( issueElement.getHtml() + extraInnerHtml );
+ }
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ AnchorsMerge.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'nl/AnchorsMerge', AnchorsMerge );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/nl/AttributeRename.js b/plugins/ckeditor/a11ychecker/quickfix/nl/AttributeRename.js
new file mode 100644
index 0000000..380f3ab
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/nl/AttributeRename.js
@@ -0,0 +1,86 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'nl',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * QuickFix renaming an attribute {@link #attributeName} to another name
+ * {@link #attributeTargetName}.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class AttributeRename
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function AttributeRename( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ AttributeRename.prototype = new QuickFix();
+
+ AttributeRename.prototype.constructor = AttributeRename;
+
+ /**
+ * Name of the attribute to be renamed.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.AttributeRename
+ */
+ AttributeRename.prototype.attributeName = 'title';
+
+ /**
+ * A desired name for the attribute.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.AttributeRename
+ */
+ AttributeRename.prototype.attributeTargetName = 'alt';
+
+ /**
+ * Gets the proposed new value of the target attribute.
+ *
+ * @returns {String}
+ */
+ AttributeRename.prototype.getProposedValue = function() {
+ return this.issue.element.getAttribute( this.attributeName ) || '';
+ };
+
+ AttributeRename.prototype.display = function( form ) {
+ form.setInputs( {
+ value: {
+ type: 'text',
+ label: 'Value',
+ value: this.getProposedValue()
+ }
+ } );
+ };
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ AttributeRename.prototype.fix = function( formAttributes, callback ) {
+ var issueElement = this.issue.element,
+ desiredValue = formAttributes.value;
+
+ // Set desired attribute value.
+ issueElement.setAttribute( this.attributeTargetName, desiredValue );
+ // Unset the old attribute.
+ issueElement.removeAttribute( this.attributeName );
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ AttributeRename.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'nl/AttributeRename', AttributeRename );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/nl/AttributeRenameDefault.js b/plugins/ckeditor/a11ychecker/quickfix/nl/AttributeRenameDefault.js
new file mode 100644
index 0000000..64fe7fa
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/nl/AttributeRenameDefault.js
@@ -0,0 +1,40 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'nl',
+ name: 'AttributeRename',
+ callback: function( AttributeRename ) {
+ /**
+ * QuickFix renaming an attribute {@link #attributeName} to another name
+ * {@link #attributeTargetName} using a proposed default value
+ * based on the value of {@link #attributeTargetName}.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class AttributeRenameDefault
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function AttributeRenameDefault( issue ) {
+ AttributeRename.call( this, issue );
+ }
+
+ AttributeRenameDefault.prototype = new AttributeRename();
+
+ AttributeRenameDefault.prototype.constructor = AttributeRenameDefault;
+
+ AttributeRenameDefault.prototype.getProposedValue = function() {
+ var element = this.issue.element;
+ return element.getAttribute( this.attributeTargetName ) ||
+ element.getAttribute( this.attributeName ) || '';
+ };
+
+ AttributeRenameDefault.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'nl/AttributeRenameDefault', AttributeRenameDefault );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/nl/DateUnfold.js b/plugins/ckeditor/a11ychecker/quickfix/nl/DateUnfold.js
new file mode 100644
index 0000000..6a6ff8a
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/nl/DateUnfold.js
@@ -0,0 +1,133 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'nl',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ // List of month names.
+ var monthNames = {
+ en: [
+ 'January',
+ 'February',
+ 'March',
+ 'April',
+ 'May',
+ 'June',
+ 'July',
+ 'August',
+ 'September',
+ 'October',
+ 'November',
+ 'December'
+ ]
+ };
+
+ /**
+ * QuickFix converting short dates to more verbose format. Eg. convert 21-3-2030
+ * to 21 March 2030.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class DateUnfold
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function DateUnfold( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ DateUnfold.prototype = new QuickFix();
+
+ DateUnfold.prototype.constructor = DateUnfold;
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ DateUnfold.prototype.fix = function( formAttributes, callback ) {
+ var issueElement = this.issue.element,
+ innerText = issueElement.getText(),
+ that = this;
+
+ innerText = innerText.replace( /(\d{1,2}[.\/-]\d{1,2}[.\/-]\d{2,4})/g, function( occur ) {
+ var extractedDate = that.parseDate( occur );
+
+ return that.getFriendlyDate( extractedDate );
+ } );
+
+ issueElement.setText( innerText );
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ /**
+ * Parses given "short" data. Returns an object with 1-based values.
+ *
+ * Eg. 21.03.2020 would be parsed to:
+ *
+ * {
+ * day: "21",
+ * month: "03",
+ * year: "2020"
+ * }
+ *
+ * @returns {Object} An object containing properties:
+ * * day
+ * * month
+ * * year
+ */
+ DateUnfold.prototype.parseDate = function( dateString ) {
+ var ret = dateString.split( /[.\-\/]+/ );
+
+ return {
+ day: ret[ 0 ],
+ month: ret[ 1 ],
+ year: ret[ 2 ]
+ };
+ };
+
+ /**
+ * var ret = dateFix.getFriendlyDate( {
+ * day: "21",
+ * month: "03",
+ * year: "2020"
+ * } );
+ *
+ * // ret === "21 March 2020"
+ *
+ * @param {Object} An object returned by {@link #parseDate}
+ * @returns {String} A human-friendly date representation.
+ */
+ DateUnfold.prototype.getFriendlyDate = function( dateObj ) {
+ // month - 1 because monthNames is 0-based array.
+ var monthName = monthNames.en[ Number( dateObj.month - 1 ) ],
+ year = Number( dateObj.year );
+
+ // In case of 2 digit year value, lets fix it.
+ if ( year >= 0 && year < 100 ) {
+ // Year 70 and greater will be considered 19xx.
+ if ( year >= 70 ) {
+ year += 1900;
+ } else {
+ // Otherwise we assume it's 20xx.
+ year += 2000;
+ }
+ }
+
+ // Cast day to Number, to remove leading 0.
+ return [ Number( dateObj.day ), monthName, year ].join( ' ' );
+ };
+
+ DateUnfold.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'nl/DateUnfold', DateUnfold );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/nl/ElementRemove.js b/plugins/ckeditor/a11ychecker/quickfix/nl/ElementRemove.js
new file mode 100644
index 0000000..6a2747c
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/nl/ElementRemove.js
@@ -0,0 +1,43 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'nl',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * The ultimate fix for unsolvable problem - removing an element.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class ElementRemove
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue
+ */
+ function ElementRemove( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ ElementRemove.prototype = new QuickFix();
+ ElementRemove.prototype.constructor = ElementRemove;
+
+ ElementRemove.prototype.display = function( form ) {
+ form.setInputs( {} );
+ };
+
+ ElementRemove.prototype.fix = function( formAttributes, callback ) {
+ this.issue.element.remove();
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ ElementRemove.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'nl/ElementRemove', ElementRemove );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/nl/ElementReplace.js b/plugins/ckeditor/a11ychecker/quickfix/nl/ElementReplace.js
new file mode 100644
index 0000000..659b7f2
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/nl/ElementReplace.js
@@ -0,0 +1,59 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'nl',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * Replaces provided element with element that a different tag name, preserving its children.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class ElementReplace
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue
+ */
+ function ElementReplace( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ ElementReplace.prototype = new QuickFix();
+ ElementReplace.prototype.constructor = ElementReplace;
+
+ /**
+ * Returns the name of the tag that issue.element should be converted to.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.ElementReplace
+ * @param {Object} formAttributes Form attributes from {@link #fix}.
+ * @returns {String}
+ */
+ ElementReplace.prototype.getTargetName = function( formAttributes ) {
+ return 'h1';
+ };
+
+ ElementReplace.prototype.display = function( form ) {
+ form.setInputs( {} );
+ };
+
+ ElementReplace.prototype.fix = function( formAttributes, callback ) {
+ var newElement = new CKEDITOR.dom.element( this.getTargetName( formAttributes ) );
+
+ newElement.replace( this.issue.element );
+ this.issue.element.moveChildren( newElement );
+
+ this.issue.element = newElement;
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ ElementReplace.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'nl/ElementReplace', ElementReplace );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/nl/ImgAlt.js b/plugins/ckeditor/a11ychecker/quickfix/nl/ImgAlt.js
new file mode 100644
index 0000000..ee24f8d
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/nl/ImgAlt.js
@@ -0,0 +1,89 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'nl',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+
+ var emptyWhitespaceRegExp = /^[\s\n\r]+$/g;
+
+ /**
+ * Fixes the image with missing alt attribute.
+ *
+ * @constructor
+ */
+ function ImgAlt( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ /**
+ * Maximal count of characters in the alt. It might be changed to `0` to prevent
+ * length validation.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.AttributeRename
+ * @static
+ */
+ ImgAlt.altLengthLimit = 100;
+
+ ImgAlt.prototype = new QuickFix();
+ ImgAlt.prototype.constructor = ImgAlt;
+
+ ImgAlt.prototype.display = function( form ) {
+ form.setInputs( {
+ alt: {
+ type: 'text',
+ label: this.lang.altLabel,
+ value: this.issue.element.getAttribute( 'alt' ) || ''
+ }
+ } );
+ };
+
+ ImgAlt.prototype.fix = function( formAttributes, callback ) {
+ this.issue.element.setAttribute( 'alt', formAttributes.alt );
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ ImgAlt.prototype.validate = function( formAttributes ) {
+ var ret = [],
+ proposedAlt = formAttributes.alt + '',
+ imgElem = this.issue && this.issue.element,
+ lang = this.lang;
+
+ // Test if the alt has only whitespaces.
+ if ( proposedAlt.match( emptyWhitespaceRegExp ) ) {
+ ret.push( lang.errorWhitespace );
+ }
+
+ // Testing against exceeding max length.
+ if ( ImgAlt.altLengthLimit && proposedAlt.length > ImgAlt.altLengthLimit ) {
+ var errorTemplate = new CKEDITOR.template( lang.errorTooLong );
+
+ ret.push( errorTemplate.output( {
+ limit: ImgAlt.altLengthLimit,
+ length: proposedAlt.length
+ } ) );
+ }
+
+ if ( imgElem ) {
+ var fileName = String( imgElem.getAttribute( 'src' ) ).split( '/' ).pop();
+ if ( fileName == proposedAlt ) {
+ ret.push( lang.errorSameAsFileName );
+ }
+ }
+
+ return ret;
+ };
+
+ ImgAlt.prototype.lang = {"altLabel":"Alternatieve tekst","errorTooLong":"Alternatieve tekst is te lang. Deze mag maximaal {limit} karaktersbevatten terwijl opgegeven tekst {length} bevat","errorWhitespace":"Alternatieve tekst mag niet alleen uit spaties bestaan","errorSameAsFileName":"Alt-tekst van de afbeelding mag niet hetzelfde zijn als de bestandsnaam"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'nl/ImgAlt', ImgAlt );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/nl/ImgAltNonEmpty.js b/plugins/ckeditor/a11ychecker/quickfix/nl/ImgAltNonEmpty.js
new file mode 100644
index 0000000..b73aded
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/nl/ImgAltNonEmpty.js
@@ -0,0 +1,44 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'nl',
+ name: 'ImgAlt',
+ callback: function( ImgAlt ) {
+
+ /**
+ * Fixes the image with missing alt attribute, requiring non-empty alt.
+ *
+ * @constructor
+ */
+ function ImgAltNonEmpty( issue ) {
+ ImgAlt.call( this, issue );
+ }
+
+ ImgAltNonEmpty.prototype = new ImgAlt();
+ ImgAltNonEmpty.prototype.constructor = ImgAltNonEmpty;
+
+ ImgAltNonEmpty.prototype.validate = function( formAttributes ) {
+ var ret = [],
+ proposedAlt = formAttributes.alt + '';
+
+ if ( !proposedAlt ) {
+ ret.push( this.lang.errorEmpty );
+ }
+
+ if ( !ret.length ) {
+ ret = ImgAlt.prototype.validate.call( this, formAttributes );
+ }
+
+ return ret;
+ };
+
+ ImgAltNonEmpty.prototype.lang = {"altLabel":"Alternatieve tekst","errorTooLong":"Alternatieve tekst is te lang. Deze mag maximaal {limit} karaktersbevatten terwijl opgegeven tekst {length} bevat","errorWhitespace":"Alternatieve tekst mag niet alleen uit spaties bestaan","errorSameAsFileName":"Alt-tekst van de afbeelding mag niet hetzelfde zijn als de bestandsnaam","errorEmpty":"Alternatieve tekst mag niet leeg zijn"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'nl/ImgAltNonEmpty', ImgAltNonEmpty );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/nl/LocalizedRepository.js b/plugins/ckeditor/a11ychecker/quickfix/nl/LocalizedRepository.js
new file mode 100644
index 0000000..6c23482
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/nl/LocalizedRepository.js
@@ -0,0 +1,174 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+define( [ 'quickfix/Repository' ], function( Repository ) {
+ 'use strict';
+
+ /**
+ * This type adds localization support for repository.
+ *
+ * @mixins CKEDITOR.event
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @constructor
+ * @param {String} basePath A path to the directory where QuickFix classes are
+ * stored.
+ */
+ function LocalizedRepository( basePath ) {
+ Repository.call( this, basePath );
+ }
+
+ LocalizedRepository.prototype = new Repository();
+ LocalizedRepository.prototype.constructor = LocalizedRepository;
+
+ LocalizedRepository.prototype._langDictionary = {};
+
+ // An array of arguments from calls that were deferred.
+ var deferredGetCalls = {},
+ languagesRequested = [];
+
+ /**
+ * See {@link CKEDITOR.plugins.a11ychecker.quickFix.Repository#get}. This implementation
+ * adds only `options.langCode` param:
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.LocalizedRepository
+ * @param {Object} options
+ * @param {String} options.langCode Language code of quickFix to be loaded.
+ * @returns {Function}
+ */
+ LocalizedRepository.prototype.get = function( options ) {
+ options.langCode = options.langCode || 'en';
+
+ if ( this.deferGetCall( options.langCode, arguments ) ) {
+ // Call should be deferred, because no lang is available yet.
+ return;
+ }
+
+ if ( !CKEDITOR.plugins.a11ychecker.dev ) {
+ // In case of release code we'll do a trick here.
+ // Each class will be represented as '/' string, that way we
+ // can load multiple language combination with given class.
+ options.name = options.langCode + '/' + options.name;
+ }
+
+ // If lang is available call to the base class.
+ return Repository.prototype.get.call( this, options );
+ };
+
+ /**
+ * Similar to {@link #get} but returns localized instance rather than class.
+ *
+ * Please note that options.callback is mandatory.
+ *
+ * @todo: this method should be also available in generic class.
+ */
+ LocalizedRepository.prototype.getInstance = function( options ) {
+ options = options || {};
+ var name = options.name,
+ langCode = options.langCode || 'en',
+ that = this;
+
+ this.get( {
+ name: name,
+ callback: function( QuickFixType ) {
+ // This callback is guaranteed to be called when dictionary for langCode is fetched.
+ var instance = new QuickFixType( options.issue );
+
+ if ( CKEDITOR.plugins.a11ychecker.dev ) {
+ // We only need to assign lang for dev version, built class will already have this property.
+ instance.lang = that._langDictionary[ langCode ][ name ];
+ }
+
+ options.callback( instance );
+ },
+ langCode: langCode
+ } );
+ };
+
+
+ /**
+ * If needed will defer {@link #get} call.
+ *
+ * @returns {Boolean} `true` if call was deferred, `false` otherwise.
+ */
+ LocalizedRepository.prototype.deferGetCall = function( langCode, getArguments ) {
+ var indexOf = CKEDITOR.tools.indexOf;
+ if ( !CKEDITOR.plugins.a11ychecker.dev || this._langDictionary[ langCode ] ) {
+ // Deferring is always disabled in built version, and if _langDictionary is already
+ // loaded.
+ return false;
+ }
+
+ this._addDeferredGet( langCode, getArguments );
+
+ if ( indexOf( languagesRequested, langCode ) === -1 ) {
+ // This particular language was not requested yet.
+ languagesRequested.push( langCode );
+ CKEDITOR.scriptLoader.load( this.basePath + 'lang/' + langCode + '.js' );
+ }
+
+ return true;
+ };
+
+ /**
+ * Registers a class of given QuickFix.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.LocalizedRepository
+ * @param {String} name QuickFix name.
+ * @param {Function} cls QuickFix type.
+ */
+ LocalizedRepository.prototype.add = function( name, cls ) {
+ return Repository.prototype.add.call( this, name, cls );
+ };
+
+ /**
+ * Method to register language dictionary for developer version.
+ *
+ * In built version languages are already inlined into a QuickFix class file, so there's
+ * no need to execute it.
+ *
+ * @param {Object} dictionary
+ */
+ LocalizedRepository.prototype.lang = function( langCode, dictionary ) {
+ this._langDictionary[ langCode ] = dictionary;
+
+ var getQueue = deferredGetCalls[ langCode ];
+
+ if ( !getQueue ) {
+ // No get calls were queued for that language.
+ return;
+ }
+
+ // All deferred gets should be called in reversed order.
+ for ( var i = getQueue.length - 1; i >= 0; i-- ) {
+ this.get.apply( this, getQueue[ i ] );
+ }
+ };
+
+ LocalizedRepository.prototype._addDeferredGet = function( langCode, getArguments ) {
+ if ( deferredGetCalls[ langCode ] ) {
+ deferredGetCalls[ langCode ].push( getArguments );
+ } else {
+ deferredGetCalls[ langCode ] = [ getArguments ];
+ }
+ };
+
+
+ /**
+ * Function created for tests, returns count of deferred get functions.
+ *
+ * @returns {Number}
+ */
+ LocalizedRepository.prototype._getDeferredGetCount = function( langCode ) {
+ return deferredGetCalls[ langCode ] ? deferredGetCalls[ langCode ].length : 0;
+ };
+
+ /**
+ * Function created for tests, clears deferred get queue.
+ */
+ LocalizedRepository.prototype._clearDeferredGetQueue = function() {
+ deferredGetCalls = {};
+ };
+
+ return LocalizedRepository;
+} );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/nl/ParagraphToHeader.js b/plugins/ckeditor/a11ychecker/quickfix/nl/ParagraphToHeader.js
new file mode 100644
index 0000000..dafc3f4
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/nl/ParagraphToHeader.js
@@ -0,0 +1,168 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'nl',
+ name: 'ElementReplace',
+ callback: function( ElementReplace ) {
+ /**
+ * Replaces provided element with element that a different tag name, preserving its children.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class ParagraphToHeader
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue
+ */
+ function ParagraphToHeader( issue ) {
+ ElementReplace.call( this, issue );
+ }
+
+ ParagraphToHeader.prototype = new ElementReplace();
+ ParagraphToHeader.prototype.constructor = ParagraphToHeader;
+
+ ParagraphToHeader.prototype.getTargetName = function( formAttributes ) {
+ return formAttributes.level;
+ };
+
+ ParagraphToHeader.prototype.display = function( form, editor ) {
+
+ var levelDict = this._getFormHeaderLeves( editor );
+
+ form.setInputs( {
+ level: {
+ type: 'select',
+ label: this.lang.levelLabel,
+ value: 'h' + this._getPreferredLevel( editor ),
+ options: levelDict
+ }
+ } );
+ };
+
+ ParagraphToHeader.prototype.fix = function( formAttributes, callback ) {
+ var that = this;
+ ElementReplace.prototype.fix.call( this, formAttributes, function() {
+ that._removeBoldTag();
+ callback( that );
+ } );
+ };
+
+ /**
+ * Determines preferred heading level for the header that should be cerated.
+ *
+ * @private
+ * @param {CKEDITOR.editor} editor
+ * @returns {Number} Number ranging from `1` to `6`.
+ */
+ ParagraphToHeader.prototype._getPreferredLevel = function( editor ) {
+ var ret = 1,
+ editable = editor.editable(),
+ headerTagRegExp = /^h[1-6]$/i,
+ range = new CKEDITOR.dom.range( editable.getDocument() ),
+ walker,
+ prevElement;
+
+ range.setStartAt( editable, CKEDITOR.POSITION_AFTER_START );
+ range.setEndAt( this.issue.element, CKEDITOR.POSITION_BEFORE_START );
+ walker = new CKEDITOR.dom.walker( range );
+
+ while ( ( prevElement = walker.previous() ) ) {
+ if ( prevElement.getName && prevElement.getName().match( headerTagRegExp ) ) {
+ ret = Number( prevElement.getName()[ 1 ] ) + 1;
+ break;
+ }
+ }
+
+ // WE can't return a higher value than 7.
+ return Math.min( ret, 6 );
+ };
+
+ /**
+ * This method check if issue element contains `` element only as a first and the only child.
+ * If so we'll remove it, but move its children to the `issue.element`.
+ */
+ ParagraphToHeader.prototype._removeBoldTag = function() {
+ var isElementEvaluator = function( el ) {
+ return el.type === CKEDITOR.NODE_ELEMENT;
+ },
+ elem = this.issue.element,
+ innerElement = elem.getFirst( isElementEvaluator ),
+ // If first child element is at the same time last element child, then it means it has only this element.
+ hasSingleElement = innerElement && innerElement.equals( elem.getLast( isElementEvaluator ) ),
+ suspiciousTagNames = [ 'strong', 'b' ];
+
+ if ( hasSingleElement && CKEDITOR.tools.indexOf( suspiciousTagNames, innerElement.getName() ) !== -1 ) {
+ innerElement.moveChildren( elem );
+ innerElement.remove();
+ }
+ };
+
+ /**
+ * Returns minimal and maximal possible header levels for given editor.
+ *
+ * Result will be based on ACF and `config.format_tags`.
+ *
+ * @param {CKEDITOR.editor}
+ * @return {Object} Allowed header level boundaries.
+ * @return {Number} return.min Minimal allowed level.
+ * @return {Number} return.email Maximal allowed level.
+ */
+ ParagraphToHeader.prototype._getPossibleLevels = function( editor ) {
+ var tags = ( editor.config.format_tags || '' ).split( ';' ),
+ ret = {
+ min: 1,
+ max: 6
+ },
+ i;
+
+ // Filtering tags.
+ for ( i = tags.length - 1; i >= 0; i-- ) {
+ // If given tag is not header tag or if it's not allowed by the ACF.
+ if ( !tags[ i ].match( /^h[1-6]$/i ) || !editor.filter.check( tags[ i ] ) ) {
+ tags.splice( i, 1 );
+ } else {
+ tags[ i ] = Number( tags[ i ][ 1 ] );
+ }
+ }
+
+ if ( tags.length ) {
+ // Note if IE8 has to be supported we need to inline sorting here.
+ tags.sort();
+
+ ret.min = tags[ 0 ];
+ ret.max = tags[ tags.length - 1 ];
+ }
+
+ return ret;
+ };
+
+ /**
+ * Returns options dictionary that should be put in form header level select.
+ *
+ * @param {CKEDITOR.editor} editor
+ */
+ ParagraphToHeader.prototype._getFormHeaderLeves = function( editor ) {
+ var dict = {},
+ boundaries = this._getPossibleLevels( editor ),
+ preferredLevel = this._getPreferredLevel( editor );
+
+ for ( var i = boundaries.min; i <= boundaries.max; i++ ) {
+ dict[ 'h' + i ] = 'H' + i;
+ }
+
+ if ( dict[ 'h' + preferredLevel ] ) {
+ dict[ 'h' + preferredLevel ] += ( ' ' + this.lang.suggested );
+ }
+
+ return dict;
+ };
+
+
+ ParagraphToHeader.prototype.lang = {"levelLabel":"Header niveau","suggested":"(Suggestie)"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'nl/ParagraphToHeader', ParagraphToHeader );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/nl/QuickFix.js b/plugins/ckeditor/a11ychecker/quickfix/nl/QuickFix.js
new file mode 100644
index 0000000..2a5ebf3
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/nl/QuickFix.js
@@ -0,0 +1,90 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+(function() {
+ 'use strict';
+
+ /**
+ * QuickFix type for the QuickFix objects.
+ *
+ * # Overview
+ *
+ * It encapsulates logic responsible for fixing Accessibility issue.
+ *
+ * ## Working with QuickFix objects
+ *
+ * ### Adding controls to the QuickFix form
+ *
+ * Controls can be added in {@link #display} method using {@link CKEDITOR.plugins.a11ychecker.ViewerForm}
+ * methods.
+ *
+ * ### Executing the fix
+ *
+ * The fixing logic is placed in {@link #fix} method, so you need to simply call it when
+ * you're sure to apply the fix.
+ *
+ * @since 4.6.0
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class QuickFix
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function QuickFix( issue ) {
+ this.issue = issue;
+ }
+
+ QuickFix.prototype = {
+ /**
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.QuickFix
+ * @property {CKEDITOR.plugins.a11ychecker.Issue} issue Issue object that QuickFix was created for.
+ */
+ issue: null
+ };
+
+ QuickFix.prototype.constructor = QuickFix;
+
+ QuickFix.prototype.display = function( form, editor ) {
+ };
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ QuickFix.prototype.fix = function( formAttributes, callback ) {
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ /**
+ * Method used to validate data placed in form.
+ *
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @returns {String[]} Array of error messages. If array is empty, then it means no errors ocurred.
+ */
+ QuickFix.prototype.validate = function( formAttributes ) {
+ return [];
+ };
+
+ /**
+ * A method called to mark the selection on object before quickfix is applied.
+ *
+ * @param {CKEDITOR.dom.selection} selection Editor selection.
+ */
+ QuickFix.prototype.markSelection = function( editor, selection ) {
+ var rng = editor.createRange();
+ rng.setStartBefore( this.issue.element );
+ rng.setEndAfter( this.issue.element );
+ selection.selectRanges( [ rng ] );
+ };
+
+ QuickFix.prototype.lang = {};
+
+ QuickFix.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'nl/QuickFix', QuickFix );
+}());
diff --git a/plugins/ckeditor/a11ychecker/quickfix/nl/TableHeaders.js b/plugins/ckeditor/a11ychecker/quickfix/nl/TableHeaders.js
new file mode 100644
index 0000000..d96a8b5
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/nl/TableHeaders.js
@@ -0,0 +1,98 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'nl',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * QuickFix adding a caption in the `table` element.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class TableHeaders
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function TableHeaders( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ TableHeaders.prototype = new QuickFix();
+
+ TableHeaders.prototype.constructor = TableHeaders;
+
+ TableHeaders.prototype.display = function( form ) {
+ var lang = this.lang;
+
+ form.setInputs( {
+ position: {
+ type: 'select',
+ label: lang.positionLabel,
+ value: 'row',
+ options: {
+ 'both': lang.positionBoth,
+ 'row': lang.positionHorizontally,
+ 'col': lang.positionVertically
+ }
+ }
+ } );
+ };
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ TableHeaders.prototype.fix = function( formAttributes, callback ) {
+ var table = this.issue.element,
+ headers = formAttributes.position,
+ newCell,
+ row,
+ i;
+ // Following code copied from CKEditor plugins/table/dialogs/table.js file.
+
+ // Should we make all first cells in a row TH?
+ if ( headers == 'col' || headers == 'both' ) {
+ for ( row = 0; row < table.$.rows.length; row++ ) {
+ if ( !table.$.rows[ row ].cells.length ) {
+ continue;
+ }
+
+ newCell = new CKEDITOR.dom.element( table.$.rows[ row ].cells[ 0 ] );
+ newCell.renameNode( 'th' );
+ newCell.setAttribute( 'scope', 'row' );
+ }
+ }
+
+ if ( !table.$.tHead && ( headers == 'row' || headers == 'both' ) ) {
+ var thead = new CKEDITOR.dom.element( table.$.createTHead() );
+ var tbody = table.getElementsByTag( 'tbody' ).getItem( 0 );
+ var theRow = tbody.getElementsByTag( 'tr' ).getItem( 0 );
+
+ // Change TD to TH:
+ for ( i = 0; i < theRow.getChildCount(); i++ ) {
+ var th = theRow.getChild( i );
+ // Skip bookmark nodes. (#6155)
+ if ( th.type == CKEDITOR.NODE_ELEMENT && !th.data( 'cke-bookmark' ) ) {
+ th.renameNode( 'th' );
+ th.setAttribute( 'scope', 'col' );
+ }
+ }
+ thead.append( theRow.remove() );
+ }
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ TableHeaders.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'nl/TableHeaders', TableHeaders );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/pt-br/AddTableCaption.js b/plugins/ckeditor/a11ychecker/quickfix/pt-br/AddTableCaption.js
new file mode 100644
index 0000000..813d1f1
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/pt-br/AddTableCaption.js
@@ -0,0 +1,75 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'pt-br',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+
+ var emptyWhitespaceRegExp = /^[\s\n\r]+$/g;
+
+ /**
+ * QuickFix adding a caption in the `table` element.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class AddTableCaption
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function AddTableCaption( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ AddTableCaption.prototype = new QuickFix();
+
+ AddTableCaption.prototype.constructor = AddTableCaption;
+
+ AddTableCaption.prototype.display = function( form ) {
+ form.setInputs( {
+ caption: {
+ type: 'text',
+ label: this.lang.captionLabel
+ }
+ } );
+ };
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ AddTableCaption.prototype.fix = function( formAttributes, callback ) {
+ var issueElement = this.issue.element,
+ caption = issueElement.getDocument().createElement( 'caption' );
+
+ caption.setHtml( formAttributes.caption );
+ // Prepend the caption.
+ issueElement.append( caption, true );
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ AddTableCaption.prototype.validate = function( formAttributes ) {
+ var proposedCaption = formAttributes.caption,
+ ret = [];
+
+ // Test if the caption has only whitespaces.
+ if ( !proposedCaption || proposedCaption.match( emptyWhitespaceRegExp ) ) {
+ ret.push( this.lang.errorEmpty );
+ }
+
+ return ret;
+ };
+
+ AddTableCaption.prototype.lang = {"captionLabel":"Legenda da tabela","errorEmpty":"O texto da legenda da tabela não pode estar vazio"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'pt-br/AddTableCaption', AddTableCaption );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/pt-br/AnchorsMerge.js b/plugins/ckeditor/a11ychecker/quickfix/pt-br/AnchorsMerge.js
new file mode 100644
index 0000000..c3515a0
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/pt-br/AnchorsMerge.js
@@ -0,0 +1,80 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'pt-br',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * QuickFix merging two or more sibling anchors with the same href.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class AnchorsMerge
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function AnchorsMerge( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ AnchorsMerge.prototype = new QuickFix();
+
+ AnchorsMerge.prototype.constructor = AnchorsMerge;
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ AnchorsMerge.prototype.fix = function( formAttributes, callback ) {
+ var issueElement = this.issue.element,
+ nextSibling = issueElement.getNext(),
+ initialHref = issueElement.getAttribute( 'href' ),
+ extraInnerHtml = '',
+ isWhitespace = function( node ) {
+ return node.type === CKEDITOR.NODE_TEXT && node.getText().match( /^[\s]*$/ );
+ },
+ iterationAllowed = function( node ) {
+ if ( !node ) {
+ return false;
+ }
+
+ // We only allow anchors that have the same href as the initial one
+ return ( node.getName && node.getName() == 'a' && nextSibling.getAttribute( 'href' ) == initialHref ) ||
+ isWhitespace( node ); // Or whitespace text nodes.
+ },
+ curNode;
+
+ while ( iterationAllowed( nextSibling ) ) {
+ curNode = nextSibling;
+
+ // This html will be added later on to the first anchor.
+ extraInnerHtml += isWhitespace( curNode ) ? curNode.getText() : curNode.getHtml();
+
+ // Prepare nextSibling var for next iteration.
+ nextSibling = curNode.getNext();
+
+ // And we can remove element safely.
+ curNode.remove();
+ }
+
+ // Adding extra html to first anchor.
+ if ( extraInnerHtml ) {
+ issueElement.setHtml( issueElement.getHtml() + extraInnerHtml );
+ }
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ AnchorsMerge.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'pt-br/AnchorsMerge', AnchorsMerge );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/pt-br/AttributeRename.js b/plugins/ckeditor/a11ychecker/quickfix/pt-br/AttributeRename.js
new file mode 100644
index 0000000..9c392b7
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/pt-br/AttributeRename.js
@@ -0,0 +1,86 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'pt-br',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * QuickFix renaming an attribute {@link #attributeName} to another name
+ * {@link #attributeTargetName}.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class AttributeRename
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function AttributeRename( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ AttributeRename.prototype = new QuickFix();
+
+ AttributeRename.prototype.constructor = AttributeRename;
+
+ /**
+ * Name of the attribute to be renamed.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.AttributeRename
+ */
+ AttributeRename.prototype.attributeName = 'title';
+
+ /**
+ * A desired name for the attribute.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.AttributeRename
+ */
+ AttributeRename.prototype.attributeTargetName = 'alt';
+
+ /**
+ * Gets the proposed new value of the target attribute.
+ *
+ * @returns {String}
+ */
+ AttributeRename.prototype.getProposedValue = function() {
+ return this.issue.element.getAttribute( this.attributeName ) || '';
+ };
+
+ AttributeRename.prototype.display = function( form ) {
+ form.setInputs( {
+ value: {
+ type: 'text',
+ label: 'Value',
+ value: this.getProposedValue()
+ }
+ } );
+ };
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ AttributeRename.prototype.fix = function( formAttributes, callback ) {
+ var issueElement = this.issue.element,
+ desiredValue = formAttributes.value;
+
+ // Set desired attribute value.
+ issueElement.setAttribute( this.attributeTargetName, desiredValue );
+ // Unset the old attribute.
+ issueElement.removeAttribute( this.attributeName );
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ AttributeRename.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'pt-br/AttributeRename', AttributeRename );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/pt-br/AttributeRenameDefault.js b/plugins/ckeditor/a11ychecker/quickfix/pt-br/AttributeRenameDefault.js
new file mode 100644
index 0000000..c737fe8
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/pt-br/AttributeRenameDefault.js
@@ -0,0 +1,40 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'pt-br',
+ name: 'AttributeRename',
+ callback: function( AttributeRename ) {
+ /**
+ * QuickFix renaming an attribute {@link #attributeName} to another name
+ * {@link #attributeTargetName} using a proposed default value
+ * based on the value of {@link #attributeTargetName}.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class AttributeRenameDefault
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function AttributeRenameDefault( issue ) {
+ AttributeRename.call( this, issue );
+ }
+
+ AttributeRenameDefault.prototype = new AttributeRename();
+
+ AttributeRenameDefault.prototype.constructor = AttributeRenameDefault;
+
+ AttributeRenameDefault.prototype.getProposedValue = function() {
+ var element = this.issue.element;
+ return element.getAttribute( this.attributeTargetName ) ||
+ element.getAttribute( this.attributeName ) || '';
+ };
+
+ AttributeRenameDefault.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'pt-br/AttributeRenameDefault', AttributeRenameDefault );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/pt-br/DateUnfold.js b/plugins/ckeditor/a11ychecker/quickfix/pt-br/DateUnfold.js
new file mode 100644
index 0000000..b3f0ab0
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/pt-br/DateUnfold.js
@@ -0,0 +1,133 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'pt-br',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ // List of month names.
+ var monthNames = {
+ en: [
+ 'January',
+ 'February',
+ 'March',
+ 'April',
+ 'May',
+ 'June',
+ 'July',
+ 'August',
+ 'September',
+ 'October',
+ 'November',
+ 'December'
+ ]
+ };
+
+ /**
+ * QuickFix converting short dates to more verbose format. Eg. convert 21-3-2030
+ * to 21 March 2030.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class DateUnfold
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function DateUnfold( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ DateUnfold.prototype = new QuickFix();
+
+ DateUnfold.prototype.constructor = DateUnfold;
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ DateUnfold.prototype.fix = function( formAttributes, callback ) {
+ var issueElement = this.issue.element,
+ innerText = issueElement.getText(),
+ that = this;
+
+ innerText = innerText.replace( /(\d{1,2}[.\/-]\d{1,2}[.\/-]\d{2,4})/g, function( occur ) {
+ var extractedDate = that.parseDate( occur );
+
+ return that.getFriendlyDate( extractedDate );
+ } );
+
+ issueElement.setText( innerText );
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ /**
+ * Parses given "short" data. Returns an object with 1-based values.
+ *
+ * Eg. 21.03.2020 would be parsed to:
+ *
+ * {
+ * day: "21",
+ * month: "03",
+ * year: "2020"
+ * }
+ *
+ * @returns {Object} An object containing properties:
+ * * day
+ * * month
+ * * year
+ */
+ DateUnfold.prototype.parseDate = function( dateString ) {
+ var ret = dateString.split( /[.\-\/]+/ );
+
+ return {
+ day: ret[ 0 ],
+ month: ret[ 1 ],
+ year: ret[ 2 ]
+ };
+ };
+
+ /**
+ * var ret = dateFix.getFriendlyDate( {
+ * day: "21",
+ * month: "03",
+ * year: "2020"
+ * } );
+ *
+ * // ret === "21 March 2020"
+ *
+ * @param {Object} An object returned by {@link #parseDate}
+ * @returns {String} A human-friendly date representation.
+ */
+ DateUnfold.prototype.getFriendlyDate = function( dateObj ) {
+ // month - 1 because monthNames is 0-based array.
+ var monthName = monthNames.en[ Number( dateObj.month - 1 ) ],
+ year = Number( dateObj.year );
+
+ // In case of 2 digit year value, lets fix it.
+ if ( year >= 0 && year < 100 ) {
+ // Year 70 and greater will be considered 19xx.
+ if ( year >= 70 ) {
+ year += 1900;
+ } else {
+ // Otherwise we assume it's 20xx.
+ year += 2000;
+ }
+ }
+
+ // Cast day to Number, to remove leading 0.
+ return [ Number( dateObj.day ), monthName, year ].join( ' ' );
+ };
+
+ DateUnfold.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'pt-br/DateUnfold', DateUnfold );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/pt-br/ElementRemove.js b/plugins/ckeditor/a11ychecker/quickfix/pt-br/ElementRemove.js
new file mode 100644
index 0000000..e33b6c2
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/pt-br/ElementRemove.js
@@ -0,0 +1,43 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'pt-br',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * The ultimate fix for unsolvable problem - removing an element.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class ElementRemove
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue
+ */
+ function ElementRemove( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ ElementRemove.prototype = new QuickFix();
+ ElementRemove.prototype.constructor = ElementRemove;
+
+ ElementRemove.prototype.display = function( form ) {
+ form.setInputs( {} );
+ };
+
+ ElementRemove.prototype.fix = function( formAttributes, callback ) {
+ this.issue.element.remove();
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ ElementRemove.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'pt-br/ElementRemove', ElementRemove );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/pt-br/ElementReplace.js b/plugins/ckeditor/a11ychecker/quickfix/pt-br/ElementReplace.js
new file mode 100644
index 0000000..b89634f
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/pt-br/ElementReplace.js
@@ -0,0 +1,59 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'pt-br',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * Replaces provided element with element that a different tag name, preserving its children.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class ElementReplace
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue
+ */
+ function ElementReplace( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ ElementReplace.prototype = new QuickFix();
+ ElementReplace.prototype.constructor = ElementReplace;
+
+ /**
+ * Returns the name of the tag that issue.element should be converted to.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.ElementReplace
+ * @param {Object} formAttributes Form attributes from {@link #fix}.
+ * @returns {String}
+ */
+ ElementReplace.prototype.getTargetName = function( formAttributes ) {
+ return 'h1';
+ };
+
+ ElementReplace.prototype.display = function( form ) {
+ form.setInputs( {} );
+ };
+
+ ElementReplace.prototype.fix = function( formAttributes, callback ) {
+ var newElement = new CKEDITOR.dom.element( this.getTargetName( formAttributes ) );
+
+ newElement.replace( this.issue.element );
+ this.issue.element.moveChildren( newElement );
+
+ this.issue.element = newElement;
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ ElementReplace.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'pt-br/ElementReplace', ElementReplace );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/pt-br/ImgAlt.js b/plugins/ckeditor/a11ychecker/quickfix/pt-br/ImgAlt.js
new file mode 100644
index 0000000..40b4d7e
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/pt-br/ImgAlt.js
@@ -0,0 +1,89 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'pt-br',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+
+ var emptyWhitespaceRegExp = /^[\s\n\r]+$/g;
+
+ /**
+ * Fixes the image with missing alt attribute.
+ *
+ * @constructor
+ */
+ function ImgAlt( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ /**
+ * Maximal count of characters in the alt. It might be changed to `0` to prevent
+ * length validation.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.AttributeRename
+ * @static
+ */
+ ImgAlt.altLengthLimit = 100;
+
+ ImgAlt.prototype = new QuickFix();
+ ImgAlt.prototype.constructor = ImgAlt;
+
+ ImgAlt.prototype.display = function( form ) {
+ form.setInputs( {
+ alt: {
+ type: 'text',
+ label: this.lang.altLabel,
+ value: this.issue.element.getAttribute( 'alt' ) || ''
+ }
+ } );
+ };
+
+ ImgAlt.prototype.fix = function( formAttributes, callback ) {
+ this.issue.element.setAttribute( 'alt', formAttributes.alt );
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ ImgAlt.prototype.validate = function( formAttributes ) {
+ var ret = [],
+ proposedAlt = formAttributes.alt + '',
+ imgElem = this.issue && this.issue.element,
+ lang = this.lang;
+
+ // Test if the alt has only whitespaces.
+ if ( proposedAlt.match( emptyWhitespaceRegExp ) ) {
+ ret.push( lang.errorWhitespace );
+ }
+
+ // Testing against exceeding max length.
+ if ( ImgAlt.altLengthLimit && proposedAlt.length > ImgAlt.altLengthLimit ) {
+ var errorTemplate = new CKEDITOR.template( lang.errorTooLong );
+
+ ret.push( errorTemplate.output( {
+ limit: ImgAlt.altLengthLimit,
+ length: proposedAlt.length
+ } ) );
+ }
+
+ if ( imgElem ) {
+ var fileName = String( imgElem.getAttribute( 'src' ) ).split( '/' ).pop();
+ if ( fileName == proposedAlt ) {
+ ret.push( lang.errorSameAsFileName );
+ }
+ }
+
+ return ret;
+ };
+
+ ImgAlt.prototype.lang = {"altLabel":"Texto alternativo","errorTooLong":"O texto alternativo é muito longo. Este deve conter no máximo {limit} caracteres, enquanto o seu possui {length}","errorWhitespace":"O texto alternativo não pode conter somente espaços em branco.","errorSameAsFileName":"O texto alternativo da imagem não deve ter o mesmo nome do arquivo da imagem"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'pt-br/ImgAlt', ImgAlt );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/pt-br/ImgAltNonEmpty.js b/plugins/ckeditor/a11ychecker/quickfix/pt-br/ImgAltNonEmpty.js
new file mode 100644
index 0000000..c65cf33
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/pt-br/ImgAltNonEmpty.js
@@ -0,0 +1,44 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'pt-br',
+ name: 'ImgAlt',
+ callback: function( ImgAlt ) {
+
+ /**
+ * Fixes the image with missing alt attribute, requiring non-empty alt.
+ *
+ * @constructor
+ */
+ function ImgAltNonEmpty( issue ) {
+ ImgAlt.call( this, issue );
+ }
+
+ ImgAltNonEmpty.prototype = new ImgAlt();
+ ImgAltNonEmpty.prototype.constructor = ImgAltNonEmpty;
+
+ ImgAltNonEmpty.prototype.validate = function( formAttributes ) {
+ var ret = [],
+ proposedAlt = formAttributes.alt + '';
+
+ if ( !proposedAlt ) {
+ ret.push( this.lang.errorEmpty );
+ }
+
+ if ( !ret.length ) {
+ ret = ImgAlt.prototype.validate.call( this, formAttributes );
+ }
+
+ return ret;
+ };
+
+ ImgAltNonEmpty.prototype.lang = {"altLabel":"Texto alternativo","errorTooLong":"O texto alternativo é muito longo. Este deve conter no máximo {limit} caracteres, enquanto o seu possui {length}","errorWhitespace":"O texto alternativo não pode conter somente espaços em branco.","errorSameAsFileName":"O texto alternativo da imagem não deve ter o mesmo nome do arquivo da imagem","errorEmpty":"O texto alternativo não deve estar vazio"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'pt-br/ImgAltNonEmpty', ImgAltNonEmpty );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/pt-br/LocalizedRepository.js b/plugins/ckeditor/a11ychecker/quickfix/pt-br/LocalizedRepository.js
new file mode 100644
index 0000000..6c23482
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/pt-br/LocalizedRepository.js
@@ -0,0 +1,174 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+define( [ 'quickfix/Repository' ], function( Repository ) {
+ 'use strict';
+
+ /**
+ * This type adds localization support for repository.
+ *
+ * @mixins CKEDITOR.event
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @constructor
+ * @param {String} basePath A path to the directory where QuickFix classes are
+ * stored.
+ */
+ function LocalizedRepository( basePath ) {
+ Repository.call( this, basePath );
+ }
+
+ LocalizedRepository.prototype = new Repository();
+ LocalizedRepository.prototype.constructor = LocalizedRepository;
+
+ LocalizedRepository.prototype._langDictionary = {};
+
+ // An array of arguments from calls that were deferred.
+ var deferredGetCalls = {},
+ languagesRequested = [];
+
+ /**
+ * See {@link CKEDITOR.plugins.a11ychecker.quickFix.Repository#get}. This implementation
+ * adds only `options.langCode` param:
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.LocalizedRepository
+ * @param {Object} options
+ * @param {String} options.langCode Language code of quickFix to be loaded.
+ * @returns {Function}
+ */
+ LocalizedRepository.prototype.get = function( options ) {
+ options.langCode = options.langCode || 'en';
+
+ if ( this.deferGetCall( options.langCode, arguments ) ) {
+ // Call should be deferred, because no lang is available yet.
+ return;
+ }
+
+ if ( !CKEDITOR.plugins.a11ychecker.dev ) {
+ // In case of release code we'll do a trick here.
+ // Each class will be represented as '/' string, that way we
+ // can load multiple language combination with given class.
+ options.name = options.langCode + '/' + options.name;
+ }
+
+ // If lang is available call to the base class.
+ return Repository.prototype.get.call( this, options );
+ };
+
+ /**
+ * Similar to {@link #get} but returns localized instance rather than class.
+ *
+ * Please note that options.callback is mandatory.
+ *
+ * @todo: this method should be also available in generic class.
+ */
+ LocalizedRepository.prototype.getInstance = function( options ) {
+ options = options || {};
+ var name = options.name,
+ langCode = options.langCode || 'en',
+ that = this;
+
+ this.get( {
+ name: name,
+ callback: function( QuickFixType ) {
+ // This callback is guaranteed to be called when dictionary for langCode is fetched.
+ var instance = new QuickFixType( options.issue );
+
+ if ( CKEDITOR.plugins.a11ychecker.dev ) {
+ // We only need to assign lang for dev version, built class will already have this property.
+ instance.lang = that._langDictionary[ langCode ][ name ];
+ }
+
+ options.callback( instance );
+ },
+ langCode: langCode
+ } );
+ };
+
+
+ /**
+ * If needed will defer {@link #get} call.
+ *
+ * @returns {Boolean} `true` if call was deferred, `false` otherwise.
+ */
+ LocalizedRepository.prototype.deferGetCall = function( langCode, getArguments ) {
+ var indexOf = CKEDITOR.tools.indexOf;
+ if ( !CKEDITOR.plugins.a11ychecker.dev || this._langDictionary[ langCode ] ) {
+ // Deferring is always disabled in built version, and if _langDictionary is already
+ // loaded.
+ return false;
+ }
+
+ this._addDeferredGet( langCode, getArguments );
+
+ if ( indexOf( languagesRequested, langCode ) === -1 ) {
+ // This particular language was not requested yet.
+ languagesRequested.push( langCode );
+ CKEDITOR.scriptLoader.load( this.basePath + 'lang/' + langCode + '.js' );
+ }
+
+ return true;
+ };
+
+ /**
+ * Registers a class of given QuickFix.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.LocalizedRepository
+ * @param {String} name QuickFix name.
+ * @param {Function} cls QuickFix type.
+ */
+ LocalizedRepository.prototype.add = function( name, cls ) {
+ return Repository.prototype.add.call( this, name, cls );
+ };
+
+ /**
+ * Method to register language dictionary for developer version.
+ *
+ * In built version languages are already inlined into a QuickFix class file, so there's
+ * no need to execute it.
+ *
+ * @param {Object} dictionary
+ */
+ LocalizedRepository.prototype.lang = function( langCode, dictionary ) {
+ this._langDictionary[ langCode ] = dictionary;
+
+ var getQueue = deferredGetCalls[ langCode ];
+
+ if ( !getQueue ) {
+ // No get calls were queued for that language.
+ return;
+ }
+
+ // All deferred gets should be called in reversed order.
+ for ( var i = getQueue.length - 1; i >= 0; i-- ) {
+ this.get.apply( this, getQueue[ i ] );
+ }
+ };
+
+ LocalizedRepository.prototype._addDeferredGet = function( langCode, getArguments ) {
+ if ( deferredGetCalls[ langCode ] ) {
+ deferredGetCalls[ langCode ].push( getArguments );
+ } else {
+ deferredGetCalls[ langCode ] = [ getArguments ];
+ }
+ };
+
+
+ /**
+ * Function created for tests, returns count of deferred get functions.
+ *
+ * @returns {Number}
+ */
+ LocalizedRepository.prototype._getDeferredGetCount = function( langCode ) {
+ return deferredGetCalls[ langCode ] ? deferredGetCalls[ langCode ].length : 0;
+ };
+
+ /**
+ * Function created for tests, clears deferred get queue.
+ */
+ LocalizedRepository.prototype._clearDeferredGetQueue = function() {
+ deferredGetCalls = {};
+ };
+
+ return LocalizedRepository;
+} );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/pt-br/ParagraphToHeader.js b/plugins/ckeditor/a11ychecker/quickfix/pt-br/ParagraphToHeader.js
new file mode 100644
index 0000000..d1c1ffb
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/pt-br/ParagraphToHeader.js
@@ -0,0 +1,168 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'pt-br',
+ name: 'ElementReplace',
+ callback: function( ElementReplace ) {
+ /**
+ * Replaces provided element with element that a different tag name, preserving its children.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class ParagraphToHeader
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue
+ */
+ function ParagraphToHeader( issue ) {
+ ElementReplace.call( this, issue );
+ }
+
+ ParagraphToHeader.prototype = new ElementReplace();
+ ParagraphToHeader.prototype.constructor = ParagraphToHeader;
+
+ ParagraphToHeader.prototype.getTargetName = function( formAttributes ) {
+ return formAttributes.level;
+ };
+
+ ParagraphToHeader.prototype.display = function( form, editor ) {
+
+ var levelDict = this._getFormHeaderLeves( editor );
+
+ form.setInputs( {
+ level: {
+ type: 'select',
+ label: this.lang.levelLabel,
+ value: 'h' + this._getPreferredLevel( editor ),
+ options: levelDict
+ }
+ } );
+ };
+
+ ParagraphToHeader.prototype.fix = function( formAttributes, callback ) {
+ var that = this;
+ ElementReplace.prototype.fix.call( this, formAttributes, function() {
+ that._removeBoldTag();
+ callback( that );
+ } );
+ };
+
+ /**
+ * Determines preferred heading level for the header that should be cerated.
+ *
+ * @private
+ * @param {CKEDITOR.editor} editor
+ * @returns {Number} Number ranging from `1` to `6`.
+ */
+ ParagraphToHeader.prototype._getPreferredLevel = function( editor ) {
+ var ret = 1,
+ editable = editor.editable(),
+ headerTagRegExp = /^h[1-6]$/i,
+ range = new CKEDITOR.dom.range( editable.getDocument() ),
+ walker,
+ prevElement;
+
+ range.setStartAt( editable, CKEDITOR.POSITION_AFTER_START );
+ range.setEndAt( this.issue.element, CKEDITOR.POSITION_BEFORE_START );
+ walker = new CKEDITOR.dom.walker( range );
+
+ while ( ( prevElement = walker.previous() ) ) {
+ if ( prevElement.getName && prevElement.getName().match( headerTagRegExp ) ) {
+ ret = Number( prevElement.getName()[ 1 ] ) + 1;
+ break;
+ }
+ }
+
+ // WE can't return a higher value than 7.
+ return Math.min( ret, 6 );
+ };
+
+ /**
+ * This method check if issue element contains `` element only as a first and the only child.
+ * If so we'll remove it, but move its children to the `issue.element`.
+ */
+ ParagraphToHeader.prototype._removeBoldTag = function() {
+ var isElementEvaluator = function( el ) {
+ return el.type === CKEDITOR.NODE_ELEMENT;
+ },
+ elem = this.issue.element,
+ innerElement = elem.getFirst( isElementEvaluator ),
+ // If first child element is at the same time last element child, then it means it has only this element.
+ hasSingleElement = innerElement && innerElement.equals( elem.getLast( isElementEvaluator ) ),
+ suspiciousTagNames = [ 'strong', 'b' ];
+
+ if ( hasSingleElement && CKEDITOR.tools.indexOf( suspiciousTagNames, innerElement.getName() ) !== -1 ) {
+ innerElement.moveChildren( elem );
+ innerElement.remove();
+ }
+ };
+
+ /**
+ * Returns minimal and maximal possible header levels for given editor.
+ *
+ * Result will be based on ACF and `config.format_tags`.
+ *
+ * @param {CKEDITOR.editor}
+ * @return {Object} Allowed header level boundaries.
+ * @return {Number} return.min Minimal allowed level.
+ * @return {Number} return.email Maximal allowed level.
+ */
+ ParagraphToHeader.prototype._getPossibleLevels = function( editor ) {
+ var tags = ( editor.config.format_tags || '' ).split( ';' ),
+ ret = {
+ min: 1,
+ max: 6
+ },
+ i;
+
+ // Filtering tags.
+ for ( i = tags.length - 1; i >= 0; i-- ) {
+ // If given tag is not header tag or if it's not allowed by the ACF.
+ if ( !tags[ i ].match( /^h[1-6]$/i ) || !editor.filter.check( tags[ i ] ) ) {
+ tags.splice( i, 1 );
+ } else {
+ tags[ i ] = Number( tags[ i ][ 1 ] );
+ }
+ }
+
+ if ( tags.length ) {
+ // Note if IE8 has to be supported we need to inline sorting here.
+ tags.sort();
+
+ ret.min = tags[ 0 ];
+ ret.max = tags[ tags.length - 1 ];
+ }
+
+ return ret;
+ };
+
+ /**
+ * Returns options dictionary that should be put in form header level select.
+ *
+ * @param {CKEDITOR.editor} editor
+ */
+ ParagraphToHeader.prototype._getFormHeaderLeves = function( editor ) {
+ var dict = {},
+ boundaries = this._getPossibleLevels( editor ),
+ preferredLevel = this._getPreferredLevel( editor );
+
+ for ( var i = boundaries.min; i <= boundaries.max; i++ ) {
+ dict[ 'h' + i ] = 'H' + i;
+ }
+
+ if ( dict[ 'h' + preferredLevel ] ) {
+ dict[ 'h' + preferredLevel ] += ( ' ' + this.lang.suggested );
+ }
+
+ return dict;
+ };
+
+
+ ParagraphToHeader.prototype.lang = {"levelLabel":"Nível de cabeçalho","suggested":"(Sugerido)"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'pt-br/ParagraphToHeader', ParagraphToHeader );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/quickfix/pt-br/QuickFix.js b/plugins/ckeditor/a11ychecker/quickfix/pt-br/QuickFix.js
new file mode 100644
index 0000000..698ea24
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/pt-br/QuickFix.js
@@ -0,0 +1,90 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+(function() {
+ 'use strict';
+
+ /**
+ * QuickFix type for the QuickFix objects.
+ *
+ * # Overview
+ *
+ * It encapsulates logic responsible for fixing Accessibility issue.
+ *
+ * ## Working with QuickFix objects
+ *
+ * ### Adding controls to the QuickFix form
+ *
+ * Controls can be added in {@link #display} method using {@link CKEDITOR.plugins.a11ychecker.ViewerForm}
+ * methods.
+ *
+ * ### Executing the fix
+ *
+ * The fixing logic is placed in {@link #fix} method, so you need to simply call it when
+ * you're sure to apply the fix.
+ *
+ * @since 4.6.0
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class QuickFix
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function QuickFix( issue ) {
+ this.issue = issue;
+ }
+
+ QuickFix.prototype = {
+ /**
+ * @member CKEDITOR.plugins.a11ychecker.quickFix.QuickFix
+ * @property {CKEDITOR.plugins.a11ychecker.Issue} issue Issue object that QuickFix was created for.
+ */
+ issue: null
+ };
+
+ QuickFix.prototype.constructor = QuickFix;
+
+ QuickFix.prototype.display = function( form, editor ) {
+ };
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ QuickFix.prototype.fix = function( formAttributes, callback ) {
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ /**
+ * Method used to validate data placed in form.
+ *
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @returns {String[]} Array of error messages. If array is empty, then it means no errors ocurred.
+ */
+ QuickFix.prototype.validate = function( formAttributes ) {
+ return [];
+ };
+
+ /**
+ * A method called to mark the selection on object before quickfix is applied.
+ *
+ * @param {CKEDITOR.dom.selection} selection Editor selection.
+ */
+ QuickFix.prototype.markSelection = function( editor, selection ) {
+ var rng = editor.createRange();
+ rng.setStartBefore( this.issue.element );
+ rng.setEndAfter( this.issue.element );
+ selection.selectRanges( [ rng ] );
+ };
+
+ QuickFix.prototype.lang = {};
+
+ QuickFix.prototype.lang = {};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'pt-br/QuickFix', QuickFix );
+}());
diff --git a/plugins/ckeditor/a11ychecker/quickfix/pt-br/TableHeaders.js b/plugins/ckeditor/a11ychecker/quickfix/pt-br/TableHeaders.js
new file mode 100644
index 0000000..d75e0fa
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/quickfix/pt-br/TableHeaders.js
@@ -0,0 +1,98 @@
+/**
+ * @license Copyright (c) 2014-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+( function() {
+ 'use strict';
+
+ CKEDITOR.plugins.a11ychecker.quickFixes.get( { langCode: 'pt-br',
+ name: 'QuickFix',
+ callback: function( QuickFix ) {
+ /**
+ * QuickFix adding a caption in the `table` element.
+ *
+ * @member CKEDITOR.plugins.a11ychecker.quickFix
+ * @class TableHeaders
+ * @constructor
+ * @param {CKEDITOR.plugins.a11ychecker.Issue} issue Issue QuickFix is created for.
+ */
+ function TableHeaders( issue ) {
+ QuickFix.call( this, issue );
+ }
+
+ TableHeaders.prototype = new QuickFix();
+
+ TableHeaders.prototype.constructor = TableHeaders;
+
+ TableHeaders.prototype.display = function( form ) {
+ var lang = this.lang;
+
+ form.setInputs( {
+ position: {
+ type: 'select',
+ label: lang.positionLabel,
+ value: 'row',
+ options: {
+ 'both': lang.positionBoth,
+ 'row': lang.positionHorizontally,
+ 'col': lang.positionVertically
+ }
+ }
+ } );
+ };
+
+ /**
+ * @param {Object} formAttributes Object containing serialized form inputs. See
+ * {@link CKEDITOR.plugins.a11ychecker.ViewerForm#serialize}.
+ * @param {Function} callback Function to be called when a fix was applied. Gets QuickFix object
+ * as a first parameter.
+ */
+ TableHeaders.prototype.fix = function( formAttributes, callback ) {
+ var table = this.issue.element,
+ headers = formAttributes.position,
+ newCell,
+ row,
+ i;
+ // Following code copied from CKEditor plugins/table/dialogs/table.js file.
+
+ // Should we make all first cells in a row TH?
+ if ( headers == 'col' || headers == 'both' ) {
+ for ( row = 0; row < table.$.rows.length; row++ ) {
+ if ( !table.$.rows[ row ].cells.length ) {
+ continue;
+ }
+
+ newCell = new CKEDITOR.dom.element( table.$.rows[ row ].cells[ 0 ] );
+ newCell.renameNode( 'th' );
+ newCell.setAttribute( 'scope', 'row' );
+ }
+ }
+
+ if ( !table.$.tHead && ( headers == 'row' || headers == 'both' ) ) {
+ var thead = new CKEDITOR.dom.element( table.$.createTHead() );
+ var tbody = table.getElementsByTag( 'tbody' ).getItem( 0 );
+ var theRow = tbody.getElementsByTag( 'tr' ).getItem( 0 );
+
+ // Change TD to TH:
+ for ( i = 0; i < theRow.getChildCount(); i++ ) {
+ var th = theRow.getChild( i );
+ // Skip bookmark nodes. (#6155)
+ if ( th.type == CKEDITOR.NODE_ELEMENT && !th.data( 'cke-bookmark' ) ) {
+ th.renameNode( 'th' );
+ th.setAttribute( 'scope', 'col' );
+ }
+ }
+ thead.append( theRow.remove() );
+ }
+
+ if ( callback ) {
+ callback( this );
+ }
+ };
+
+ TableHeaders.prototype.lang = {"positionLabel":"Posição","positionHorizontally":"Horizontal","positionVertically":"Vertical","positionBoth":"Ambos"};
+ CKEDITOR.plugins.a11ychecker.quickFixes.add( 'pt-br/TableHeaders', TableHeaders );
+ }
+ } );
+}() );
diff --git a/plugins/ckeditor/a11ychecker/skins/moono-lisa/a11ychecker.css b/plugins/ckeditor/a11ychecker/skins/moono-lisa/a11ychecker.css
new file mode 100644
index 0000000..5156640
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/skins/moono-lisa/a11ychecker.css
@@ -0,0 +1,4 @@
+/*!
+Copyright (c) 20032014-2018, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/license
+*/a.cke_a11yc_ui_button{display:inline-block;*display:inline;*zoom:1;padding:4px;margin:0;text-align:center;color:#484848;vertical-align:middle;border:1px solid #bcbcbc;background:#f8f8f8;-webkit-border-radius:3px;-webkit-background-clip:padding-box;-moz-border-radius:3px;-moz-background-clip:padding;border-radius:3px;background-clip:padding-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}a.cke_a11yc_ui_button:hover{cursor:pointer;border-color:#bcbcbc;background:#fff}a.cke_a11yc_ui_button:focus,a.cke_a11yc_ui_button:active{border-color:#139ff7;outline:none}a.cke_a11yc_ui_button>span{padding:0 6px}a.cke_a11yc_ui_button>span:hover{cursor:pointer}a.cke_a11yc_ui_button_ok{color:#fff;border-color:#09863e;background:#09863e}a.cke_a11yc_ui_button_ok:hover{border-color:#53aa78;background:#53aa78}a.cke_a11yc_ui_button_ok>span{color:#fff}select.cke_a11yc_ui_input_select{height:25px;line-height:25px;background-color:#fff;border:1px solid #c9cccf;padding:3px 3px 3px 6px;outline:none;-webkit-border-radius:3px;-webkit-background-clip:padding-box;-moz-border-radius:3px;-moz-background-clip:padding;border-radius:3px;background-clip:padding-box}select.cke_a11yc_ui_input_select:focus{outline:none;border:1px solid #139ff7}.cke_a11yc_ui_navigation{display:table;overflow:hidden;width:100%;background:#eee;outline:1px solid #ddd;border-collapse:separate;border-spacing:10px}.cke_a11yc_ui_navigation.cke_a11yc_testability_notice{background-color:#fefefe}.cke_a11yc_ui_navigation.cke_a11yc_testability_warning{background-color:#fffacd}.cke_a11yc_ui_navigation.cke_a11yc_testability_error{background-color:#ffe4e4}.cke_a11yc_ui_navigation .cke_a11yc_ui_button_wrapper,.cke_a11yc_ui_navigation .cke_a11yc_ui_navigation_counter{display:table-cell}.cke_a11yc_ui_navigation .cke_a11yc_ui_navigation_counter{width:100%;font-size:14px;font-weight:bold;vertical-align:middle;text-align:left;white-space:normal}a.cke_a11yc_ui_previous span,a.cke_a11yc_ui_next span{background-repeat:no-repeat}a.cke_a11yc_ui_next>span{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAKQWlDQ1BJQ0MgUHJvZmlsZQAASA2dlndUU9kWh8+9N73QEiIgJfQaegkg0jtIFQRRiUmAUAKGhCZ2RAVGFBEpVmRUwAFHhyJjRRQLg4Ji1wnyEFDGwVFEReXdjGsJ7601896a/cdZ39nnt9fZZ+9917oAUPyCBMJ0WAGANKFYFO7rwVwSE8vE9wIYEAEOWAHA4WZmBEf4RALU/L09mZmoSMaz9u4ugGS72yy/UCZz1v9/kSI3QyQGAApF1TY8fiYX5QKUU7PFGTL/BMr0lSkyhjEyFqEJoqwi48SvbPan5iu7yZiXJuShGlnOGbw0noy7UN6aJeGjjAShXJgl4GejfAdlvVRJmgDl9yjT0/icTAAwFJlfzOcmoWyJMkUUGe6J8gIACJTEObxyDov5OWieAHimZ+SKBIlJYqYR15hp5ejIZvrxs1P5YjErlMNN4Yh4TM/0tAyOMBeAr2+WRQElWW2ZaJHtrRzt7VnW5mj5v9nfHn5T/T3IevtV8Sbsz55BjJ5Z32zsrC+9FgD2JFqbHbO+lVUAtG0GQOXhrE/vIADyBQC03pzzHoZsXpLE4gwnC4vs7GxzAZ9rLivoN/ufgm/Kv4Y595nL7vtWO6YXP4EjSRUzZUXlpqemS0TMzAwOl89k/fcQ/+PAOWnNycMsnJ/AF/GF6FVR6JQJhIlou4U8gViQLmQKhH/V4X8YNicHGX6daxRodV8AfYU5ULhJB8hvPQBDIwMkbj96An3rWxAxCsi+vGitka9zjzJ6/uf6Hwtcim7hTEEiU+b2DI9kciWiLBmj34RswQISkAd0oAo0gS4wAixgDRyAM3AD3iAAhIBIEAOWAy5IAmlABLJBPtgACkEx2AF2g2pwANSBetAEToI2cAZcBFfADXALDIBHQAqGwUswAd6BaQiC8BAVokGqkBakD5lC1hAbWgh5Q0FQOBQDxUOJkBCSQPnQJqgYKoOqoUNQPfQjdBq6CF2D+qAH0CA0Bv0BfYQRmALTYQ3YALaA2bA7HAhHwsvgRHgVnAcXwNvhSrgWPg63whfhG/AALIVfwpMIQMgIA9FGWAgb8URCkFgkAREha5EipAKpRZqQDqQbuY1IkXHkAwaHoWGYGBbGGeOHWYzhYlZh1mJKMNWYY5hWTBfmNmYQM4H5gqVi1bGmWCesP3YJNhGbjS3EVmCPYFuwl7ED2GHsOxwOx8AZ4hxwfrgYXDJuNa4Etw/XjLuA68MN4SbxeLwq3hTvgg/Bc/BifCG+Cn8cfx7fjx/GvyeQCVoEa4IPIZYgJGwkVBAaCOcI/YQRwjRRgahPdCKGEHnEXGIpsY7YQbxJHCZOkxRJhiQXUiQpmbSBVElqIl0mPSa9IZPJOmRHchhZQF5PriSfIF8lD5I/UJQoJhRPShxFQtlOOUq5QHlAeUOlUg2obtRYqpi6nVpPvUR9Sn0vR5Mzl/OX48mtk6uRa5Xrl3slT5TXl3eXXy6fJ18hf0r+pvy4AlHBQMFTgaOwVqFG4bTCPYVJRZqilWKIYppiiWKD4jXFUSW8koGStxJPqUDpsNIlpSEaQtOledK4tE20Otpl2jAdRzek+9OT6cX0H+i99AllJWVb5SjlHOUa5bPKUgbCMGD4M1IZpYyTjLuMj/M05rnP48/bNq9pXv+8KZX5Km4qfJUilWaVAZWPqkxVb9UU1Z2qbapP1DBqJmphatlq+9Uuq43Pp893ns+dXzT/5PyH6rC6iXq4+mr1w+o96pMamhq+GhkaVRqXNMY1GZpumsma5ZrnNMe0aFoLtQRa5VrntV4wlZnuzFRmJbOLOaGtru2nLdE+pN2rPa1jqLNYZ6NOs84TXZIuWzdBt1y3U3dCT0svWC9fr1HvoT5Rn62fpL9Hv1t/ysDQINpgi0GbwaihiqG/YZ5ho+FjI6qRq9Eqo1qjO8Y4Y7ZxivE+41smsImdSZJJjclNU9jU3lRgus+0zwxr5mgmNKs1u8eisNxZWaxG1qA5wzzIfKN5m/krCz2LWIudFt0WXyztLFMt6ywfWSlZBVhttOqw+sPaxJprXWN9x4Zq42Ozzqbd5rWtqS3fdr/tfTuaXbDdFrtOu8/2DvYi+yb7MQc9h3iHvQ732HR2KLuEfdUR6+jhuM7xjOMHJ3snsdNJp9+dWc4pzg3OowsMF/AX1C0YctFx4bgccpEuZC6MX3hwodRV25XjWuv6zE3Xjed2xG3E3dg92f24+ysPSw+RR4vHlKeT5xrPC16Il69XkVevt5L3Yu9q76c+Oj6JPo0+E752vqt9L/hh/QL9dvrd89fw5/rX+08EOASsCegKpARGBFYHPgsyCRIFdQTDwQHBu4IfL9JfJFzUFgJC/EN2hTwJNQxdFfpzGC4sNKwm7Hm4VXh+eHcELWJFREPEu0iPyNLIR4uNFksWd0bJR8VF1UdNRXtFl0VLl1gsWbPkRoxajCCmPRYfGxV7JHZyqffS3UuH4+ziCuPuLjNclrPs2nK15anLz66QX8FZcSoeGx8d3xD/iRPCqeVMrvRfuXflBNeTu4f7kufGK+eN8V34ZfyRBJeEsoTRRJfEXYljSa5JFUnjAk9BteB1sl/ygeSplJCUoykzqdGpzWmEtPi000IlYYqwK10zPSe9L8M0ozBDuspp1e5VE6JA0ZFMKHNZZruYjv5M9UiMJJslg1kLs2qy3mdHZZ/KUcwR5vTkmuRuyx3J88n7fjVmNXd1Z752/ob8wTXuaw6thdauXNu5Tnddwbrh9b7rj20gbUjZ8MtGy41lG99uit7UUaBRsL5gaLPv5sZCuUJR4b0tzlsObMVsFWzt3WazrWrblyJe0fViy+KK4k8l3JLr31l9V/ndzPaE7b2l9qX7d+B2CHfc3em681iZYlle2dCu4F2t5czyovK3u1fsvlZhW3FgD2mPZI+0MqiyvUqvakfVp+qk6oEaj5rmvep7t+2d2sfb17/fbX/TAY0DxQc+HhQcvH/I91BrrUFtxWHc4azDz+ui6rq/Z39ff0TtSPGRz0eFR6XHwo911TvU1zeoN5Q2wo2SxrHjccdv/eD1Q3sTq+lQM6O5+AQ4ITnx4sf4H++eDDzZeYp9qukn/Z/2ttBailqh1tzWibakNml7THvf6YDTnR3OHS0/m/989Iz2mZqzymdLz5HOFZybOZ93fvJCxoXxi4kXhzpXdD66tOTSna6wrt7LgZevXvG5cqnbvfv8VZerZ645XTt9nX297Yb9jdYeu56WX+x+aem172296XCz/ZbjrY6+BX3n+l37L972un3ljv+dGwOLBvruLr57/17cPel93v3RB6kPXj/Mejj9aP1j7OOiJwpPKp6qP6391fjXZqm99Oyg12DPs4hnj4a4Qy//lfmvT8MFz6nPK0a0RupHrUfPjPmM3Xqx9MXwy4yX0+OFvyn+tveV0auffnf7vWdiycTwa9HrmT9K3qi+OfrW9m3nZOjk03dp76anit6rvj/2gf2h+2P0x5Hp7E/4T5WfjT93fAn88ngmbWbm3/eE8/syOll+AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAhUlEQVQIHWM2Nzc/JC4u/hwIXjAwMLAAMTMQMwExA6OlpeV/EOPfv39Hf/782XbhwoWDQO5fEIZLghSAAFDRkd+/f7ecO3duP4YkSMH///+vAE2JAdkBB0BdV4G6OoC61gEF/4AlkQQ3AgXB9gHpfwwmJiaRQAY3EHMBMScQswMxKxAzAwAhokLukwaZHgAAAABJRU5ErkJggg==);background-position:right center;padding-right:16px;margin-right:7px}a.cke_a11yc_ui_previous>span{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAKQWlDQ1BJQ0MgUHJvZmlsZQAASA2dlndUU9kWh8+9N73QEiIgJfQaegkg0jtIFQRRiUmAUAKGhCZ2RAVGFBEpVmRUwAFHhyJjRRQLg4Ji1wnyEFDGwVFEReXdjGsJ7601896a/cdZ39nnt9fZZ+9917oAUPyCBMJ0WAGANKFYFO7rwVwSE8vE9wIYEAEOWAHA4WZmBEf4RALU/L09mZmoSMaz9u4ugGS72yy/UCZz1v9/kSI3QyQGAApF1TY8fiYX5QKUU7PFGTL/BMr0lSkyhjEyFqEJoqwi48SvbPan5iu7yZiXJuShGlnOGbw0noy7UN6aJeGjjAShXJgl4GejfAdlvVRJmgDl9yjT0/icTAAwFJlfzOcmoWyJMkUUGe6J8gIACJTEObxyDov5OWieAHimZ+SKBIlJYqYR15hp5ejIZvrxs1P5YjErlMNN4Yh4TM/0tAyOMBeAr2+WRQElWW2ZaJHtrRzt7VnW5mj5v9nfHn5T/T3IevtV8Sbsz55BjJ5Z32zsrC+9FgD2JFqbHbO+lVUAtG0GQOXhrE/vIADyBQC03pzzHoZsXpLE4gwnC4vs7GxzAZ9rLivoN/ufgm/Kv4Y595nL7vtWO6YXP4EjSRUzZUXlpqemS0TMzAwOl89k/fcQ/+PAOWnNycMsnJ/AF/GF6FVR6JQJhIlou4U8gViQLmQKhH/V4X8YNicHGX6daxRodV8AfYU5ULhJB8hvPQBDIwMkbj96An3rWxAxCsi+vGitka9zjzJ6/uf6Hwtcim7hTEEiU+b2DI9kciWiLBmj34RswQISkAd0oAo0gS4wAixgDRyAM3AD3iAAhIBIEAOWAy5IAmlABLJBPtgACkEx2AF2g2pwANSBetAEToI2cAZcBFfADXALDIBHQAqGwUswAd6BaQiC8BAVokGqkBakD5lC1hAbWgh5Q0FQOBQDxUOJkBCSQPnQJqgYKoOqoUNQPfQjdBq6CF2D+qAH0CA0Bv0BfYQRmALTYQ3YALaA2bA7HAhHwsvgRHgVnAcXwNvhSrgWPg63whfhG/AALIVfwpMIQMgIA9FGWAgb8URCkFgkAREha5EipAKpRZqQDqQbuY1IkXHkAwaHoWGYGBbGGeOHWYzhYlZh1mJKMNWYY5hWTBfmNmYQM4H5gqVi1bGmWCesP3YJNhGbjS3EVmCPYFuwl7ED2GHsOxwOx8AZ4hxwfrgYXDJuNa4Etw/XjLuA68MN4SbxeLwq3hTvgg/Bc/BifCG+Cn8cfx7fjx/GvyeQCVoEa4IPIZYgJGwkVBAaCOcI/YQRwjRRgahPdCKGEHnEXGIpsY7YQbxJHCZOkxRJhiQXUiQpmbSBVElqIl0mPSa9IZPJOmRHchhZQF5PriSfIF8lD5I/UJQoJhRPShxFQtlOOUq5QHlAeUOlUg2obtRYqpi6nVpPvUR9Sn0vR5Mzl/OX48mtk6uRa5Xrl3slT5TXl3eXXy6fJ18hf0r+pvy4AlHBQMFTgaOwVqFG4bTCPYVJRZqilWKIYppiiWKD4jXFUSW8koGStxJPqUDpsNIlpSEaQtOledK4tE20Otpl2jAdRzek+9OT6cX0H+i99AllJWVb5SjlHOUa5bPKUgbCMGD4M1IZpYyTjLuMj/M05rnP48/bNq9pXv+8KZX5Km4qfJUilWaVAZWPqkxVb9UU1Z2qbapP1DBqJmphatlq+9Uuq43Pp893ns+dXzT/5PyH6rC6iXq4+mr1w+o96pMamhq+GhkaVRqXNMY1GZpumsma5ZrnNMe0aFoLtQRa5VrntV4wlZnuzFRmJbOLOaGtru2nLdE+pN2rPa1jqLNYZ6NOs84TXZIuWzdBt1y3U3dCT0svWC9fr1HvoT5Rn62fpL9Hv1t/ysDQINpgi0GbwaihiqG/YZ5ho+FjI6qRq9Eqo1qjO8Y4Y7ZxivE+41smsImdSZJJjclNU9jU3lRgus+0zwxr5mgmNKs1u8eisNxZWaxG1qA5wzzIfKN5m/krCz2LWIudFt0WXyztLFMt6ywfWSlZBVhttOqw+sPaxJprXWN9x4Zq42Ozzqbd5rWtqS3fdr/tfTuaXbDdFrtOu8/2DvYi+yb7MQc9h3iHvQ732HR2KLuEfdUR6+jhuM7xjOMHJ3snsdNJp9+dWc4pzg3OowsMF/AX1C0YctFx4bgccpEuZC6MX3hwodRV25XjWuv6zE3Xjed2xG3E3dg92f24+ysPSw+RR4vHlKeT5xrPC16Il69XkVevt5L3Yu9q76c+Oj6JPo0+E752vqt9L/hh/QL9dvrd89fw5/rX+08EOASsCegKpARGBFYHPgsyCRIFdQTDwQHBu4IfL9JfJFzUFgJC/EN2hTwJNQxdFfpzGC4sNKwm7Hm4VXh+eHcELWJFREPEu0iPyNLIR4uNFksWd0bJR8VF1UdNRXtFl0VLl1gsWbPkRoxajCCmPRYfGxV7JHZyqffS3UuH4+ziCuPuLjNclrPs2nK15anLz66QX8FZcSoeGx8d3xD/iRPCqeVMrvRfuXflBNeTu4f7kufGK+eN8V34ZfyRBJeEsoTRRJfEXYljSa5JFUnjAk9BteB1sl/ygeSplJCUoykzqdGpzWmEtPi000IlYYqwK10zPSe9L8M0ozBDuspp1e5VE6JA0ZFMKHNZZruYjv5M9UiMJJslg1kLs2qy3mdHZZ/KUcwR5vTkmuRuyx3J88n7fjVmNXd1Z752/ob8wTXuaw6thdauXNu5Tnddwbrh9b7rj20gbUjZ8MtGy41lG99uit7UUaBRsL5gaLPv5sZCuUJR4b0tzlsObMVsFWzt3WazrWrblyJe0fViy+KK4k8l3JLr31l9V/ndzPaE7b2l9qX7d+B2CHfc3em681iZYlle2dCu4F2t5czyovK3u1fsvlZhW3FgD2mPZI+0MqiyvUqvakfVp+qk6oEaj5rmvep7t+2d2sfb17/fbX/TAY0DxQc+HhQcvH/I91BrrUFtxWHc4azDz+ui6rq/Z39ff0TtSPGRz0eFR6XHwo911TvU1zeoN5Q2wo2SxrHjccdv/eD1Q3sTq+lQM6O5+AQ4ITnx4sf4H++eDDzZeYp9qukn/Z/2ttBailqh1tzWibakNml7THvf6YDTnR3OHS0/m/989Iz2mZqzymdLz5HOFZybOZ93fvJCxoXxi4kXhzpXdD66tOTSna6wrt7LgZevXvG5cqnbvfv8VZerZ645XTt9nX297Yb9jdYeu56WX+x+aem172296XCz/ZbjrY6+BX3n+l37L972un3ljv+dGwOLBvruLr57/17cPel93v3RB6kPXj/Mejj9aP1j7OOiJwpPKp6qP6391fjXZqm99Oyg12DPs4hnj4a4Qy//lfmvT8MFz6nPK0a0RupHrUfPjPmM3Xqx9MXwy4yX0+OFvyn+tveV0auffnf7vWdiycTwa9HrmT9K3qi+OfrW9m3nZOjk03dp76anit6rvj/2gf2h+2P0x5Hp7E/4T5WfjT93fAn88ngmbWbm3/eE8/syOll+AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAhklEQVQIHWNkYGBgBmImJMwIZDOamJj4soAYUAmQImZjY+MgVlbWciBbGSQJ0gUSDAUKVjAyMmoA+Qz/////xWJkZKTLxsa2GCioCRJEBszPnz9/KyIicoeZmVkJqEAWSfIvyD5WIAbbp6en58TJyVnFxMRkATIWJAmzF+5iAwMDew4OjhIAregW7mj1jM8AAAAASUVORK5CYII=);background-position:6px center;padding-left:23px}.cke_a11yc_ui_desc_wrapper{padding:0 10px;margin:15px 0 10px}.cke_a11yc_ui_desc_title,.cke_a11yc_ui_desc_info{white-space:normal}.cke_a11yc_ui_desc_title{font-size:14px;font-weight:bold}.cke_a11yc_ui_desc_info{color:#6e6e6e;margin-top:10px;line-height:1.4em}.cke_a11yc_ui_desc_info code{font-family:monospace;padding:1px 2px;background:#eee;border:1px solid #ccc;-webkit-border-radius:2px;-webkit-background-clip:padding-box;-moz-border-radius:2px;-moz-background-clip:padding;border-radius:2px;background-clip:padding-box;color:inherit}.cke_a11yc_ui_desc_info a{color:#00b2ce;text-decoration:underline}.cke_a11yc_ui_form{margin:10px 0 0;overflow:hidden}.cke_a11yc_ui_form_fieldset{width:100%;display:table;border-collapse:separate;border-spacing:10px 0}.cke_a11yc_ui_form_fieldset:not(:empty){margin-bottom:10px}.cke_a11yc_ui_form_actionset{width:100%;display:table;border-collapse:separate;border-spacing:10px}.cke_a11yc_ui_form_actionset .cke_a11yc_ui_button_wrapper{display:table-cell}.cke_a11yc_ui_form .cke_a11yc_ui_button_ok,.cke_a11yc_ui_form .cke_a11yc_ui_button_ok_wrapper{width:100%}.cke_a11yc_ui_input_label{padding-right:20px;width:10%}.cke_a11yc_ui_input_label:after{content:':'}.cke_a11yc_ui_input_wrapper{display:table-row}.cke_a11yc_ui_input_wrapper+.cke_a11yc_ui_input_wrapper{border-top:10px solid transparent}.cke_a11yc_ui_input_wrapper .cke_a11yc_ui_input,.cke_a11yc_ui_input_wrapper .cke_a11yc_ui_input_label{display:table-cell}.cke_a11yc_ui_input_wrapper .cke_a11yc_ui_input_text,.cke_a11yc_ui_input_wrapper .cke_a11yc_ui_input_select{width:100%}input.cke_a11yc_ui_input_text{background-color:#fff;border:1px solid #c9cccf;padding:4px 6px;outline:none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-border-radius:3px;-webkit-background-clip:padding-box;-moz-border-radius:3px;-moz-background-clip:padding;border-radius:3px;background-clip:padding-box}input.cke_a11yc_ui_input_text:hover{border:1px solid #aeb3b9}input.cke_a11yc_ui_input_text:focus{outline:none;border:1px solid #139ff7}.cke_a11yc_ui_listening{display:none;overflow:hidden;padding:10px}.cke_a11yc_ui_listening p{white-space:normal}.cke_a11yc_ui_listening strong{font-weight:bold}.cke_a11yc_ui_listening .cke_a11yc_ui_button{cursor:pointer}.cke_a11yc_ui_listening a.cke_a11yc_ui_button{display:block;overflow:hidden;padding-left:15px;margin-top:10px;position:relative}.cke_balloon.cke_a11yc_mode_listening{-webkit-transition:0.3s ease-in-out;-moz-transition:0.3s ease-in-out;-o-transition:0.3s ease-in-out;transition:0.3s ease-in-out}.cke_balloon.cke_a11yc_mode_listening .cke_a11yc_ui_navigation,.cke_balloon.cke_a11yc_mode_listening .cke_a11yc_ui_desc_wrapper,.cke_balloon.cke_a11yc_mode_listening .cke_a11yc_ui_form,.cke_balloon.cke_a11yc_mode_listening .cke_balloon_triangle_outer{display:none}.cke_balloon.cke_a11yc_mode_listening .cke_a11yc_ui_listening{display:block}.cke_hc select:focus,.cke_hc input:focus,.cke_hc a.cke_a11yc_ui_button:focus{border-width:3px}.cke_hc select:focus.cke_a11yc_ui_button,.cke_hc input:focus.cke_a11yc_ui_button,.cke_hc a.cke_a11yc_ui_button:focus.cke_a11yc_ui_button{padding:2px}.cke_hc select:focus.cke_a11yc_ui_input_select,.cke_hc input:focus.cke_a11yc_ui_input_select,.cke_hc a.cke_a11yc_ui_button:focus.cke_a11yc_ui_input_select{padding:1px 1px 1px 4px}.cke_hc select:focus.cke_a11yc_ui_input_text,.cke_hc input:focus.cke_a11yc_ui_input_text,.cke_hc a.cke_a11yc_ui_button:focus.cke_a11yc_ui_input_text{padding:2px 4px}.cke_a11yc_ui_button_wrapper a.cke_a11yc_ui_button{padding:10px 5px;-webkit-border-radius:2px;-webkit-background-clip:padding-box;-moz-border-radius:2px;-moz-background-clip:padding;border-radius:2px;background-clip:padding-box}.cke_a11yc_ui_button_wrapper a.cke_a11yc_ui_button span{font-size:15px;line-height:16px}.cke_a11yc_ui_button_wrapper a.cke_a11yc_ui_button:focus,.cke_a11yc_ui_button_wrapper a.cke_a11yc_ui_button:active{padding:9px 4px;border-width:2px}.cke_a11yc_ui_button_wrapper a.cke_a11yc_ui_button_ignore{min-width:100px}a.cke_a11yc_ui_button_ok:focus{box-shadow:inset 0 0 0 2px #fff}.cke_a11yc_ui_navigation{padding:0 6px;margin:1px 0 0 -6px}.cke_a11yc_ui_navigation a.cke_a11yc_ui_button{position:relative}.cke_a11yc_ui_navigation a.cke_a11yc_ui_button:focus,.cke_a11yc_ui_navigation a.cke_a11yc_ui_button:active{border:solid 2px #139ff7;z-index:1}.cke_a11yc_ui_navigation a.cke_a11yc_ui_button:hover,.cke_a11yc_ui_navigation a.cke_a11yc_ui_button:hover>span{background-color:#fff}.cke_a11yc_ui_navigation a.cke_a11yc_ui_previous>span,.cke_a11yc_ui_navigation a.cke_a11yc_ui_next>span{background:none;padding:0;margin:0}.cke_a11yc_ui_navigation a.cke_a11yc_ui_previous>span>span,.cke_a11yc_ui_navigation a.cke_a11yc_ui_next>span>span{display:none}.cke_a11yc_ui_navigation a.cke_a11yc_ui_previous{padding:9px 14px 9px 6px}.cke_a11yc_ui_navigation a.cke_a11yc_ui_previous:focus,.cke_a11yc_ui_navigation a.cke_a11yc_ui_previous:active{padding:8px 13px 8px 5px}.cke_a11yc_ui_navigation a.cke_a11yc_ui_previous>span:before{content:'';display:inline-block;width:0;height:0;border:6px solid transparent;vertical-align:middle}.cke_a11yc_ui_navigation a.cke_a11yc_ui_next{padding:9px 6px 9px 14px;margin-left:-11px}.cke_a11yc_ui_navigation a.cke_a11yc_ui_next:focus,.cke_a11yc_ui_navigation a.cke_a11yc_ui_next:active{padding:8px 5px 8px 13px}.cke_a11yc_ui_navigation a.cke_a11yc_ui_next>span:after{content:'';display:inline-block;width:0;height:0;border:6px solid transparent;vertical-align:middle}.cke_a11yc_ui_navigation.cke_a11yc_testability_notice{outline-color:#d1d1d1}.cke_a11yc_ui_navigation.cke_a11yc_testability_notice .cke_a11yc_ui_button{border-color:#d1d1d1;background-color:#fafafa}.cke_a11yc_ui_navigation.cke_a11yc_testability_notice a.cke_a11yc_ui_previous>span:before{border-right-color:#797979}.cke_a11yc_ui_navigation.cke_a11yc_testability_notice a.cke_a11yc_ui_next>span:after{border-left-color:#797979}.cke_a11yc_ui_navigation.cke_a11yc_testability_notice .cke_a11yc_ui_navigation_counter{color:#797979}.cke_a11yc_ui_navigation.cke_a11yc_testability_warning{outline-color:#c9c597}.cke_a11yc_ui_navigation.cke_a11yc_testability_warning .cke_a11yc_ui_button{border-color:#c9c597;background-color:#fffffb}.cke_a11yc_ui_navigation.cke_a11yc_testability_warning a.cke_a11yc_ui_previous>span:before{border-right-color:#858048}.cke_a11yc_ui_navigation.cke_a11yc_testability_warning a.cke_a11yc_ui_next>span:after{border-left-color:#858048}.cke_a11yc_ui_navigation.cke_a11yc_testability_warning .cke_a11yc_ui_navigation_counter{color:#858048}.cke_a11yc_ui_navigation.cke_a11yc_testability_error{outline-color:#e9b6b6}.cke_a11yc_ui_navigation.cke_a11yc_testability_error .cke_a11yc_ui_button{border-color:#e9b6b6;background-color:#fffbfb}.cke_a11yc_ui_navigation.cke_a11yc_testability_error a.cke_a11yc_ui_previous>span:before{border-right-color:#be5555}.cke_a11yc_ui_navigation.cke_a11yc_testability_error a.cke_a11yc_ui_next>span:after{border-left-color:#be5555}.cke_a11yc_ui_navigation.cke_a11yc_testability_error .cke_a11yc_ui_navigation_counter{color:#be5555}.cke_a11yc_ui_desc_wrapper{margin-top:30px}.cke_a11yc_ui_desc_title{color:#484848}.cke_a11yc_ui_form{margin-top:20px}.cke_a11yc_ui_form_fieldset,.cke_a11yc_ui_form_actionset{margin-bottom:0}.cke_a11yc_ui_form .cke_a11yc_ui_button_ok{width:98%}.cke_a11yc_ui_input_label{color:#4b4b4b;font-size:14px;padding-right:0}input.cke_a11yc_ui_input_text{padding:6px;-webkit-border-radius:2px;-webkit-background-clip:padding-box;-moz-border-radius:2px;-moz-background-clip:padding;border-radius:2px;background-clip:padding-box}input.cke_a11yc_ui_input_text:hover{border:1px solid #c9cccf}input.cke_a11yc_ui_input_text:focus{border:2px solid #139ff7;padding:5px}select.cke_a11yc_ui_input_select{height:28px;line-height:28px;padding:5px 3px 4px 6px;border:1px solid #eee;-webkit-border-radius:2px;-webkit-background-clip:padding-box;-moz-border-radius:2px;-moz-background-clip:padding;border-radius:2px;background-clip:padding-box;-webkit-box-shadow:inset 0 0 0 1px #c9cccf;-moz-box-shadow:inset 0 0 0 1px #c9cccf;box-shadow:inset 0 0 0 1px #c9cccf}select.cke_a11yc_ui_input_select:focus{border-color:#139ff7;-webkit-box-shadow:inset 0 0 0 1px #139ff7;-moz-box-shadow:inset 0 0 0 1px #139ff7;box-shadow:inset 0 0 0 1px #139ff7}.cke_a11yc_ui_listening p{padding:0 5px;text-align:center}.cke_a11yc_ui_listening a.cke_a11yc_ui_button{padding-top:9px;padding-bottom:9px;background:#09863e;border-width:0}.cke_a11yc_ui_listening a.cke_a11yc_ui_button:hover{background:#53aa78}.cke_a11yc_ui_listening a.cke_a11yc_ui_button:focus,.cke_a11yc_ui_listening a.cke_a11yc_ui_button:active{border:2px solid #139ff7;padding:7px 2px 7px 13px}.cke_a11yc_ui_listening a.cke_a11yc_ui_button:focus{box-shadow:inset 0 0 0 2px #fff}.cke_a11yc_ui_listening a.cke_a11yc_ui_button span{color:#fff}_::-webkit-:not(:root:root), .cke_a11yc_ui_form select.cke_a11yc_ui_input_select{width:calc(100% - 2px);border:1px solid #c9cccf;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}_::-webkit-:not(:root:root), .cke_a11yc_ui_form select.cke_a11yc_ui_input_select:focus{border:2px solid #139ff7;width:100%;margin:0}_::-webkit-:not(:root:root), .cke_a11yc_ui_form .cke_a11yc_ui_input_wrapper .cke_a11yc_ui_input_select{width:calc(100% - 2px);margin:0 1px}
\ No newline at end of file
diff --git a/plugins/ckeditor/a11ychecker/skins/moono-lisa/contents.css b/plugins/ckeditor/a11ychecker/skins/moono-lisa/contents.css
new file mode 100644
index 0000000..f958b36
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/skins/moono-lisa/contents.css
@@ -0,0 +1,4 @@
+/*!
+Copyright (c) 20032014-2018, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/license
+*/.cke_editable.cke_loading a,.cke_editable.cke_loading img,.cke_editable.cke_loading.cke_editable_inline.cke_focus{cursor:wait}.cke_editable .cke_a11yc_issue{outline:3px solid #ff9f9f;background-color:#ffe4e4;font-style:italic}.cke_editable .cke_a11yc_issue:hover{cursor:pointer}.cke_editable .cke_a11yc_issue.cke_a11yc_notice{outline-color:#dcdcdc;background-color:#fefefe}.cke_editable .cke_a11yc_issue.cke_a11yc_warning{outline-color:#ffe4b5;background-color:#fffacd}.cke_editable .cke_a11yc_issue.cke_a11yc_error{outline-color:#ff9f9f;background-color:#ffe4e4}.cke_editable .cke_a11yc_issue.cke_a11yc_ignored{outline-color:#dcdcdc;background-color:transparent}.cke_editable .cke_a11yc_issue.cke_a11yc_focused:hover{cursor:auto}.cke_editable .cke_a11yc_issue.cke_a11yc_focused.cke_a11yc_error,.cke_editable .cke_a11yc_issue.cke_a11yc_focused.cke_a11yc_warning,.cke_editable .cke_a11yc_issue.cke_a11yc_focused.cke_a11yc_notice{outline-color:#e87b23;background-color:#f6d9be}.cke_editable .cke_a11yc_issue.cke_a11yc_focused.cke_a11yc_ignored{outline-color:#a9a9a9;background-color:transparent}
\ No newline at end of file
diff --git a/plugins/ckeditor/a11ychecker/skins/moono/a11ychecker.css b/plugins/ckeditor/a11ychecker/skins/moono/a11ychecker.css
new file mode 100644
index 0000000..e91b185
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/skins/moono/a11ychecker.css
@@ -0,0 +1,4 @@
+/*!
+Copyright (c) 20032014-2018, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/license
+*/a.cke_a11yc_ui_button{display:inline-block;*display:inline;*zoom:1;padding:4px;margin:0;text-align:center;color:#333;vertical-align:middle;border:1px solid #b6b6b6;background:#e4e4e4;-webkit-border-radius:3px;-webkit-background-clip:padding-box;-moz-border-radius:3px;-moz-background-clip:padding;border-radius:3px;background-clip:padding-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}a.cke_a11yc_ui_button:hover{cursor:pointer;border-color:#9e9e9e;background:#ccc}a.cke_a11yc_ui_button:focus,a.cke_a11yc_ui_button:active{border-color:#969696;outline:none}a.cke_a11yc_ui_button>span{padding:0 6px}a.cke_a11yc_ui_button>span:hover{cursor:pointer}a.cke_a11yc_ui_button_ok{color:#fff;border-color:#62a60a #62a60a #4d9200;background:#69b10b}a.cke_a11yc_ui_button_ok:hover{border-color:#5b9909 #5b9909 #478500;background:#88be14}a.cke_a11yc_ui_button_ok>span{color:#fff}select.cke_a11yc_ui_input_select{height:25px;line-height:25px;background-color:#fff;border:1px solid #c9cccf;padding:3px 3px 3px 6px;outline:none;-webkit-border-radius:3px;-webkit-background-clip:padding-box;-moz-border-radius:3px;-moz-background-clip:padding;border-radius:3px;background-clip:padding-box}select.cke_a11yc_ui_input_select:focus{outline:none;border:1px solid #139ff7}.cke_a11yc_ui_navigation{display:table;overflow:hidden;width:100%;background:#eee;outline:1px solid #ddd;border-collapse:separate;border-spacing:10px}.cke_a11yc_ui_navigation.cke_a11yc_testability_notice{background-color:#f1f1f1}.cke_a11yc_ui_navigation.cke_a11yc_testability_warning{background-color:#fffacd}.cke_a11yc_ui_navigation.cke_a11yc_testability_error{background-color:#ffe4e4}.cke_a11yc_ui_navigation .cke_a11yc_ui_button_wrapper,.cke_a11yc_ui_navigation .cke_a11yc_ui_navigation_counter{display:table-cell}.cke_a11yc_ui_navigation .cke_a11yc_ui_navigation_counter{width:100%;font-size:14px;font-weight:bold;vertical-align:middle;text-align:left;white-space:normal}a.cke_a11yc_ui_previous span,a.cke_a11yc_ui_next span{background-repeat:no-repeat}a.cke_a11yc_ui_next>span{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAKQWlDQ1BJQ0MgUHJvZmlsZQAASA2dlndUU9kWh8+9N73QEiIgJfQaegkg0jtIFQRRiUmAUAKGhCZ2RAVGFBEpVmRUwAFHhyJjRRQLg4Ji1wnyEFDGwVFEReXdjGsJ7601896a/cdZ39nnt9fZZ+9917oAUPyCBMJ0WAGANKFYFO7rwVwSE8vE9wIYEAEOWAHA4WZmBEf4RALU/L09mZmoSMaz9u4ugGS72yy/UCZz1v9/kSI3QyQGAApF1TY8fiYX5QKUU7PFGTL/BMr0lSkyhjEyFqEJoqwi48SvbPan5iu7yZiXJuShGlnOGbw0noy7UN6aJeGjjAShXJgl4GejfAdlvVRJmgDl9yjT0/icTAAwFJlfzOcmoWyJMkUUGe6J8gIACJTEObxyDov5OWieAHimZ+SKBIlJYqYR15hp5ejIZvrxs1P5YjErlMNN4Yh4TM/0tAyOMBeAr2+WRQElWW2ZaJHtrRzt7VnW5mj5v9nfHn5T/T3IevtV8Sbsz55BjJ5Z32zsrC+9FgD2JFqbHbO+lVUAtG0GQOXhrE/vIADyBQC03pzzHoZsXpLE4gwnC4vs7GxzAZ9rLivoN/ufgm/Kv4Y595nL7vtWO6YXP4EjSRUzZUXlpqemS0TMzAwOl89k/fcQ/+PAOWnNycMsnJ/AF/GF6FVR6JQJhIlou4U8gViQLmQKhH/V4X8YNicHGX6daxRodV8AfYU5ULhJB8hvPQBDIwMkbj96An3rWxAxCsi+vGitka9zjzJ6/uf6Hwtcim7hTEEiU+b2DI9kciWiLBmj34RswQISkAd0oAo0gS4wAixgDRyAM3AD3iAAhIBIEAOWAy5IAmlABLJBPtgACkEx2AF2g2pwANSBetAEToI2cAZcBFfADXALDIBHQAqGwUswAd6BaQiC8BAVokGqkBakD5lC1hAbWgh5Q0FQOBQDxUOJkBCSQPnQJqgYKoOqoUNQPfQjdBq6CF2D+qAH0CA0Bv0BfYQRmALTYQ3YALaA2bA7HAhHwsvgRHgVnAcXwNvhSrgWPg63whfhG/AALIVfwpMIQMgIA9FGWAgb8URCkFgkAREha5EipAKpRZqQDqQbuY1IkXHkAwaHoWGYGBbGGeOHWYzhYlZh1mJKMNWYY5hWTBfmNmYQM4H5gqVi1bGmWCesP3YJNhGbjS3EVmCPYFuwl7ED2GHsOxwOx8AZ4hxwfrgYXDJuNa4Etw/XjLuA68MN4SbxeLwq3hTvgg/Bc/BifCG+Cn8cfx7fjx/GvyeQCVoEa4IPIZYgJGwkVBAaCOcI/YQRwjRRgahPdCKGEHnEXGIpsY7YQbxJHCZOkxRJhiQXUiQpmbSBVElqIl0mPSa9IZPJOmRHchhZQF5PriSfIF8lD5I/UJQoJhRPShxFQtlOOUq5QHlAeUOlUg2obtRYqpi6nVpPvUR9Sn0vR5Mzl/OX48mtk6uRa5Xrl3slT5TXl3eXXy6fJ18hf0r+pvy4AlHBQMFTgaOwVqFG4bTCPYVJRZqilWKIYppiiWKD4jXFUSW8koGStxJPqUDpsNIlpSEaQtOledK4tE20Otpl2jAdRzek+9OT6cX0H+i99AllJWVb5SjlHOUa5bPKUgbCMGD4M1IZpYyTjLuMj/M05rnP48/bNq9pXv+8KZX5Km4qfJUilWaVAZWPqkxVb9UU1Z2qbapP1DBqJmphatlq+9Uuq43Pp893ns+dXzT/5PyH6rC6iXq4+mr1w+o96pMamhq+GhkaVRqXNMY1GZpumsma5ZrnNMe0aFoLtQRa5VrntV4wlZnuzFRmJbOLOaGtru2nLdE+pN2rPa1jqLNYZ6NOs84TXZIuWzdBt1y3U3dCT0svWC9fr1HvoT5Rn62fpL9Hv1t/ysDQINpgi0GbwaihiqG/YZ5ho+FjI6qRq9Eqo1qjO8Y4Y7ZxivE+41smsImdSZJJjclNU9jU3lRgus+0zwxr5mgmNKs1u8eisNxZWaxG1qA5wzzIfKN5m/krCz2LWIudFt0WXyztLFMt6ywfWSlZBVhttOqw+sPaxJprXWN9x4Zq42Ozzqbd5rWtqS3fdr/tfTuaXbDdFrtOu8/2DvYi+yb7MQc9h3iHvQ732HR2KLuEfdUR6+jhuM7xjOMHJ3snsdNJp9+dWc4pzg3OowsMF/AX1C0YctFx4bgccpEuZC6MX3hwodRV25XjWuv6zE3Xjed2xG3E3dg92f24+ysPSw+RR4vHlKeT5xrPC16Il69XkVevt5L3Yu9q76c+Oj6JPo0+E752vqt9L/hh/QL9dvrd89fw5/rX+08EOASsCegKpARGBFYHPgsyCRIFdQTDwQHBu4IfL9JfJFzUFgJC/EN2hTwJNQxdFfpzGC4sNKwm7Hm4VXh+eHcELWJFREPEu0iPyNLIR4uNFksWd0bJR8VF1UdNRXtFl0VLl1gsWbPkRoxajCCmPRYfGxV7JHZyqffS3UuH4+ziCuPuLjNclrPs2nK15anLz66QX8FZcSoeGx8d3xD/iRPCqeVMrvRfuXflBNeTu4f7kufGK+eN8V34ZfyRBJeEsoTRRJfEXYljSa5JFUnjAk9BteB1sl/ygeSplJCUoykzqdGpzWmEtPi000IlYYqwK10zPSe9L8M0ozBDuspp1e5VE6JA0ZFMKHNZZruYjv5M9UiMJJslg1kLs2qy3mdHZZ/KUcwR5vTkmuRuyx3J88n7fjVmNXd1Z752/ob8wTXuaw6thdauXNu5Tnddwbrh9b7rj20gbUjZ8MtGy41lG99uit7UUaBRsL5gaLPv5sZCuUJR4b0tzlsObMVsFWzt3WazrWrblyJe0fViy+KK4k8l3JLr31l9V/ndzPaE7b2l9qX7d+B2CHfc3em681iZYlle2dCu4F2t5czyovK3u1fsvlZhW3FgD2mPZI+0MqiyvUqvakfVp+qk6oEaj5rmvep7t+2d2sfb17/fbX/TAY0DxQc+HhQcvH/I91BrrUFtxWHc4azDz+ui6rq/Z39ff0TtSPGRz0eFR6XHwo911TvU1zeoN5Q2wo2SxrHjccdv/eD1Q3sTq+lQM6O5+AQ4ITnx4sf4H++eDDzZeYp9qukn/Z/2ttBailqh1tzWibakNml7THvf6YDTnR3OHS0/m/989Iz2mZqzymdLz5HOFZybOZ93fvJCxoXxi4kXhzpXdD66tOTSna6wrt7LgZevXvG5cqnbvfv8VZerZ645XTt9nX297Yb9jdYeu56WX+x+aem172296XCz/ZbjrY6+BX3n+l37L972un3ljv+dGwOLBvruLr57/17cPel93v3RB6kPXj/Mejj9aP1j7OOiJwpPKp6qP6391fjXZqm99Oyg12DPs4hnj4a4Qy//lfmvT8MFz6nPK0a0RupHrUfPjPmM3Xqx9MXwy4yX0+OFvyn+tveV0auffnf7vWdiycTwa9HrmT9K3qi+OfrW9m3nZOjk03dp76anit6rvj/2gf2h+2P0x5Hp7E/4T5WfjT93fAn88ngmbWbm3/eE8/syOll+AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAhUlEQVQIHWM2Nzc/JC4u/hwIXjAwMLAAMTMQMwExA6OlpeV/EOPfv39Hf/782XbhwoWDQO5fEIZLghSAAFDRkd+/f7ecO3duP4YkSMH///+vAE2JAdkBB0BdV4G6OoC61gEF/4AlkQQ3AgXB9gHpfwwmJiaRQAY3EHMBMScQswMxKxAzAwAhokLukwaZHgAAAABJRU5ErkJggg==);background-position:right center;padding-right:16px;margin-right:7px}a.cke_a11yc_ui_previous>span{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAKQWlDQ1BJQ0MgUHJvZmlsZQAASA2dlndUU9kWh8+9N73QEiIgJfQaegkg0jtIFQRRiUmAUAKGhCZ2RAVGFBEpVmRUwAFHhyJjRRQLg4Ji1wnyEFDGwVFEReXdjGsJ7601896a/cdZ39nnt9fZZ+9917oAUPyCBMJ0WAGANKFYFO7rwVwSE8vE9wIYEAEOWAHA4WZmBEf4RALU/L09mZmoSMaz9u4ugGS72yy/UCZz1v9/kSI3QyQGAApF1TY8fiYX5QKUU7PFGTL/BMr0lSkyhjEyFqEJoqwi48SvbPan5iu7yZiXJuShGlnOGbw0noy7UN6aJeGjjAShXJgl4GejfAdlvVRJmgDl9yjT0/icTAAwFJlfzOcmoWyJMkUUGe6J8gIACJTEObxyDov5OWieAHimZ+SKBIlJYqYR15hp5ejIZvrxs1P5YjErlMNN4Yh4TM/0tAyOMBeAr2+WRQElWW2ZaJHtrRzt7VnW5mj5v9nfHn5T/T3IevtV8Sbsz55BjJ5Z32zsrC+9FgD2JFqbHbO+lVUAtG0GQOXhrE/vIADyBQC03pzzHoZsXpLE4gwnC4vs7GxzAZ9rLivoN/ufgm/Kv4Y595nL7vtWO6YXP4EjSRUzZUXlpqemS0TMzAwOl89k/fcQ/+PAOWnNycMsnJ/AF/GF6FVR6JQJhIlou4U8gViQLmQKhH/V4X8YNicHGX6daxRodV8AfYU5ULhJB8hvPQBDIwMkbj96An3rWxAxCsi+vGitka9zjzJ6/uf6Hwtcim7hTEEiU+b2DI9kciWiLBmj34RswQISkAd0oAo0gS4wAixgDRyAM3AD3iAAhIBIEAOWAy5IAmlABLJBPtgACkEx2AF2g2pwANSBetAEToI2cAZcBFfADXALDIBHQAqGwUswAd6BaQiC8BAVokGqkBakD5lC1hAbWgh5Q0FQOBQDxUOJkBCSQPnQJqgYKoOqoUNQPfQjdBq6CF2D+qAH0CA0Bv0BfYQRmALTYQ3YALaA2bA7HAhHwsvgRHgVnAcXwNvhSrgWPg63whfhG/AALIVfwpMIQMgIA9FGWAgb8URCkFgkAREha5EipAKpRZqQDqQbuY1IkXHkAwaHoWGYGBbGGeOHWYzhYlZh1mJKMNWYY5hWTBfmNmYQM4H5gqVi1bGmWCesP3YJNhGbjS3EVmCPYFuwl7ED2GHsOxwOx8AZ4hxwfrgYXDJuNa4Etw/XjLuA68MN4SbxeLwq3hTvgg/Bc/BifCG+Cn8cfx7fjx/GvyeQCVoEa4IPIZYgJGwkVBAaCOcI/YQRwjRRgahPdCKGEHnEXGIpsY7YQbxJHCZOkxRJhiQXUiQpmbSBVElqIl0mPSa9IZPJOmRHchhZQF5PriSfIF8lD5I/UJQoJhRPShxFQtlOOUq5QHlAeUOlUg2obtRYqpi6nVpPvUR9Sn0vR5Mzl/OX48mtk6uRa5Xrl3slT5TXl3eXXy6fJ18hf0r+pvy4AlHBQMFTgaOwVqFG4bTCPYVJRZqilWKIYppiiWKD4jXFUSW8koGStxJPqUDpsNIlpSEaQtOledK4tE20Otpl2jAdRzek+9OT6cX0H+i99AllJWVb5SjlHOUa5bPKUgbCMGD4M1IZpYyTjLuMj/M05rnP48/bNq9pXv+8KZX5Km4qfJUilWaVAZWPqkxVb9UU1Z2qbapP1DBqJmphatlq+9Uuq43Pp893ns+dXzT/5PyH6rC6iXq4+mr1w+o96pMamhq+GhkaVRqXNMY1GZpumsma5ZrnNMe0aFoLtQRa5VrntV4wlZnuzFRmJbOLOaGtru2nLdE+pN2rPa1jqLNYZ6NOs84TXZIuWzdBt1y3U3dCT0svWC9fr1HvoT5Rn62fpL9Hv1t/ysDQINpgi0GbwaihiqG/YZ5ho+FjI6qRq9Eqo1qjO8Y4Y7ZxivE+41smsImdSZJJjclNU9jU3lRgus+0zwxr5mgmNKs1u8eisNxZWaxG1qA5wzzIfKN5m/krCz2LWIudFt0WXyztLFMt6ywfWSlZBVhttOqw+sPaxJprXWN9x4Zq42Ozzqbd5rWtqS3fdr/tfTuaXbDdFrtOu8/2DvYi+yb7MQc9h3iHvQ732HR2KLuEfdUR6+jhuM7xjOMHJ3snsdNJp9+dWc4pzg3OowsMF/AX1C0YctFx4bgccpEuZC6MX3hwodRV25XjWuv6zE3Xjed2xG3E3dg92f24+ysPSw+RR4vHlKeT5xrPC16Il69XkVevt5L3Yu9q76c+Oj6JPo0+E752vqt9L/hh/QL9dvrd89fw5/rX+08EOASsCegKpARGBFYHPgsyCRIFdQTDwQHBu4IfL9JfJFzUFgJC/EN2hTwJNQxdFfpzGC4sNKwm7Hm4VXh+eHcELWJFREPEu0iPyNLIR4uNFksWd0bJR8VF1UdNRXtFl0VLl1gsWbPkRoxajCCmPRYfGxV7JHZyqffS3UuH4+ziCuPuLjNclrPs2nK15anLz66QX8FZcSoeGx8d3xD/iRPCqeVMrvRfuXflBNeTu4f7kufGK+eN8V34ZfyRBJeEsoTRRJfEXYljSa5JFUnjAk9BteB1sl/ygeSplJCUoykzqdGpzWmEtPi000IlYYqwK10zPSe9L8M0ozBDuspp1e5VE6JA0ZFMKHNZZruYjv5M9UiMJJslg1kLs2qy3mdHZZ/KUcwR5vTkmuRuyx3J88n7fjVmNXd1Z752/ob8wTXuaw6thdauXNu5Tnddwbrh9b7rj20gbUjZ8MtGy41lG99uit7UUaBRsL5gaLPv5sZCuUJR4b0tzlsObMVsFWzt3WazrWrblyJe0fViy+KK4k8l3JLr31l9V/ndzPaE7b2l9qX7d+B2CHfc3em681iZYlle2dCu4F2t5czyovK3u1fsvlZhW3FgD2mPZI+0MqiyvUqvakfVp+qk6oEaj5rmvep7t+2d2sfb17/fbX/TAY0DxQc+HhQcvH/I91BrrUFtxWHc4azDz+ui6rq/Z39ff0TtSPGRz0eFR6XHwo911TvU1zeoN5Q2wo2SxrHjccdv/eD1Q3sTq+lQM6O5+AQ4ITnx4sf4H++eDDzZeYp9qukn/Z/2ttBailqh1tzWibakNml7THvf6YDTnR3OHS0/m/989Iz2mZqzymdLz5HOFZybOZ93fvJCxoXxi4kXhzpXdD66tOTSna6wrt7LgZevXvG5cqnbvfv8VZerZ645XTt9nX297Yb9jdYeu56WX+x+aem172296XCz/ZbjrY6+BX3n+l37L972un3ljv+dGwOLBvruLr57/17cPel93v3RB6kPXj/Mejj9aP1j7OOiJwpPKp6qP6391fjXZqm99Oyg12DPs4hnj4a4Qy//lfmvT8MFz6nPK0a0RupHrUfPjPmM3Xqx9MXwy4yX0+OFvyn+tveV0auffnf7vWdiycTwa9HrmT9K3qi+OfrW9m3nZOjk03dp76anit6rvj/2gf2h+2P0x5Hp7E/4T5WfjT93fAn88ngmbWbm3/eE8/syOll+AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAhklEQVQIHWNkYGBgBmImJMwIZDOamJj4soAYUAmQImZjY+MgVlbWciBbGSQJ0gUSDAUKVjAyMmoA+Qz/////xWJkZKTLxsa2GCioCRJEBszPnz9/KyIicoeZmVkJqEAWSfIvyD5WIAbbp6en58TJyVnFxMRkATIWJAmzF+5iAwMDew4OjhIAregW7mj1jM8AAAAASUVORK5CYII=);background-position:6px center;padding-left:23px}.cke_a11yc_ui_desc_wrapper{padding:0 10px;margin:15px 0 10px}.cke_a11yc_ui_desc_title,.cke_a11yc_ui_desc_info{white-space:normal}.cke_a11yc_ui_desc_title{font-size:14px;font-weight:bold}.cke_a11yc_ui_desc_info{color:#6e6e6e;margin-top:10px;line-height:1.4em}.cke_a11yc_ui_desc_info code{font-family:monospace;padding:1px 2px;background:#eee;border:1px solid #ccc;-webkit-border-radius:2px;-webkit-background-clip:padding-box;-moz-border-radius:2px;-moz-background-clip:padding;border-radius:2px;background-clip:padding-box;color:inherit}.cke_a11yc_ui_desc_info a{color:#00b2ce;text-decoration:underline}.cke_a11yc_ui_form{margin:10px 0 0;overflow:hidden}.cke_a11yc_ui_form_fieldset{width:100%;display:table;border-collapse:separate;border-spacing:10px 0}.cke_a11yc_ui_form_fieldset:not(:empty){margin-bottom:10px}.cke_a11yc_ui_form_actionset{width:100%;display:table;border-collapse:separate;border-spacing:10px}.cke_a11yc_ui_form_actionset .cke_a11yc_ui_button_wrapper{display:table-cell}.cke_a11yc_ui_form .cke_a11yc_ui_button_ok,.cke_a11yc_ui_form .cke_a11yc_ui_button_ok_wrapper{width:100%}.cke_a11yc_ui_input_label{padding-right:20px;width:10%}.cke_a11yc_ui_input_label:after{content:':'}.cke_a11yc_ui_input_wrapper{display:table-row}.cke_a11yc_ui_input_wrapper+.cke_a11yc_ui_input_wrapper{border-top:10px solid transparent}.cke_a11yc_ui_input_wrapper .cke_a11yc_ui_input,.cke_a11yc_ui_input_wrapper .cke_a11yc_ui_input_label{display:table-cell}.cke_a11yc_ui_input_wrapper .cke_a11yc_ui_input_text,.cke_a11yc_ui_input_wrapper .cke_a11yc_ui_input_select{width:100%}input.cke_a11yc_ui_input_text{background-color:#fff;border:1px solid #c9cccf;padding:4px 6px;outline:none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-border-radius:3px;-webkit-background-clip:padding-box;-moz-border-radius:3px;-moz-background-clip:padding;border-radius:3px;background-clip:padding-box}input.cke_a11yc_ui_input_text:hover{border:1px solid #aeb3b9}input.cke_a11yc_ui_input_text:focus{outline:none;border:1px solid #139ff7}.cke_a11yc_ui_listening{display:none;overflow:hidden;padding:10px}.cke_a11yc_ui_listening p{white-space:normal}.cke_a11yc_ui_listening strong{font-weight:bold}.cke_a11yc_ui_listening .cke_a11yc_ui_button{cursor:pointer}.cke_a11yc_ui_listening a.cke_a11yc_ui_button{display:block;overflow:hidden;padding-left:15px;margin-top:10px;position:relative}.cke_balloon.cke_a11yc_mode_listening{-webkit-transition:0.3s ease-in-out;-moz-transition:0.3s ease-in-out;-o-transition:0.3s ease-in-out;transition:0.3s ease-in-out}.cke_balloon.cke_a11yc_mode_listening .cke_a11yc_ui_navigation,.cke_balloon.cke_a11yc_mode_listening .cke_a11yc_ui_desc_wrapper,.cke_balloon.cke_a11yc_mode_listening .cke_a11yc_ui_form,.cke_balloon.cke_a11yc_mode_listening .cke_balloon_triangle_outer{display:none}.cke_balloon.cke_a11yc_mode_listening .cke_a11yc_ui_listening{display:block}.cke_hc select:focus,.cke_hc input:focus,.cke_hc a.cke_a11yc_ui_button:focus{border-width:3px}.cke_hc select:focus.cke_a11yc_ui_button,.cke_hc input:focus.cke_a11yc_ui_button,.cke_hc a.cke_a11yc_ui_button:focus.cke_a11yc_ui_button{padding:2px}.cke_hc select:focus.cke_a11yc_ui_input_select,.cke_hc input:focus.cke_a11yc_ui_input_select,.cke_hc a.cke_a11yc_ui_button:focus.cke_a11yc_ui_input_select{padding:1px 1px 1px 4px}.cke_hc select:focus.cke_a11yc_ui_input_text,.cke_hc input:focus.cke_a11yc_ui_input_text,.cke_hc a.cke_a11yc_ui_button:focus.cke_a11yc_ui_input_text{padding:2px 4px}a.cke_a11yc_ui_button{border-bottom-color:#999;-webkit-box-shadow:0 1px 0 rgba(255, 255, 255, 0.5), 0 0 2px rgba(255, 255, 255, 0.15) inset, 0 1px 0 rgba(255, 255, 255, 0.15) inset;-moz-box-shadow:0 1px 0 rgba(255, 255, 255, 0.5), 0 0 2px rgba(255, 255, 255, 0.15) inset, 0 1px 0 rgba(255, 255, 255, 0.15) inset;box-shadow:0 1px 0 rgba(255, 255, 255, 0.5), 0 0 2px rgba(255, 255, 255, 0.15) inset, 0 1px 0 rgba(255, 255, 255, 0.15) inset;background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMSAxIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJub25lIj48bGluZWFyR3JhZGllbnQgaWQ9Imxlc3NoYXQtZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiIHN0b3Atb3BhY2l0eT0iMSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2U0ZTRlNCIgc3RvcC1vcGFjaXR5PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2xlc3NoYXQtZ2VuZXJhdGVkKSIgLz48L3N2Zz4=);background-image:-webkit-linear-gradient(top, #ffffff, #e4e4e4);background-image:-moz-linear-gradient(top, #ffffff, #e4e4e4);background-image:-o-linear-gradient(top, #ffffff, #e4e4e4);background-image:linear-gradient(to bottom, #ffffff, #e4e4e4)}a.cke_a11yc_ui_button:hover{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMSAxIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJub25lIj48bGluZWFyR3JhZGllbnQgaWQ9Imxlc3NoYXQtZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiNmMmYyZjIiIHN0b3Atb3BhY2l0eT0iMSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2NjY2NjYyIgc3RvcC1vcGFjaXR5PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2xlc3NoYXQtZ2VuZXJhdGVkKSIgLz48L3N2Zz4=);background-image:-webkit-linear-gradient(top, #f2f2f2, #cccccc);background-image:-moz-linear-gradient(top, #f2f2f2, #cccccc);background-image:-o-linear-gradient(top, #f2f2f2, #cccccc);background-image:linear-gradient(to bottom, #f2f2f2, #cccccc)}a.cke_a11yc_ui_button:focus,a.cke_a11yc_ui_button:active{-webkit-box-shadow:0 0 6px rgba(0, 0, 0, 0.4) inset;-moz-box-shadow:0 0 6px rgba(0, 0, 0, 0.4) inset;box-shadow:0 0 6px rgba(0, 0, 0, 0.4) inset}a.cke_a11yc_ui_button>span{text-shadow:0 1px 0 #fff}a.cke_a11yc_ui_button_ok{text-shadow:0 -1px 0 #55830c;background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMSAxIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJub25lIj48bGluZWFyR3JhZGllbnQgaWQ9Imxlc3NoYXQtZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiM5YWQ3MTciIHN0b3Atb3BhY2l0eT0iMSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzY5YjEwYiIgc3RvcC1vcGFjaXR5PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2xlc3NoYXQtZ2VuZXJhdGVkKSIgLz48L3N2Zz4=);background-image:-webkit-linear-gradient(top, #9ad717, #69b10b);background-image:-moz-linear-gradient(top, #9ad717, #69b10b);background-image:-o-linear-gradient(top, #9ad717, #69b10b);background-image:linear-gradient(to bottom, #9ad717, #69b10b)}a.cke_a11yc_ui_button_ok:hover{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMSAxIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJub25lIj48bGluZWFyR3JhZGllbnQgaWQ9Imxlc3NoYXQtZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiM4OGJlMTQiIHN0b3Atb3BhY2l0eT0iMSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzVkOWMwYSIgc3RvcC1vcGFjaXR5PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2xlc3NoYXQtZ2VuZXJhdGVkKSIgLz48L3N2Zz4=);background-image:-webkit-linear-gradient(top, #88be14 0%, #5d9c0a 100%);background-image:-moz-linear-gradient(top, #88be14 0%, #5d9c0a 100%);background-image:-o-linear-gradient(top, #88be14 0%, #5d9c0a 100%);background-image:linear-gradient(to bottom, #88be14 0%, #5d9c0a 100%)}a.cke_a11yc_ui_button_ok>span{text-shadow:0 -1px 0 #55830c}.cke_a11yc_ui_desc_info{font-style:italic}select.cke_a11yc_ui_input_select{border-top-color:#aeb3b9;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.15) inset;-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.15) inset;box-shadow:0 1px 2px rgba(0, 0, 0, 0.15) inset}select.cke_a11yc_ui_input_select:focus{border-top-color:#1392e9}input.cke_a11yc_ui_input_text{border-top-color:#aeb3b9;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.15) inset;-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.15) inset;box-shadow:0 1px 2px rgba(0, 0, 0, 0.15) inset}input.cke_a11yc_ui_input_text:hover{border-top-color:#a0a6ad}input.cke_a11yc_ui_input_text:focus{border-top-color:#1392e9}.cke_a11yc_ui_listening a.cke_a11yc_ui_button :before{content:url(images/reload.png );position:absolute;top:5px;left:5px}
\ No newline at end of file
diff --git a/plugins/ckeditor/a11ychecker/skins/moono/contents.css b/plugins/ckeditor/a11ychecker/skins/moono/contents.css
new file mode 100644
index 0000000..3b56e77
--- /dev/null
+++ b/plugins/ckeditor/a11ychecker/skins/moono/contents.css
@@ -0,0 +1,4 @@
+/*!
+Copyright (c) 20032014-2018, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/license
+*/.cke_editable.cke_loading a,.cke_editable.cke_loading img,.cke_editable.cke_loading.cke_editable_inline.cke_focus{cursor:wait}.cke_editable .cke_a11yc_issue{outline:3px solid #ff9f9f;background-color:#ffe4e4;font-style:italic}.cke_editable .cke_a11yc_issue:hover{cursor:pointer}.cke_editable .cke_a11yc_issue.cke_a11yc_notice{outline-color:#dcdcdc;background-color:#f1f1f1}.cke_editable .cke_a11yc_issue.cke_a11yc_warning{outline-color:#ffe4b5;background-color:#fffacd}.cke_editable .cke_a11yc_issue.cke_a11yc_error{outline-color:#ff9f9f;background-color:#ffe4e4}.cke_editable .cke_a11yc_issue.cke_a11yc_ignored{outline-color:#dcdcdc;background-color:transparent}.cke_editable .cke_a11yc_issue.cke_a11yc_focused:hover{cursor:auto}.cke_editable .cke_a11yc_issue.cke_a11yc_focused.cke_a11yc_error,.cke_editable .cke_a11yc_issue.cke_a11yc_focused.cke_a11yc_warning,.cke_editable .cke_a11yc_issue.cke_a11yc_focused.cke_a11yc_notice{outline-color:#e87b23;background-color:#f6d9be}.cke_editable .cke_a11yc_issue.cke_a11yc_focused.cke_a11yc_ignored{outline-color:#a9a9a9;background-color:transparent}
\ No newline at end of file
diff --git a/plugins/ckeditor/a11ychecker/skins/moono/images/reload.png b/plugins/ckeditor/a11ychecker/skins/moono/images/reload.png
new file mode 100644
index 0000000..a47b8d9
Binary files /dev/null and b/plugins/ckeditor/a11ychecker/skins/moono/images/reload.png differ
diff --git a/plugins/ckeditor/balloonpanel/index.js b/plugins/ckeditor/balloonpanel/index.js
new file mode 100644
index 0000000..93f70fe
--- /dev/null
+++ b/plugins/ckeditor/balloonpanel/index.js
@@ -0,0 +1,6 @@
+define(function (require, exports, module) {
+
+ var Helper = require("../helper.js");
+ var moduleId = module.uri.match(/^.+(_modules[^\/]+)\/.*/)[1];
+ Helper.registerPlugin2("balloonpanel", moduleId);
+});
\ No newline at end of file
diff --git a/plugins/ckeditor/balloonpanel/plugin.js b/plugins/ckeditor/balloonpanel/plugin.js
new file mode 100644
index 0000000..981fbd0
--- /dev/null
+++ b/plugins/ckeditor/balloonpanel/plugin.js
@@ -0,0 +1,919 @@
+/**
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @fileOverview The Balloon Panel plugin that provides an ability to create a floating, balloon-shaped
+ * container capable of presenting content at a precise position in the document.
+ */
+
+( function() {
+ 'use strict';
+
+ // This flag prevents appending stylesheet more than once.
+ var stylesLoaded = false;
+
+ CKEDITOR.plugins.add( 'balloonpanel', {
+ init: function() {
+ if ( !stylesLoaded ) {
+ CKEDITOR.document.appendStyleSheet( this.path + 'skins/' + CKEDITOR.skin.name + '/balloonpanel.css' );
+ stylesLoaded = true;
+ }
+ }
+ } );
+
+ /**
+ * A class that represents a floating, balloon-shaped panel capable of presenting defined
+ * content at a precise position in the document. It can be used to represent
+ * contextual data or forms i.e. related to an element in the editor's editable.
+ *
+ * // Create an instance of the balloon panel.
+ * var panel = new CKEDITOR.ui.balloonPanel( editor, {
+ * title: 'My Panel',
+ * content: 'This is my panel
'
+ * } );
+ *
+ * // Attach the panel to an element in DOM and show it immediately.
+ * panel.attach( domElement );
+ *
+ * @class
+ * @since 4.6.0
+ * @param {CKEDITOR.editor} editor The editor instance for which the panel is created.
+ * @param {Object} definition An object containing the panel definition.
+ */
+ CKEDITOR.ui.balloonPanel = function( editor, definition ) {
+ /**
+ * The editor for this balloon panel.
+ */
+ this.editor = editor;
+
+ CKEDITOR.tools.extend( this, {
+ /**
+ * The default width of the balloon panel.
+ */
+ width: 360,
+
+ /**
+ * The default height of the balloon panel.
+ */
+ height: 'auto',
+
+ /**
+ * The default width of the triangle that points to the element in the editable.
+ */
+ triangleWidth: 20,
+
+ /**
+ * The default height of the triangle that points to the element in the editable.
+ */
+ triangleHeight: 20,
+
+ /**
+ * The default distance between the triangle and the vertical edge of the panel.
+ */
+ triangleMinDistance: 40
+ }, definition, true );
+
+ /**
+ * Templates for UI elements in this balloon panel.
+ * See {@link #templateDefinitions}, {@link #parts}.
+ */
+ this.templates = {};
+
+ for ( var t in this.templateDefinitions ) {
+ this.templates[ t ] = new CKEDITOR.template( this.templateDefinitions[ t ] );
+ }
+
+ /**
+ * @property parts The UI elements of the balloon panel.
+ * @property {CKEDITOR.dom.element} parts.title The title bar of the panel.
+ * @property {CKEDITOR.dom.element} parts.close The Close button.
+ * @property {CKEDITOR.dom.element} parts.content The element that stores the content of the panel.
+ * @property {CKEDITOR.dom.element} parts.panel The undermost element that stores all other elements. The panel is positioned absolutely.
+ * @property {CKEDITOR.dom.element} parts.triangle The panel's triangle.
+ * @property {CKEDITOR.dom.element} parts.triangleOuter The outer element of the triangle.
+ * @property {CKEDITOR.dom.element} parts.triangleInner The inner element of the triangle.
+ */
+ this.parts = {};
+
+ /**
+ * Focusable elements in this balloon panel.
+ * See {@link #registerFocusable}, {@link #deregisterFocusable} and {@link CKEDITOR.focusManager}.
+ */
+ this.focusables = {};
+
+ /**
+ * Event listeners associated with this balloon panel, activated on panel show.
+ * See {@link #addShowListener}, {@link #activateShowListeners}, {@link #deactivateShowListeners}.
+ */
+ this.showListeners = {};
+
+ /**
+ * Event listeners associated with this balloon panel, active as long as the panel is shown.
+ * See {@link #addShowListener}, {@link #activateShowListeners}, {@link #deactivateShowListeners}.
+ */
+ this.activeShowListeners = {};
+
+ /**
+ * @property rect Contains panel properties as {@link #move}, {@link #resize},
+ * {@link #method-show} and {@link #method-hide} are called. It stores values and avoids unnecessary
+ * and expensive checks in the future.
+ *
+ * @property {Number} rect.width
+ * @property {Number} rect.height
+ * @property {Number} rect.top
+ * @property {Number} rect.left
+ * @property {Boolean} rect.visible
+ */
+ this.rect = {
+ visible: false
+ };
+
+ // Build the UI of the balloon panel.
+ this.build();
+
+ // Handle panel destruction.
+ editor.on( 'destroy', function() {
+ this.destroy();
+ }, this );
+
+ /**
+ * Event fired when the balloon panel is shown.
+ *
+ * @event show
+ */
+
+ /**
+ * Event fired when the balloon panel is hidden.
+ *
+ * @event hide
+ */
+
+ /**
+ * Event fired when the balloon panel is attached to an element.
+ *
+ * @event attach
+ */
+ };
+
+ CKEDITOR.ui.balloonPanel.prototype = {
+ /**
+ * @property templateDefinitions Balloon panel templates. Automatically converted into a {@link CKEDITOR.template} in the panel constructor.
+ * @property {String} templateDefinitions.panel The template for the panel outermost container.
+ * @property {String} templateDefinitions.content The template for the panel content container.
+ * @property {String} templateDefinitions.title The template for the panel title bar.
+ * @property {String} templateDefinitions.close The template for the panel Close button.
+ * @property {String} templateDefinitions.triangleOuter The template for the panel outer triangle.
+ * @property {String} templateDefinitions.triangleInner The template for the panel inner triangle.
+ */
+ templateDefinitions: {
+ panel:
+ '',
+
+ content: '{content}',
+
+ title: '{title}',
+
+ close:
+ '' +
+ 'X' +
+ '',
+
+ triangleOuter: '',
+
+ triangleInner: ''
+ },
+
+ /**
+ * Builds the UI of the balloon panel.
+ */
+ build: function() {
+ var editor = this.editor;
+
+ this.parts = {
+ title: CKEDITOR.dom.element.createFromHtml( this.templates.title.output( {
+ title: this.title
+ } ) ),
+
+ close: CKEDITOR.dom.element.createFromHtml( this.templates.close.output() ),
+
+ panel: CKEDITOR.dom.element.createFromHtml( this.templates.panel.output( {
+ id: editor.id,
+ langDir: editor.lang.dir,
+ langCode: editor.langCode,
+ name: editor.name,
+ style: 'display:none;',
+ voiceLabel: editor.lang.editorPanel + ', ' + editor.name
+ } ) ),
+
+ content: CKEDITOR.dom.element.createFromHtml( this.templates.content.output( {
+ content: this.content || ''
+ } ) ),
+
+ triangleOuter: CKEDITOR.dom.element.createFromHtml( this.templates.triangleOuter.output() ),
+
+ triangleInner: CKEDITOR.dom.element.createFromHtml( this.templates.triangleInner.output() )
+ };
+
+ // Append UI elements to create a panel.
+ this.parts.panel.append( this.parts.title, 1 );
+ this.parts.panel.append( this.parts.close, 1 );
+ this.parts.panel.append( this.parts.triangleOuter );
+ this.parts.panel.append( this.parts.content );
+ this.parts.triangleOuter.append( this.parts.triangleInner );
+
+ // Register panel children to focusManager (prevent from blurring the editor).
+ this.registerFocusable( this.parts.panel );
+ this.registerFocusable( this.parts.close );
+
+ // Panel title and close button are not to be selected.
+ this.parts.title.unselectable();
+ this.parts.close.unselectable();
+
+ // Append the panel to the global document.
+ CKEDITOR.document.getBody().append( this.parts.panel );
+
+ // Set default dimensions of the panel.
+ this.resize( this.width, this.height );
+
+ // Activates listeners on panel show.
+ // All listeners will be deactivated on panel hide.
+ this.on( 'show', this.activateShowListeners, this );
+
+ // Deactivate all listeners on panel hide.
+ this.on( 'hide', this.deactivateShowListeners, this );
+
+ this.parts.close.on( 'click', function( evt ) {
+ this.hide();
+ evt.data.preventDefault();
+ }, this );
+ },
+
+ /**
+ * Shows the balloon panel.
+ */
+ show: function() {
+ if ( this.rect.visible ) {
+ return;
+ }
+
+ this.rect.visible = true;
+ this.parts.panel.show();
+
+ this.fire( 'show' );
+ },
+
+ /**
+ * Hides the balloon panel and moves the focus back to the editable.
+ */
+ hide: function() {
+ if ( !this.rect.visible ) {
+ return;
+ }
+
+ this.rect.visible = false;
+ this.parts.panel.hide();
+ this.blur();
+
+ this.fire( 'hide' );
+ },
+
+ /**
+ * Moves the focus back to the editor's editable.
+ *
+ * @method blur
+ * @member CKEDITOR.ui.balloonPanel
+ */
+ blur: function() {
+ this.editor.focus();
+ },
+
+ /**
+ * Moves the **upper-left** balloon panel corner to the specified absolute position.
+ *
+ * @param {Number} top
+ * @param {Number} left
+ */
+ move: function( top, left ) {
+ this.rect.left = left;
+ this.rect.top = top;
+
+ this.parts.panel.setStyles( {
+ left: CKEDITOR.tools.cssLength( left ),
+ top: CKEDITOR.tools.cssLength( top )
+ } );
+ },
+
+ /**
+ * Places the balloon panel next to a specified element or a selection so the tip of the balloon's triangle
+ * touches that element or the center of the selection. Once the panel is attached it gains focus.
+ *
+ * @method attach
+ * @param {CKEDITOR.dom.element/CKEDITOR.dom.selection} elementOrSelection The element or selection to which the panel is attached.
+ * **Since 4.11.0** instead of an element it is possible to pass a selection {@link CKEDITOR.dom.selection}.
+ * @param {Object/CKEDITOR.dom.element/Boolean} [options] **Since 4.8.0** this parameter works as an `options` object.
+ *
+ * If a `{@link CKEDITOR.dom.element}/Boolean` instance is given, this parameter acts as an `options.focusElement`.
+ * @param {CKEDITOR.dom.element/Boolean} [options.focusElement] The element to be focused after the panel
+ * is attached. By default the `panel` property of {@link #parts} will be focused. You might specify the element
+ * to be focused by passing any {@link CKEDITOR.dom.element} instance.
+ * You can also prevent changing the focus at all by setting it to `false`.
+ * @param {Boolean} [options.show=true] Defines if the balloon panel should be shown after being attached.
+ */
+ attach: ( function() {
+ var winGlobal, frame, editable, isInline;
+
+ function rectIntersectArea( rect1, rect2 ) {
+ var hOverlap = Math.max( 0, Math.min( rect1.right, rect2.right ) - Math.max( rect1.left, rect2.left ) ),
+ vOverlap = Math.max( 0, Math.min( rect1.bottom, rect2.bottom ) - Math.max( rect1.top, rect2.top ) );
+
+ return hOverlap * vOverlap;
+ }
+
+ function newPanelRect( top, left, panelWidth, panelHeight ) {
+ var newRect = {
+ top: top,
+ left: left
+ };
+
+ newRect.right = newRect.left + panelWidth;
+ newRect.bottom = newRect.top + panelHeight;
+
+ return newRect;
+ }
+
+ function createLineRect( first, last ) {
+ var newRect = first;
+ newRect.right = last.right;
+ newRect.width = newRect.right - newRect.left;
+
+ if ( last.y ) {
+ newRect.y = last.y;
+ }
+
+ return newRect;
+ }
+
+ function getTopAndBottomRects( rectList ) {
+ var topAlignedRects = getAlignedRects( rectList, true ),
+ bottomAlignedRects = getAlignedRects( rectList ),
+ first = createLineRect( topAlignedRects[ 0 ], topAlignedRects.pop() ),
+ last = createLineRect( bottomAlignedRects[ 0 ], bottomAlignedRects.pop() );
+
+ // Make height of both rects equal to height of whole selection, so panel won't cover selection unless it needs to.
+ first.bottom = last.bottom;
+ first.height = first.bottom - first.top;
+ if ( last.y ) {
+ first.y = last.y;
+ }
+
+ last.top = first.top;
+ last.height = first.height;
+
+ return [ first, last ];
+ }
+
+ function getAlignedRects( rectList, top ) {
+ var edgeRect = top ? rectList [ 0 ] : rectList[ rectList.length - 1 ],
+ alignment = top ? 'top' : 'bottom';
+
+ return CKEDITOR.tools.array.filter( rectList, function( item ) {
+ if ( item[ alignment ] === edgeRect[ alignment ] ) {
+ return item;
+ }
+ } );
+ }
+
+ var triangleRelativePosition = {
+ right: 'left',
+ top: 'bottom',
+ topLeft: 'bottomLeft',
+ topRight: 'bottomRight',
+ bottom: 'top',
+ bottomLeft: 'topLeft',
+ bottomRight: 'topRight',
+ left: 'right'
+ };
+
+ return function( elementOrSelection, options ) {
+ if ( elementOrSelection instanceof CKEDITOR.dom.selection ) {
+ var ranges = elementOrSelection.getRanges(),
+ rectList;
+
+ // Handle fake selection within table.
+ if ( elementOrSelection.isFake && elementOrSelection.isInTable() ) {
+ rectList = CKEDITOR.tools.array.map( ranges, function( item ) {
+ // With table selection the first rect represents `td` element rect. Lets use it in that case.
+ return item.getClientRects( true )[ 0 ];
+ } );
+ } else {
+ rectList = ranges[ ranges.length - 1 ].getClientRects( true );
+ }
+
+ // We need two rects, one representing the first selected line, and other representing the last selected line.
+ var first = rectList[ 0 ],
+ last = rectList[ rectList.length - 1 ],
+ selectionRects;
+
+ if ( first === last ) {
+ selectionRects = [ first ];
+ } else if ( first.top === last.top ) {
+ selectionRects = [ createLineRect( first, last ) ];
+ } else {
+ selectionRects = getTopAndBottomRects( rectList );
+ }
+ }
+
+ if ( options instanceof CKEDITOR.dom.element || !options ) {
+ options = { focusElement: options };
+ }
+
+ options = CKEDITOR.tools.extend( options, {
+ show: true
+ } );
+
+ if ( options.show === true ) {
+ this.show();
+ }
+
+ this.fire( 'attach' );
+
+ winGlobal = CKEDITOR.document.getWindow();
+ frame = this.editor.window.getFrame();
+ editable = this.editor.editable();
+ isInline = editable.isInline();
+
+ if ( !isInline && CKEDITOR.env.safari ) {
+ // Overwrite frame with editor iframe closest parent, because iframe has wrong rect values in mobile Safari (#1076).
+ frame = frame.getParent();
+ }
+
+ var panelWidth = this.getWidth(),
+ panelHeight = this.getHeight(),
+
+ // The area of the panel.
+ panelArea = panelWidth * panelHeight,
+ alignments, minDifferenceAlignment, alignmentRect, areaDifference,
+
+ elementRect = elementOrSelection.getClientRect && elementOrSelection.getClientRect( true ),
+ editorRect = isInline ? editable.getClientRect( true ) : frame.getClientRect( true ),
+
+ viewPaneSize = winGlobal.getViewPaneSize(),
+ winGlobalScroll = winGlobal.getScrollPosition(),
+
+ // allowedRect is the rect into which the panel should fit to remain
+ // both within the visible area of the editor and the viewport, i.e.
+ // the rect area covered by "#":
+ //
+ // [Viewport]
+ // +-------------------------------------+
+ // | [Editor] |
+ // | +--------------------+
+ // | |############| |
+ // | |############| |
+ // | |############| |
+ // | +--------------------+
+ // | |
+ // +-------------------------------------+
+ allowedRect = {
+ top: Math.max( editorRect.top, winGlobalScroll.y ),
+ left: Math.max( editorRect.left, winGlobalScroll.x ),
+ right: Math.min( editorRect.right, viewPaneSize.width + winGlobalScroll.x ),
+ bottom: Math.min( editorRect.bottom, viewPaneSize.height + winGlobalScroll.y )
+ },
+ alignmentKeys;
+
+ // Position balloon on entire view port only when it's real inline mode (#1048).
+ if ( isInline && this.editor.elementMode === CKEDITOR.ELEMENT_MODE_INLINE ) {
+ // In inline we want to limit position within the window.
+ allowedRect = this._getViewPaneRect( winGlobal );
+
+ // We need also consider triangle.
+ allowedRect.right += this.triangleWidth;
+ allowedRect.bottom += this.triangleHeight;
+ }
+
+ // This method will modify elementRect if the element is outside of allowedRect / editorRect.
+ // If it's outside then in
+ if ( selectionRects ) {
+ CKEDITOR.tools.array.forEach( selectionRects, function( item ) {
+ this._adjustElementRect( item, isInline ? allowedRect : editorRect );
+ }, this );
+
+ alignments = this._getAlignments( selectionRects[ 0 ], panelWidth, panelHeight );
+
+ if ( selectionRects.length > 1 ) {
+ alignments[ 'bottom hcenter' ] = this._getAlignments( selectionRects[ 1 ], panelWidth, panelHeight )[ 'bottom hcenter' ];
+ }
+
+ alignmentKeys = {
+ 'top hcenter': true,
+ 'bottom hcenter': true
+ };
+ } else {
+ this._adjustElementRect( elementRect, isInline ? allowedRect : editorRect );
+ alignments = this._getAlignments( elementRect, panelWidth, panelHeight );
+ }
+
+ // Iterate over all possible alignments to find the optimal one.
+ for ( var a in alignmentKeys || alignments ) {
+ // Create a rect which would represent the panel in such alignment.
+ alignmentRect = newPanelRect( alignments[ a ].top, alignments[ a ].left, panelWidth, panelHeight );
+
+ // Calculate the difference between the area of the panel and intersection of allowed rect and alignment rect.
+ // It is the area of the panel, which would be OUT of allowed rect if such alignment was used. Less is better.
+ areaDifference = alignments[ a ].areaDifference = panelArea - rectIntersectArea( alignmentRect, allowedRect );
+
+ // If the difference is 0, it means that the panel is fully within allowed rect. That's great!
+ if ( areaDifference === 0 ) {
+ minDifferenceAlignment = a;
+ break;
+ }
+
+ // If there's no alignment of a minimal area difference, use the first available.
+ if ( !minDifferenceAlignment ) {
+ minDifferenceAlignment = a;
+ }
+
+ // Determine the alignment of a minimal area difference. It will be used as a fallback
+ // if no alignment provides a perfect fit into allowed rect.
+ if ( areaDifference < alignments[ minDifferenceAlignment ].areaDifference ) {
+ minDifferenceAlignment = a;
+ }
+ }
+
+ // For non-static parent elements we need to remove its margin offset from balloon panel (#1048).
+ var parent = this.parts.panel.getAscendant( function( el ) {
+ return el instanceof CKEDITOR.dom.document ? false : el.getComputedStyle( 'position' ) !== 'static';
+ } ),
+ parentMargin = {
+ left: parent ? parseInt( parent.getComputedStyle( 'margin-left' ), 10 ) : 0,
+ top: parent ? parseInt( parent.getComputedStyle( 'margin-top' ), 10 ) : 0
+ };
+
+ this.move( alignments[ minDifferenceAlignment ].top - parentMargin.top , alignments[ minDifferenceAlignment ].left - parentMargin.left );
+
+ minDifferenceAlignment = minDifferenceAlignment.split( ' ' );
+ this.setTriangle( triangleRelativePosition[ minDifferenceAlignment[ 0 ] ], minDifferenceAlignment[ 1 ] );
+
+ // Set focus to proper element.
+ if ( options.focusElement !== false ) {
+ ( options.focusElement || this.parts.panel ).focus();
+ }
+ };
+ } )(),
+
+ /**
+ * Resizes the balloon panel container to given dimensions. Use `'auto'` to
+ * make the dimensions of the panel flexible.
+ *
+ * @param {Number} width
+ * @param {Number} height
+ */
+ resize: function( width, height ) {
+ this.rect.width = width;
+ this.rect.height = height;
+
+ this.parts.panel.setStyles( {
+ width: CKEDITOR.tools.cssLength( width ),
+ height: CKEDITOR.tools.cssLength( height )
+ } );
+ },
+
+ /**
+ * Returns the balloon panel width.
+ *
+ * @returns {Number}
+ */
+ getWidth: function() {
+ return this.rect.width === 'auto' ? this.parts.panel.getClientRect().width : this.rect.width;
+ },
+
+ /**
+ * Returns the balloon panel height.
+ *
+ * @returns {Number}
+ */
+ getHeight: function() {
+ return this.rect.height === 'auto' ? this.parts.panel.getClientRect().height : this.rect.height;
+ },
+
+ /**
+ * Changes the position of the balloon's triangle that points to the element in the editable.
+ *
+ * @param {String} side One of 'left', 'right', 'top' or 'bottom'.
+ */
+ setTriangle: function( side, align ) {
+ var outer = this.parts.triangleOuter,
+ inner = this.parts.triangleInner;
+
+ if ( this.triangleSide ) {
+ outer.removeClass( 'cke_balloon_triangle_' + this.triangleSide );
+ outer.removeClass( 'cke_balloon_triangle_align_' + this.triangleAlign );
+ inner.removeClass( 'cke_balloon_triangle_' + this.triangleSide );
+ }
+
+ this.triangleSide = side;
+ this.triangleAlign = align;
+
+ outer.addClass( 'cke_balloon_triangle_' + side );
+ outer.addClass( 'cke_balloon_triangle_align_' + align );
+ inner.addClass( 'cke_balloon_triangle_' + side );
+ },
+
+ /**
+ * Registers a new focusable element in the editor's focus manager so the instance
+ * does not blur once the child of the balloon panel gains focus.
+ * See {@link #focusables}.
+ *
+ * @param {CKEDITOR.dom.element} element An element to be registered.
+ */
+ registerFocusable: function( element ) {
+ this.editor.focusManager.add( element );
+
+ this.focusables[ element.getUniqueId() ] = element;
+ },
+
+ /**
+ * Unregisters an element from editor's focus manager.
+ * See {@link #focusables}.
+ *
+ * @param {CKEDITOR.dom.element} element An element to be registered.
+ */
+ deregisterFocusable: function( element ) {
+ this.editor.focusManager.remove( element );
+
+ delete this.focusables[ element.getUniqueId() ];
+ },
+
+ /**
+ * Adds an event listener associated with this balloon panel. This listener
+ * will be activated on panel `show` and deactivated on panel `hide`.
+ * See {@link #showListeners}, {@link #activeShowListeners}, {@link #activateShowListeners},
+ * {@link #deactivateShowListeners}.
+ *
+ * @param {Function} listener A function that, if called, attaches the listener
+ * and returns the listener object.
+ * @returns {Object} An object containing the `removeListener` method that removes
+ * the listener from the collection.
+ */
+ addShowListener: function( listener ) {
+ var id = CKEDITOR.tools.getNextNumber();
+
+ // Adds the listener to the register of on-show-activated listeners.
+ this.showListeners[ id ] = listener;
+
+ // Activate listener immediately if panel is already visible.
+ if ( this.rect.visible ) {
+ this.activateShowListener( id );
+ }
+
+ var that = this;
+
+ return {
+ removeListener: function() {
+ that.removeShowListener( id );
+ }
+ };
+ },
+
+ /**
+ * Removes an event listener associated with this balloon panel visible state.
+ * See {@link #addShowListener}.
+ *
+ * @param {Number} id An ID of the listener.
+ */
+ removeShowListener: function( id ) {
+ this.deactivateShowListener( id );
+ delete this.showListeners[ id ];
+ },
+
+ /**
+ * Activates an event listener associated with this balloon panel.
+ * See {@link #showListeners}, {@link #activeShowListeners}, {@link #deactivateShowListener},
+ * {@link #addShowListener}, {@link #removeShowListener}.
+ */
+ activateShowListener: function( id ) {
+ this.activeShowListeners[ id ] = this.showListeners[ id ].call( this );
+ },
+
+ /**
+ * Deactivates an event listener associated with this balloon panel.
+ * See {@link #activateShowListener}.
+ */
+ deactivateShowListener: function( id ) {
+ if ( this.activeShowListeners[ id ] ) {
+ this.activeShowListeners[ id ].removeListener();
+ }
+
+ delete this.activeShowListeners[ id ];
+ },
+
+ /**
+ * Activates all event listeners associated with this balloon panel.
+ * See {@link #showListeners}, {@link #activeShowListeners}, {@link #deactivateShowListeners},
+ * {@link #addShowListener}, {@link #removeShowListener}.
+ */
+ activateShowListeners: function() {
+ for ( var id in this.showListeners ) {
+ this.activateShowListener( id );
+ }
+ },
+
+ /**
+ * Removes all event listeners associated with this balloon panel.
+ * See {@link #activateShowListeners}.
+ */
+ deactivateShowListeners: function() {
+ for ( var id in this.activeShowListeners ) {
+ this.deactivateShowListener( id );
+ }
+ },
+
+ /**
+ * Destroys the balloon panel by removing it from DOM and purging
+ * all associated event listeners.
+ */
+ destroy: function() {
+ this.deactivateShowListeners();
+ this.parts.panel.remove();
+ },
+
+ /**
+ * Sets the balloon panel title.
+ *
+ * @param {String} title A new panel title.
+ */
+ setTitle: function( title ) {
+ this.parts.title.setHtml( title );
+ },
+
+ /**
+ * Returns a dictionary containing different alignment positions.
+ *
+ * Keys tell where the balloon is positioned relative to the element, e.g. this would be the result for "top center":
+ *
+ * [Editor]
+ * +-------------------------------------+
+ * | [Panel] |
+ * | +-----------------+ |
+ * | | | |
+ * | [El.] +--------v--------+ |
+ * | +-------------------------------+ |
+ * | | | |
+ * | | | |
+ * +--+-------------------------------+--+
+ *
+ * Sample result:
+ *
+ * {
+ * "right vcenter": { top: 529.5, left: 175 },
+ * "left vcenter": { top: 529.5, left: 10},
+ * "top hcenter": { top: 402, left: 92.5},
+ * "top left": { top: 402, left: 102.5},
+ * "top right": { top: 402, left: 82.5},
+ * "bottom hcenter": { top: 643, left: 92.5},
+ * "bottom left": { top: 643, left: 102.5},
+ * "bottom right": { top: 643, left: 82.5}
+ * }
+ *
+ * @private
+ * @param elementRect
+ * @param {Number} panelWidth
+ * @param {Number} panelHeight
+ * @returns {Object}
+ */
+ _getAlignments: function( elementRect, panelWidth, panelHeight ) {
+ return {
+ 'right vcenter': {
+ top: elementRect.top + elementRect.height / 2 - panelHeight / 2,
+ left: elementRect.right + this.triangleWidth
+ },
+ 'left vcenter': {
+ top: elementRect.top + elementRect.height / 2 - panelHeight / 2,
+ left: elementRect.left - panelWidth - this.triangleWidth
+ },
+ 'top hcenter': {
+ top: elementRect.top - panelHeight - this.triangleHeight,
+ left: elementRect.left + elementRect.width / 2 - panelWidth / 2
+ },
+ 'top left': {
+ top: elementRect.top - panelHeight - this.triangleHeight,
+ left: elementRect.left + elementRect.width / 2 - this.triangleMinDistance
+ },
+ 'top right': {
+ top: elementRect.top - panelHeight - this.triangleHeight,
+ left: elementRect.right - elementRect.width / 2 - panelWidth + this.triangleMinDistance
+ },
+ 'bottom hcenter': {
+ top: elementRect.bottom + this.triangleHeight,
+ left: elementRect.left + elementRect.width / 2 - panelWidth / 2
+ },
+ 'bottom left': {
+ top: elementRect.bottom + this.triangleHeight,
+ left: elementRect.left + elementRect.width / 2 - this.triangleMinDistance
+ },
+ 'bottom right': {
+ top: elementRect.bottom + this.triangleHeight,
+ left: elementRect.right - elementRect.width / 2 - panelWidth + this.triangleMinDistance
+ }
+ };
+ },
+
+ /**
+ * This method will modify `elementRect` if the element is outside of `editorRect`. If it is outside, it is
+ * going to change it into a rectangle that is within `editorRect`.
+ *
+ * For example here `elementRect` is going to be changed into a very narrow rectangle (with unmodified height)
+ * representation within `editorRect`.
+ *
+ * +------------------------------------------+
+ * | |
+ * | #| +----------+
+ * | #| | |
+ * | #| | |
+ * | editorRect #| |elmentRect|
+ * | #| | |
+ * | #| | |
+ * | #| +----------+
+ * | |
+ * +------------------------------------------+
+ *
+ * @private
+ * @param elementRect Rectangle object that should be contained within `editorRect`. **This object might be modified.**
+ * @param editorRect Reference container that should contain `elementRect`.
+ */
+ _adjustElementRect: function( elementRect, editorRect ) {
+ elementRect.left = numberInRange( editorRect.left, editorRect.right - 1, elementRect.left );
+ elementRect.right = numberInRange( editorRect.left, editorRect.right, elementRect.right );
+ elementRect.top = numberInRange( editorRect.top, editorRect.bottom - 1, elementRect.top );
+ elementRect.bottom = numberInRange( editorRect.top, editorRect.bottom, elementRect.bottom );
+ },
+
+ /**
+ * @param {CKEDITOR.dom.window} window
+ * @returns {Object} Returns viewport position, taking scroll offset into account.
+ * @returns {Number} return.top
+ * @returns {Number} return.bottom
+ * @returns {Number} return.left
+ * @returns {Number} return.right
+ */
+ _getViewPaneRect: function( window ) {
+ var pos = window.getScrollPosition(),
+ viewSize = window.getViewPaneSize();
+
+ return {
+ top: pos.y,
+ bottom: pos.y + viewSize.height,
+ left: pos.x,
+ right: pos.x + viewSize.width
+ };
+ }
+ };
+
+ function numberInRange( min, max, num ) {
+ return Math.max( min, Math.min( max, num ) );
+ }
+
+ CKEDITOR.event.implementOn( CKEDITOR.ui.balloonPanel.prototype );
+
+ /**
+ * The definition of a balloon panel.
+ *
+ * This virtual class illustrates the properties that developers can use to define and create
+ * balloon panels.
+ *
+ * CKEDITOR.ui.balloonPanel( editor, {
+ * title: 'My Panel',
+ * onShow: function() {
+ * ...
+ * }
+ * } );
+ *
+ * @class CKEDITOR.ui.balloonPanel.definition
+ */
+
+ /**
+ * The title of the balloon panel.
+ *
+ * @member CKEDITOR.ui.balloonPanel.definition
+ * @property {String} title
+ */
+
+ /**
+ * The static content of the balloon panel.
+ *
+ * @member CKEDITOR.ui.balloonPanel.definition
+ * @property {String} content
+ */
+} )();
diff --git a/plugins/ckeditor/balloonpanel/skins/kama/balloonpanel.css b/plugins/ckeditor/balloonpanel/skins/kama/balloonpanel.css
new file mode 100644
index 0000000..7f653af
--- /dev/null
+++ b/plugins/ckeditor/balloonpanel/skins/kama/balloonpanel.css
@@ -0,0 +1,220 @@
+/*
+Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+*/
+
+.cke_balloon
+{
+ position: absolute;
+ z-index: 10000;
+
+ background: #fff;
+ border: 1px solid #b2b2b2;
+ border-bottom-color: #999;
+
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
+
+ -moz-box-shadow: 0 0 3px rgba(0, 0, 0, .15);
+ -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, .15);
+ box-shadow: 0 0 3px rgba(0, 0, 0, .15);
+
+ outline: none;
+}
+
+.cke_balloon_title
+{
+ font-weight: bold;
+ font-size: 14px;
+ cursor: default;
+
+ color: #474747;
+ text-shadow: 0 1px 0 rgba(255,255,255,.75);
+
+ padding: 3px 3px 8px;
+ border-bottom: 1px solid #eee;
+
+ -moz-border-radius: 2px 2px 0 0;
+ -webkit-border-radius: 2px 2px 0 0;
+ border-radius: 2px 2px 0 0;
+
+ -moz-box-shadow: 0 1px 0 #fff inset;
+ -webkit-box-shadow: 0 1px 0 #fff inset;
+ box-shadow: 0 1px 0 #fff inset;
+}
+
+/* The close button at the top of the panel. */
+a.cke_balloon_close_button
+{
+ background-image: url(../../../../skins/kama/images/sprites.png);
+ background-repeat: no-repeat;
+ background-position: 0 -1022px;
+ position: absolute;
+ cursor: pointer;
+ text-align: center;
+ height: 20px;
+ width: 20px;
+ top: 5px;
+}
+
+a.cke_balloon_close_button:hover {
+ background-position: 0 -1045px;
+}
+
+.cke_balloon_content
+{
+ overflow: hidden;
+ min-height: 68px;
+}
+
+.cke_balloon_close_button:hover
+{
+ opacity: 1;
+ filter: alpha(opacity = 100);
+}
+
+.cke_balloon_close_button span
+{
+ display: none;
+}
+
+.cke_ltr .cke_balloon_close_button
+{
+ right: 5px;
+}
+
+.cke_rtl .cke_balloon_close_button
+{
+ left: 6px;
+}
+
+.cke_balloon_triangle
+{
+ position: absolute;
+ border-style: solid;
+ display: block;
+ width: 0;
+ height: 0;
+}
+
+.cke_balloon_triangle_inner
+{
+ z-index: 0;
+}
+
+.cke_balloon_triangle_outer
+{
+ z-index: 0;
+}
+
+/* side: [ bottom, top ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_bottom,
+ .cke_balloon_triangle_outer.cke_balloon_triangle_top
+ {
+ border-color: #6B6B6B transparent;
+ }
+
+ .cke_balloon_triangle_inner.cke_balloon_triangle_bottom,
+ .cke_balloon_triangle_inner.cke_balloon_triangle_top
+ {
+ left: -20px;
+ }
+
+/* side: [ bottom ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_bottom
+ {
+ border-width: 20px 20px 0;
+ bottom: -20px;
+ }
+
+ .cke_balloon_triangle_inner.cke_balloon_triangle_bottom
+ {
+ border-color: #fff transparent;
+ border-width: 20px 20px 0;
+ top: -21px;
+ }
+
+/* side: [ top ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_top
+ {
+ border-width: 0 20px 20px;
+ top: -20px;
+ }
+
+ .cke_balloon_triangle_inner.cke_balloon_triangle_top
+ {
+ border-color: #fff transparent;
+ border-width: 0 20px 20px;
+ top: 1px;
+ }
+
+/* side: [ left, right ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_left,
+ .cke_balloon_triangle_outer.cke_balloon_triangle_right
+ {
+ border-color: transparent #6B6B6B;
+ }
+
+ .cke_balloon_triangle_inner.cke_balloon_triangle_left,
+ .cke_balloon_triangle_inner.cke_balloon_triangle_right
+ {
+ border-color: transparent #fff;
+ top: -20px;
+ }
+
+/* side: [ left ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_left
+ {
+ border-width: 20px 20px 20px 0;
+ left: -20px;
+ }
+
+ .cke_balloon_triangle_inner.cke_balloon_triangle_left
+ {
+ border-color: transparent #fff;
+ border-width: 20px 20px 20px 0;
+ left: 1px;
+ }
+
+/* side: [ right ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_right
+ {
+ border-width: 20px 0 20px 20px;
+ right: -20px;
+ }
+
+ .cke_balloon_triangle_inner.cke_balloon_triangle_right
+ {
+ border-width: 20px 0 20px 20px;
+ right: 1px;
+ }
+
+
+/* align: [ hcenter ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_align_hcenter
+ {
+ left: 50%;
+ margin-left: -20px;
+ }
+
+/* align: [ left ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_align_left
+ {
+ left: 20px;
+ margin-left: 0;
+ }
+
+/* align: [ right ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_align_right
+ {
+ right: 20px;
+ margin-left: 0;
+ }
+
+/* align: [ vcenter ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_align_vcenter
+ {
+ top: 50%;
+ margin-top: -20px;
+ }
diff --git a/plugins/ckeditor/balloonpanel/skins/moono-lisa/balloonpanel.css b/plugins/ckeditor/balloonpanel/skins/moono-lisa/balloonpanel.css
new file mode 100644
index 0000000..ccaae48
--- /dev/null
+++ b/plugins/ckeditor/balloonpanel/skins/moono-lisa/balloonpanel.css
@@ -0,0 +1,223 @@
+/*
+Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+*/
+
+.cke_balloon
+{
+ position: absolute;
+ z-index: 10000;
+
+ background: #fff;
+ border: 2px solid #aaa;
+ outline: none;
+}
+
+.cke_balloon_title
+{
+ font-weight: bold;
+ font-size: 12px;
+ cursor: default;
+
+ color: #484848;
+
+ padding: 12px 30px 12px 12px; /* Let's the title and close don't overlap each other - padding-right. */
+ background: #f8f8f8;
+}
+
+/* The close button at the top of the panel. */
+a.cke_balloon_close_button
+{
+ background-image: url(images/close.png);
+ background-repeat: no-repeat;
+ background-position: 50% -1px;
+ position: absolute;
+ cursor: pointer;
+ text-align: center;
+ height: 16px;
+ width: 16px;
+ top: 8px;
+ z-index: 5;
+ opacity: 0.7;
+ filter: alpha(opacity = 70);
+ border: 2px solid transparent;
+ border-radius: 2px;
+}
+
+a.cke_balloon_close_button:focus,
+a.cke_balloon_close_button:active
+{
+ outline: none;
+ border: 2px solid #0079f7;
+}
+
+.cke_balloon_content
+{
+ overflow: hidden;
+ min-height: 68px;
+ padding: 0 6px 6px 6px;
+}
+
+.cke_balloon_close_button:hover
+{
+ opacity: 1;
+ filter: alpha(opacity = 100);
+}
+
+.cke_balloon_close_button:focus:hover
+{
+ opacity: 1;
+ filter: alpha(opacity = 100);
+ border: 2px solid #139FF7;
+}
+
+.cke_hidpi .cke_balloon_close_button
+{
+ background-image: url(images/hidpi/close.png);
+ background-size: 16px;
+}
+
+.cke_balloon_close_button span
+{
+ display: none;
+}
+
+.cke_ltr .cke_balloon_close_button
+{
+ right: 10px;
+}
+
+.cke_rtl .cke_balloon_close_button
+{
+ left: 10px;
+}
+
+.cke_balloon_triangle
+{
+ position: absolute;
+ border-style: solid;
+ display: block;
+ width: 0;
+ height: 0;
+}
+
+.cke_balloon_triangle_inner
+{
+ z-index: 0;
+}
+
+.cke_balloon_triangle_outer
+{
+ z-index: 0;
+}
+
+/* side: [ bottom, top ] */
+.cke_balloon_triangle_outer.cke_balloon_triangle_bottom,
+.cke_balloon_triangle_outer.cke_balloon_triangle_top
+{
+ border-color: #999 transparent;
+}
+
+.cke_balloon_triangle_inner.cke_balloon_triangle_bottom,
+.cke_balloon_triangle_inner.cke_balloon_triangle_top
+{
+ left: -20px;
+}
+
+/* side: [ bottom ] */
+.cke_balloon_triangle_outer.cke_balloon_triangle_bottom
+{
+ border-width: 20px 20px 0;
+ bottom: -20px;
+}
+
+.cke_balloon_triangle_inner.cke_balloon_triangle_bottom
+{
+ border-color: #fff transparent;
+ border-width: 20px 20px 0;
+ top: -22px;
+}
+
+/* side: [ top ] */
+.cke_balloon_triangle_outer.cke_balloon_triangle_top
+{
+ border-width: 0 20px 20px;
+ top: -20px;
+}
+
+.cke_balloon_triangle_inner.cke_balloon_triangle_top
+{
+ border-color: #f8f8f8 transparent;
+ border-width: 0 20px 20px;
+ top: 2px;
+}
+
+/* side: [ left, right ] */
+.cke_balloon_triangle_outer.cke_balloon_triangle_left,
+.cke_balloon_triangle_outer.cke_balloon_triangle_right
+{
+ border-color: transparent #999;
+}
+
+.cke_balloon_triangle_inner.cke_balloon_triangle_left,
+.cke_balloon_triangle_inner.cke_balloon_triangle_right
+{
+ border-color: transparent #fff;
+ top: -20px;
+}
+
+/* side: [ left ] */
+.cke_balloon_triangle_outer.cke_balloon_triangle_left
+{
+ border-width: 20px 20px 20px 0;
+ left: -20px;
+}
+
+.cke_balloon_triangle_inner.cke_balloon_triangle_left
+{
+ border-color: transparent #fff;
+ border-width: 20px 20px 20px 0;
+ left: 2px;
+}
+
+/* side: [ right ] */
+.cke_balloon_triangle_outer.cke_balloon_triangle_right
+{
+ border-width: 20px 0 20px 20px;
+ right: -20px;
+}
+
+.cke_balloon_triangle_inner.cke_balloon_triangle_right
+{
+ border-width: 20px 0 20px 20px;
+ right: 2px;
+}
+
+
+/* align: [ hcenter ] */
+.cke_balloon_triangle_outer.cke_balloon_triangle_align_hcenter
+{
+ left: 50%;
+ margin-left: -20px;
+}
+
+/* align: [ left ] */
+.cke_balloon_triangle_outer.cke_balloon_triangle_align_left
+{
+ left: 20px;
+ margin-left: 0;
+}
+
+/* align: [ right ] */
+.cke_balloon_triangle_outer.cke_balloon_triangle_align_right
+{
+ right: 20px;
+ margin-left: 0;
+}
+
+/* align: [ vcenter ] */
+.cke_balloon_triangle_outer.cke_balloon_triangle_align_vcenter
+{
+ top: 50%;
+ margin-top: -20px;
+}
diff --git a/plugins/ckeditor/balloonpanel/skins/moono-lisa/images/close.png b/plugins/ckeditor/balloonpanel/skins/moono-lisa/images/close.png
new file mode 100644
index 0000000..40caa6d
Binary files /dev/null and b/plugins/ckeditor/balloonpanel/skins/moono-lisa/images/close.png differ
diff --git a/plugins/ckeditor/balloonpanel/skins/moono-lisa/images/hidpi/close.png b/plugins/ckeditor/balloonpanel/skins/moono-lisa/images/hidpi/close.png
new file mode 100644
index 0000000..0e4aa2e
Binary files /dev/null and b/plugins/ckeditor/balloonpanel/skins/moono-lisa/images/hidpi/close.png differ
diff --git a/plugins/ckeditor/balloonpanel/skins/moono/balloonpanel.css b/plugins/ckeditor/balloonpanel/skins/moono/balloonpanel.css
new file mode 100644
index 0000000..103dc82
--- /dev/null
+++ b/plugins/ckeditor/balloonpanel/skins/moono/balloonpanel.css
@@ -0,0 +1,237 @@
+/*
+Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+*/
+
+.cke_balloon
+{
+ position: absolute;
+ z-index: 10000;
+
+ background: #fff;
+ border: 1px solid #b2b2b2;
+ border-bottom-color: #999;
+
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
+
+ -moz-box-shadow: 0 0 3px rgba(0, 0, 0, .15);
+ -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, .15);
+ box-shadow: 0 0 3px rgba(0, 0, 0, .15);
+
+ outline: none;
+}
+
+.cke_balloon_title
+{
+ font-weight: bold;
+ font-size: 13px;
+ cursor: default;
+
+ color: #474747;
+ text-shadow: 0 1px 0 rgba(255,255,255,.75);
+
+ border-bottom: 1px solid #999;
+ padding: 6px 10px;
+
+ -moz-border-radius: 2px 2px 0 0;
+ -webkit-border-radius: 2px 2px 0 0;
+ border-radius: 2px 2px 0 0;
+
+ -moz-box-shadow: 0 1px 0 #fff inset;
+ -webkit-box-shadow: 0 1px 0 #fff inset;
+ box-shadow: 0 1px 0 #fff inset;
+
+ /* Let's the title and close don't overlap each other */
+ padding-right: 30px;
+
+ background: #cfd1cf;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#cfd1cf));
+ background-image: -moz-linear-gradient(top, #f5f5f5, #cfd1cf);
+ background-image: -webkit-linear-gradient(top, #f5f5f5, #cfd1cf);
+ background-image: -o-linear-gradient(top, #f5f5f5, #cfd1cf);
+ background-image: -ms-linear-gradient(top, #f5f5f5, #cfd1cf);
+ background-image: linear-gradient(top, #f5f5f5, #cfd1cf);
+ filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#f5f5f5', endColorstr='#cfd1cf');
+}
+
+/* The close button at the top of the panel. */
+a.cke_balloon_close_button
+{
+ background-image: url(images/close.png);
+ background-repeat: no-repeat;
+ background-position: 50%;
+ position: absolute;
+ cursor: pointer;
+ text-align: center;
+ height: 20px;
+ width: 20px;
+ top: 3px;
+ z-index: 5;
+ opacity: 0.8;
+ filter: alpha(opacity = 80);
+}
+
+.cke_balloon_content
+{
+ overflow: hidden;
+ min-height: 68px;
+}
+
+.cke_balloon_close_button:hover
+{
+ opacity: 1;
+ filter: alpha(opacity = 100);
+}
+
+.cke_hidpi .cke_balloon_close_button
+{
+ background-image: url(images/hidpi/close.png);
+ background-size: 16px;
+}
+
+.cke_balloon_close_button span
+{
+ display: none;
+}
+
+.cke_ltr .cke_balloon_close_button
+{
+ right: 5px;
+}
+
+.cke_rtl .cke_balloon_close_button
+{
+ left: 6px;
+}
+
+.cke_balloon_triangle
+{
+ position: absolute;
+ border-style: solid;
+ display: block;
+ width: 0;
+ height: 0;
+}
+
+.cke_balloon_triangle_inner
+{
+ z-index: 0;
+}
+
+.cke_balloon_triangle_outer
+{
+ z-index: 0;
+}
+
+/* side: [ bottom, top ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_bottom,
+ .cke_balloon_triangle_outer.cke_balloon_triangle_top
+ {
+ border-color: #6B6B6B transparent;
+ }
+
+ .cke_balloon_triangle_inner.cke_balloon_triangle_bottom,
+ .cke_balloon_triangle_inner.cke_balloon_triangle_top
+ {
+ left: -20px;
+ }
+
+/* side: [ bottom ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_bottom
+ {
+ border-width: 20px 20px 0;
+ bottom: -20px;
+ }
+
+ .cke_balloon_triangle_inner.cke_balloon_triangle_bottom
+ {
+ border-color: #fff transparent;
+ border-width: 20px 20px 0;
+ top: -21px;
+ }
+
+/* side: [ top ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_top
+ {
+ border-width: 0 20px 20px;
+ top: -20px;
+ }
+
+ .cke_balloon_triangle_inner.cke_balloon_triangle_top
+ {
+ border-color: #f5f5f5 transparent;
+ border-width: 0 20px 20px;
+ top: 1px;
+ }
+
+/* side: [ left, right ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_left,
+ .cke_balloon_triangle_outer.cke_balloon_triangle_right
+ {
+ border-color: transparent #6B6B6B;
+ }
+
+ .cke_balloon_triangle_inner.cke_balloon_triangle_left,
+ .cke_balloon_triangle_inner.cke_balloon_triangle_right
+ {
+ border-color: transparent #fff;
+ top: -20px;
+ }
+
+/* side: [ left ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_left
+ {
+ border-width: 20px 20px 20px 0;
+ left: -20px;
+ }
+
+ .cke_balloon_triangle_inner.cke_balloon_triangle_left
+ {
+ border-color: transparent #fff;
+ border-width: 20px 20px 20px 0;
+ left: 1px;
+ }
+
+/* side: [ right ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_right
+ {
+ border-width: 20px 0 20px 20px;
+ right: -20px;
+ }
+
+ .cke_balloon_triangle_inner.cke_balloon_triangle_right
+ {
+ border-width: 20px 0 20px 20px;
+ right: 1px;
+ }
+
+
+/* align: [ hcenter ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_align_hcenter
+ {
+ left: 50%;
+ margin-left: -20px;
+ }
+
+/* align: [ left ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_align_left
+ {
+ left: 20px;
+ margin-left: 0;
+ }
+
+/* align: [ right ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_align_right
+ {
+ right: 20px;
+ margin-left: 0;
+ }
+
+/* align: [ vcenter ] */
+ .cke_balloon_triangle_outer.cke_balloon_triangle_align_vcenter
+ {
+ top: 50%;
+ margin-top: -20px;
+ }
diff --git a/plugins/ckeditor/balloonpanel/skins/moono/images/close.png b/plugins/ckeditor/balloonpanel/skins/moono/images/close.png
new file mode 100644
index 0000000..04b9c97
Binary files /dev/null and b/plugins/ckeditor/balloonpanel/skins/moono/images/close.png differ
diff --git a/plugins/ckeditor/balloonpanel/skins/moono/images/hidpi/close.png b/plugins/ckeditor/balloonpanel/skins/moono/images/hidpi/close.png
new file mode 100644
index 0000000..e406c2c
Binary files /dev/null and b/plugins/ckeditor/balloonpanel/skins/moono/images/hidpi/close.png differ
diff --git a/plugins/ckeditor/helper.js b/plugins/ckeditor/helper.js
new file mode 100644
index 0000000..563a5fb
--- /dev/null
+++ b/plugins/ckeditor/helper.js
@@ -0,0 +1,37 @@
+define(function (require, exports, module) {
+
+ var CKEDITOR = window.CKEDITOR;
+
+ return {
+ registerPlugin: function (pluginId, moduleId) {
+ var pluginPath = "../../../" + moduleId + "/oup-ckeditor/plugins/ckeditor/wordcount/";
+
+ CKEDITOR.plugins.addExternal(pluginId, pluginPath, 'plugin.js');
+
+ if (CKEDITOR.config.extraPlugins.length > 0) {
+ CKEDITOR.config.extraPlugins += ",";
+ }
+ CKEDITOR.config.extraPlugins += pluginId;
+ },
+ registerPlugin1: function (pluginId, moduleId) {
+ var pluginPath = "../../../" + moduleId + "/oup-ckeditor/plugins/ckeditor/a11ychecker/";
+
+ CKEDITOR.plugins.addExternal(pluginId, pluginPath, 'plugin.js');
+
+ if (CKEDITOR.config.extraPlugins.length > 0) {
+ CKEDITOR.config.extraPlugins += ",";
+ }
+ CKEDITOR.config.extraPlugins += pluginId;
+ },
+ registerPlugin2: function (pluginId, moduleId) {
+ var pluginPath = "../../../" + moduleId + "/oup-ckeditor/plugins/ckeditor/balloonpanel/";
+
+ CKEDITOR.plugins.addExternal(pluginId, pluginPath, 'plugin.js');
+
+ if (CKEDITOR.config.extraPlugins.length > 0) {
+ CKEDITOR.config.extraPlugins += ",";
+ }
+ CKEDITOR.config.extraPlugins += pluginId;
+ }
+ };
+});
\ No newline at end of file
diff --git a/plugins/ckeditor/wordcount/css/wordcount.css b/plugins/ckeditor/wordcount/css/wordcount.css
new file mode 100644
index 0000000..fe72026
--- /dev/null
+++ b/plugins/ckeditor/wordcount/css/wordcount.css
@@ -0,0 +1,3 @@
+.cke_wordcount {display:block;float:right;margin-top:-2px;margin-right:3px;color:black;}
+
+.cke_wordcountLimitReached {color:red! important}
\ No newline at end of file
diff --git a/plugins/ckeditor/wordcount/index.js b/plugins/ckeditor/wordcount/index.js
new file mode 100644
index 0000000..3b8b6bd
--- /dev/null
+++ b/plugins/ckeditor/wordcount/index.js
@@ -0,0 +1,15 @@
+define(function (require, exports, module) {
+
+ var Helper = require("../helper.js");
+ var moduleId = module.uri.match(/^.+(_modules[^\/]+)\/.*/)[1];
+ Helper.registerPlugin("wordcount", moduleId);
+ window.CKEDITOR.config.wordcount = {
+ showParagraphs: false,
+ showWordCount: false,
+ showCharCount: false,
+ countSpacesAsChars: false,
+ countHTML: false
+ //maxWordCount: 10,
+ //maxCharCount: 10
+ };
+});
\ No newline at end of file
diff --git a/plugins/ckeditor/wordcount/lang/ar.js b/plugins/ckeditor/wordcount/lang/ar.js
new file mode 100644
index 0000000..7c181a4
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/ar.js
@@ -0,0 +1,12 @@
+// Arabic Translation by Amine BENHAMIDA
+
+CKEDITOR.plugins.setLang('wordcount', 'ar', {
+ WordCount: 'كلمات:',
+ CharCount: 'حروف:',
+ CharCountWithHTML: 'حروف مع إتش تي إم إل',
+ Paragraphs: 'فقرات',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'لا يمكن اضافة هذا المحتوى لانه تجاوز الحد الاقصى',
+ Selected: 'محدد: ',
+ title: 'احصائيات'
+});
diff --git a/plugins/ckeditor/wordcount/lang/bg.js b/plugins/ckeditor/wordcount/lang/bg.js
new file mode 100644
index 0000000..1e37b6b
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/bg.js
@@ -0,0 +1,17 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'bg', {
+ WordCount: 'Думи:',
+ WordCountRemaining: 'Оставащи думи',
+ CharCount: 'Знаци:',
+ CharCountRemaining: 'Знаци',
+ CharCountWithHTML: 'Знаци (с HTML):',
+ CharCountWithHTMLRemaining: 'Оставащи знаци (с HTML)',
+ Paragraphs: 'Параграфи:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'Съдържанието не може да бъде поставено, защото е над разрешения лимит',
+ Selected: 'Избрани: ',
+ title: 'Статистика'
+});
diff --git a/plugins/ckeditor/wordcount/lang/ca.js b/plugins/ckeditor/wordcount/lang/ca.js
new file mode 100644
index 0000000..19f67c4
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/ca.js
@@ -0,0 +1,14 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'ca', {
+ WordCount: 'Paraules:',
+ CharCount: 'Caràcters:',
+ CharCountWithHTML: 'Caràcters (including HTML):',
+ Paragraphs: 'Paragraphs:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'Content can not be pasted because it is above the allowed limit',
+ Selected: 'Selected: ',
+ title: 'Estadístiques'
+});
diff --git a/plugins/ckeditor/wordcount/lang/cs.js b/plugins/ckeditor/wordcount/lang/cs.js
new file mode 100644
index 0000000..6dbd0bf
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/cs.js
@@ -0,0 +1,15 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'cs',
+ {
+ WordCount: 'Slov: ',
+ CharCount: 'Znaků: ',
+ CharCountWithHTML: 'Znaků (s HTML): ',
+ Paragraphs: 'Odstavců: ',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'Obsah nelze vložit',
+ Selected: 'Výběr: ',
+ title: 'Statistika'
+ });
\ No newline at end of file
diff --git a/plugins/ckeditor/wordcount/lang/da.js b/plugins/ckeditor/wordcount/lang/da.js
new file mode 100644
index 0000000..aaf781a
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/da.js
@@ -0,0 +1,14 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'da', {
+ WordCount: 'Ord:',
+ CharCount: 'Karakterer:',
+ CharCountWithHTML: 'Karakterer (med HTML):',
+ Paragraphs: 'Afsnit:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'Indholdet kan ikke indsættes da det er længere end den tilladte grænse.',
+ Selected: 'Markeret: ',
+ title: 'Statistik'
+});
diff --git a/plugins/ckeditor/wordcount/lang/de.js b/plugins/ckeditor/wordcount/lang/de.js
new file mode 100644
index 0000000..42e298d
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/de.js
@@ -0,0 +1,14 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'de', {
+ WordCount: 'Wörter:',
+ CharCount: 'Zeichen:',
+ CharCountWithHTML: 'Zeichen (inkl. HTML):',
+ Paragraphs: 'Absätze:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'Content can not be pasted because it is above the allowed limit',
+ Selected: 'Selected: ',
+ title: 'Statistik'
+});
diff --git a/plugins/ckeditor/wordcount/lang/el.js b/plugins/ckeditor/wordcount/lang/el.js
new file mode 100644
index 0000000..2643c22
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/el.js
@@ -0,0 +1,14 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'el', {
+ WordCount: 'Λέξεις:',
+ CharCount: 'Χαρακτήρες:',
+ CharCountWithHTML: 'Χαρακτήρες (μαζί με HTML):',
+ Paragraphs: 'Paragraphs:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'Content can not be pasted because it is above the allowed limit',
+ Selected: 'Selected: ',
+ title: 'Στατιστικά'
+});
diff --git a/plugins/ckeditor/wordcount/lang/en.js b/plugins/ckeditor/wordcount/lang/en.js
new file mode 100644
index 0000000..581790f
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/en.js
@@ -0,0 +1,17 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'en', {
+ WordCount: 'Words:',
+ WordCountRemaining: 'Words remaining',
+ CharCount: 'Characters:',
+ CharCountRemaining: 'Characters remaining',
+ CharCountWithHTML: 'Characters (with HTML):',
+ CharCountWithHTMLRemaining: 'Characters (with HTML) remaining',
+ Paragraphs: 'Paragraphs:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'Content cannot be pasted because it is above the allowed limit',
+ Selected: 'Selected: ',
+ title: 'Statistics'
+});
diff --git a/plugins/ckeditor/wordcount/lang/es.js b/plugins/ckeditor/wordcount/lang/es.js
new file mode 100644
index 0000000..8cd41ff
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/es.js
@@ -0,0 +1,14 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'es', {
+ WordCount: 'Palabras:',
+ CharCount: 'Carácteres:',
+ CharCountWithHTML: 'Carácteres (con HTML):',
+ Paragraphs: 'Párrafos:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'El contenido no se puede pegar, ya que se encuentra fuera del límite permitido',
+ Selected: 'Seleccionado: ',
+ title: 'Estadísticas'
+});
diff --git a/plugins/ckeditor/wordcount/lang/eu.js b/plugins/ckeditor/wordcount/lang/eu.js
new file mode 100644
index 0000000..3d2e9c1
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/eu.js
@@ -0,0 +1,17 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'eu', {
+ WordCount: 'Hitzak:',
+ WordCountRemaining: 'Gelditzen diren hitzak',
+ CharCount: 'Karaktereak:',
+ CharCountRemaining: 'Gelditzen diren karaktereak',
+ CharCountWithHTML: 'Karaktereak (HTMLarekin):',
+ CharCountWithHTMLRemaining: 'Gelditzen diren karaktereak (HTMLarekin)',
+ Paragraphs: 'Paragrafoak:',
+ ParagraphsRemaining: 'Gelditzen diren paragrafoak',
+ pasteWarning: 'Ezin da edukia itsatsi, onartutako muga gainditu duelako',
+ Selected: 'Hautatuta: ',
+ title: 'Estatistikak'
+});
diff --git a/plugins/ckeditor/wordcount/lang/fa.js b/plugins/ckeditor/wordcount/lang/fa.js
new file mode 100644
index 0000000..e679255
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/fa.js
@@ -0,0 +1,13 @@
+/*
+Its The Persian (Farsi) Language Translate For Iranian By "Mohsen Esmaili"
+*/
+CKEDITOR.plugins.setLang('wordcount', 'fa', {
+ WordCount: 'لغت:',
+ CharCount: 'کاراکتر:',
+ CharCountWithHTML: 'کاراکترها (با HTML):',
+ Paragraphs: 'پاراگراف:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'محتوای مورد نظر را نمی توان چسباند. زیرا این بیشتر از حد مجاز است.',
+ Selected: 'انتخاب شده: ',
+ title: 'آمار'
+});
\ No newline at end of file
diff --git a/plugins/ckeditor/wordcount/lang/fi.js b/plugins/ckeditor/wordcount/lang/fi.js
new file mode 100644
index 0000000..827a72f
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/fi.js
@@ -0,0 +1,15 @@
+/**
+ * Finnish localisation.
+ *
+ * @author Joel Posti / Response200.pro
+ */
+CKEDITOR.plugins.setLang('wordcount', 'fi', {
+ WordCount: 'Sanoja:',
+ CharCount: 'Merkkejä:',
+ CharCountWithHTML: 'Merkkejä (ml. HTML):',
+ Paragraphs: 'Kappaleita:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'Sisältöä ei voida liittää, koska se ylittää sallitun rajan.',
+ Selected: 'Valittuna: ',
+ title: 'Statistiikkaa'
+});
diff --git a/plugins/ckeditor/wordcount/lang/fr.js b/plugins/ckeditor/wordcount/lang/fr.js
new file mode 100644
index 0000000..1fa562b
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/fr.js
@@ -0,0 +1,12 @@
+// French Translation by Nicolas M. et Pierre-Luc Auclair
+
+CKEDITOR.plugins.setLang('wordcount', 'fr', {
+ WordCount: 'Mots :',
+ CharCount: 'Caractères :',
+ CharCountWithHTML: 'Caractères (incluant HTML) :',
+ Paragraphs: 'Paragraphes :',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'Le contenu ne peut pas être collé car il dépasse la limite autorisée',
+ Selected: 'Sélectionné :',
+ title: 'Statistiques'
+});
diff --git a/plugins/ckeditor/wordcount/lang/he.js b/plugins/ckeditor/wordcount/lang/he.js
new file mode 100644
index 0000000..43895e0
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/he.js
@@ -0,0 +1,14 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'he', {
+ WordCount: 'מילים:',
+ CharCount: 'תווים:',
+ CharCountWithHTML: 'תווים (כולל HTML):',
+ Paragraphs: 'פסקאות:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'לא ניתן להדביק תוכן בשל עודף תווים',
+ Selected: 'נבחר: ',
+ title: 'סטטיסטיקות'
+});
\ No newline at end of file
diff --git a/plugins/ckeditor/wordcount/lang/hr.js b/plugins/ckeditor/wordcount/lang/hr.js
new file mode 100644
index 0000000..4cfc018
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/hr.js
@@ -0,0 +1,14 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'hr', {
+ WordCount: 'Riječi:',
+ CharCount: 'Znakova:',
+ CharCountWithHTML: 'Znakova (uključujući HTML):',
+ Paragraphs: 'Paragraphs:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'Content can not be pasted because it is above the allowed limit',
+ Selected: 'Selected: ',
+ title: 'Statistika'
+});
diff --git a/plugins/ckeditor/wordcount/lang/hu.js b/plugins/ckeditor/wordcount/lang/hu.js
new file mode 100644
index 0000000..7866a8e
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/hu.js
@@ -0,0 +1,14 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'hu', {
+ WordCount: 'Szavak:',
+ CharCount: 'Karakaterek:',
+ CharCountWithHTML: 'Karakterek (HTML tagekkel):',
+ Paragraphs: 'Bekezdések:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'A szöveget nem lehet beilleszteni, mert a megadott limit felett van',
+ Selected: 'Kiválasztva: ',
+ title: 'Statisztika'
+});
diff --git a/plugins/ckeditor/wordcount/lang/it.js b/plugins/ckeditor/wordcount/lang/it.js
new file mode 100644
index 0000000..0771726
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/it.js
@@ -0,0 +1,15 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+@author translation: Davide Montorio
+*/
+CKEDITOR.plugins.setLang('wordcount', 'it', {
+ WordCount: 'Parole:',
+ CharCount: 'Caratteri:',
+ CharCountWithHTML: 'Caratteri (HTML incluso):',
+ Paragraphs: 'Paragrafi:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'Il contenuto non può essere incollato poiché supera il limite massimo di caratteri disponibili',
+ Selected: 'Selezionato: ',
+ title: 'Statistiche'
+});
diff --git a/plugins/ckeditor/wordcount/lang/ja.js b/plugins/ckeditor/wordcount/lang/ja.js
new file mode 100644
index 0000000..1d02684
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/ja.js
@@ -0,0 +1,14 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'ja', {
+ WordCount: '単語数:',
+ CharCount: '文字数:',
+ CharCountWithHTML: '文字数 (HTMLタグを含む):',
+ Paragraphs: '段落数:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: '文字数/単語数の上限を超えるため、貼り付けできません。',
+ Selected: '選択中の字数:',
+ title: 'ワードカウント'
+});
diff --git a/plugins/ckeditor/wordcount/lang/ko.js b/plugins/ckeditor/wordcount/lang/ko.js
new file mode 100644
index 0000000..4e32f47
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/ko.js
@@ -0,0 +1,16 @@
+/*
+Korean translation by Maxime Houdais
+*/
+CKEDITOR.plugins.setLang('wordcount', 'ko', {
+ WordCount: '단어:',
+ WordCountRemaining: '남은 단어',
+ CharCount: '글자:',
+ CharCountRemaining: '남은 글자',
+ CharCountWithHTML: '글자 와 HTML:',
+ CharCountWithHTMLRemaining: '남은 글자 와 HTML',
+ Paragraphs: '단락:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: '허용 된 한도를 초과하여 콘텐츠를 붙여 넣을 수 없습니다.',
+ Selected: '선택:',
+ title: '통계'
+});
diff --git a/plugins/ckeditor/wordcount/lang/nl.js b/plugins/ckeditor/wordcount/lang/nl.js
new file mode 100644
index 0000000..e2a8170
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/nl.js
@@ -0,0 +1,14 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'nl', {
+ WordCount: 'Woorden:',
+ CharCount: 'Tekens:',
+ CharCountWithHTML: 'Tekens (inclusief HTML):',
+ Paragraphs: 'Paragrafen:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'De tekst kan niet worden geplakt omdat de limiet is overschreden',
+ Selected: 'Geselecteerd: ',
+ title: 'Statistieken'
+});
diff --git a/plugins/ckeditor/wordcount/lang/no.js b/plugins/ckeditor/wordcount/lang/no.js
new file mode 100644
index 0000000..e9fba5c
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/no.js
@@ -0,0 +1,11 @@
+// Norwegian translation by Vegard S.
+CKEDITOR.plugins.setLang('wordcount', 'no', {
+ WordCount: 'Ord:',
+ CharCount: 'Tegn:',
+ CharCountWithHTML: 'Tegn (including HTML):',
+ Paragraphs: 'Paragraphs:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'Content can not be pasted because it is above the allowed limit',
+ Selected: 'Selected: ',
+ title: 'Statistikk'
+});
diff --git a/plugins/ckeditor/wordcount/lang/pl.js b/plugins/ckeditor/wordcount/lang/pl.js
new file mode 100644
index 0000000..cc74244
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/pl.js
@@ -0,0 +1,14 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'pl', {
+ WordCount: 'Słów:',
+ CharCount: 'Znaków:',
+ CharCountWithHTML: 'Znaków (wraz z kodem HTML):',
+ Paragraphs: 'Paragrafy:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'Zawartość nie może zostać wklejona, ponieważ przekracza dozwolony limit',
+ Selected: 'Zaznaczono: ',
+ title: 'Statystyka'
+});
diff --git a/plugins/ckeditor/wordcount/lang/pt-br.js b/plugins/ckeditor/wordcount/lang/pt-br.js
new file mode 100644
index 0000000..da5b7a5
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/pt-br.js
@@ -0,0 +1,14 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'pt-br', {
+ WordCount: 'Contagem de palavras:',
+ CharCount: 'Contagem de carateres:',
+ CharCountWithHTML: 'Carateres (incluindo HTML):',
+ Paragraphs: 'Parágrafos:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'Conteúdo não pode ser colado porque ultrapassa o limite permitido',
+ Selected: 'Selecionado: ',
+ title: 'Estatísticas'
+});
diff --git a/plugins/ckeditor/wordcount/lang/pt.js b/plugins/ckeditor/wordcount/lang/pt.js
new file mode 100644
index 0000000..5fd624b
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/pt.js
@@ -0,0 +1,10 @@
+CKEDITOR.plugins.setLang('wordcount', 'pt', {
+ WordCount: 'Palavras:',
+ CharCount: 'Caracteres:',
+ CharCountWithHTML: 'Carateres (incluindo HTML):',
+ Paragraphs: 'Parágrafos:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'O conteúdo não pode ser colado porque ultrapassa o limite permitido',
+ Selected: 'Selecionado: ',
+ title: 'Estatísticas'
+});
diff --git a/plugins/ckeditor/wordcount/lang/ro.js b/plugins/ckeditor/wordcount/lang/ro.js
new file mode 100644
index 0000000..6ce7c05
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/ro.js
@@ -0,0 +1,15 @@
+// Romanian Translation by Bogdanov Mihail
+
+CKEDITOR.plugins.setLang('wordcount', 'ro', {
+ WordCount: 'Numar cuvinte',
+ WordCountRemaining: 'Cuvinte ramase',
+ CharCount: 'Numar caracter:',
+ CharCountRemaining: 'Caractere ramase:',
+ CharCountWithHTML: 'Numar caractere (cu HTML):',
+ CharCountWithHTMLRemaining: 'Caractere (cu HTML) ramase',
+ Paragraphs: 'Paragrafe:',
+ ParagraphsRemaining: 'Paragrafe ramase',
+ pasteWarning: 'Continutul nu poate fi adaugat deoarece este mai mare decat limita setata',
+ Selected: 'Selectat:',
+ title: 'Statistici'
+});
\ No newline at end of file
diff --git a/plugins/ckeditor/wordcount/lang/ru.js b/plugins/ckeditor/wordcount/lang/ru.js
new file mode 100644
index 0000000..fd51b93
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/ru.js
@@ -0,0 +1,14 @@
+/*
+Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'ru', {
+ WordCount: 'Слов:',
+ CharCount: 'Символов:',
+ CharCountWithHTML: ' (включая HTML-разметку):',
+ Paragraphs: 'Параграфов:',
+ ParagraphsRemaining: 'Параграфов осталось',
+ pasteWarning: 'Контент не может быть вставлен, т.к. привышает допустимый лимит',
+ Selected: 'Выделено: ',
+ title: 'Статистика'
+});
diff --git a/plugins/ckeditor/wordcount/lang/sk.js b/plugins/ckeditor/wordcount/lang/sk.js
new file mode 100644
index 0000000..70eeb3a
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/sk.js
@@ -0,0 +1,15 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'sk', {
+ WordCount: 'Slov:',
+ CharCount: 'Znakov:',
+ CharCountWithHTML: 'Znakov (vrátane HTML):',
+ Paragraphs: 'Odstavcov:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'Obsah sa nedá prilepiť.',
+ Selected: 'Výber: ',
+ title: 'Štatistika'
+});
+
diff --git a/plugins/ckeditor/wordcount/lang/sv.js b/plugins/ckeditor/wordcount/lang/sv.js
new file mode 100644
index 0000000..3350917
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/sv.js
@@ -0,0 +1,15 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'sv', {
+ WordCount: 'Ord:',
+ CharCount: 'Tecken:',
+ CharCountRemaining: 'tecken återstår',
+ CharCountWithHTML: 'Tecken (inklusive HTML):',
+ Paragraphs: 'Paragraf:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'Innehåll kan inte klistras in eftersom det överskrider den tillåtna gränsen',
+ Selected: 'Valt: ',
+ title: 'Statistik'
+});
diff --git a/plugins/ckeditor/wordcount/lang/tr.js b/plugins/ckeditor/wordcount/lang/tr.js
new file mode 100644
index 0000000..e916533
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/tr.js
@@ -0,0 +1,14 @@
+/*
+Mesut ÇAKIR
+mesut.cakir@hotmail.com.tr
+*/
+CKEDITOR.plugins.setLang('wordcount', 'tr', {
+ WordCount: 'Kelime:',
+ CharCount: 'Karakter:',
+ CharCountWithHTML: 'Karakter (HTML dahil):',
+ Paragraphs: 'Paragraf:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: 'Content can not be pasted because it is above the allowed limit',
+ Selected: 'Selected: ',
+ title: 'İstatistik'
+});
diff --git a/plugins/ckeditor/wordcount/lang/uk.js b/plugins/ckeditor/wordcount/lang/uk.js
new file mode 100644
index 0000000..a7d976c
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/uk.js
@@ -0,0 +1,17 @@
+/*
+ Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
+ For licensing, see LICENSE.html or http://ckeditor.com/license
+ */
+CKEDITOR.plugins.setLang('wordcount', 'uk', {
+ WordCount: 'Слів:',
+ WordCountRemaining: 'Слів залишилося',
+ CharCount: 'Символів:',
+ CharCountRemaining: 'Символів залишилося',
+ CharCountWithHTML: 'Символів (включаючи HTML-розмітку):',
+ CharCountWithHTMLRemaining: 'Символів (включаючи HTML-розмітку) залишилося',
+ Paragraphs: 'Параграфів:',
+ ParagraphsRemaining: 'Параграфів залишилося',
+ pasteWarning: 'Контент не може бути вставлено, оскільки перевищує допустимий ліміт',
+ Selected: 'Виділено: ',
+ title: 'Статистика'
+});
diff --git a/plugins/ckeditor/wordcount/lang/zh-cn.js b/plugins/ckeditor/wordcount/lang/zh-cn.js
new file mode 100644
index 0000000..a8b0dd5
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/zh-cn.js
@@ -0,0 +1,14 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'zh-cn', {
+ WordCount: '词数:',
+ CharCount: '字符:',
+ CharCountWithHTML: '字符 (含HTML)',
+ Paragraphs: '段落:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: '由于上限允许,内容不能粘贴',
+ Selected: '已选择: ',
+ title: '统计'
+});
diff --git a/plugins/ckeditor/wordcount/lang/zh.js b/plugins/ckeditor/wordcount/lang/zh.js
new file mode 100644
index 0000000..ec35ca2
--- /dev/null
+++ b/plugins/ckeditor/wordcount/lang/zh.js
@@ -0,0 +1,14 @@
+/*
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang('wordcount', 'zh', {
+ WordCount: '詞數:',
+ CharCount: '字數:',
+ CharCountWithHTML: '字數 (含HTML)',
+ Paragraphs: '段落:',
+ ParagraphsRemaining: 'Paragraphs remaining',
+ pasteWarning: '由於字數達到上限,內容不能粘貼',
+ Selected: '已選擇: ',
+ title: '統計'
+});
\ No newline at end of file
diff --git a/plugins/ckeditor/wordcount/plugin.js b/plugins/ckeditor/wordcount/plugin.js
new file mode 100644
index 0000000..634b9fd
--- /dev/null
+++ b/plugins/ckeditor/wordcount/plugin.js
@@ -0,0 +1,596 @@
+/**
+ * @license Copyright (c) CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.html or http://ckeditor.com/license
+ */
+
+CKEDITOR.plugins.add("wordcount",
+ {
+ lang: "ar,bg,ca,cs,da,de,el,en,es,eu,fa,fi,fr,he,hr,hu,it,ko,ja,nl,no,pl,pt,pt-br,ru,sk,sv,tr,uk,zh-cn,zh,ro", // %REMOVE_LINE_CORE%
+ version: "1.17.5",
+ requires: 'htmlwriter,notification,undo',
+ bbcodePluginLoaded: false,
+ onLoad: function() {
+ CKEDITOR.document.appendStyleSheet(this.path + "css/wordcount.css");
+ },
+ init: function(editor) {
+ var defaultFormat = "",
+ lastWordCount = -1,
+ lastCharCount = -1,
+ lastParagraphs = -1,
+ limitReachedNotified = false,
+ limitRestoredNotified = false,
+ timeoutId = 0,
+ notification = null;
+
+
+ var dispatchEvent = function(type, currentLength, maxLength) {
+ if (typeof document.dispatchEvent == 'undefined') {
+ return;
+ }
+
+ type = 'ckeditor.wordcount.' + type;
+
+ var cEvent;
+ var eventInitDict = {
+ bubbles: false,
+ cancelable: true,
+ detail: {
+ currentLength: currentLength,
+ maxLength: maxLength
+ }
+ };
+
+ try {
+ cEvent = new CustomEvent(type, eventInitDict);
+ } catch (o_O) {
+ cEvent = document.createEvent('CustomEvent');
+ cEvent.initCustomEvent(
+ type,
+ eventInitDict.bubbles,
+ eventInitDict.cancelable,
+ eventInitDict.detail
+ );
+ }
+
+ document.dispatchEvent(cEvent);
+ };
+
+ // Default Config
+ var defaultConfig = {
+ showRemaining: false,
+ showParagraphs: true,
+ showWordCount: true,
+ showCharCount: false,
+ countBytesAsChars: false,
+ countSpacesAsChars: false,
+ countHTML: false,
+ countLineBreaks: false,
+ hardLimit: true,
+ warnOnLimitOnly: false,
+
+ //MAXLENGTH Properties
+ maxWordCount: -1,
+ maxCharCount: -1,
+ maxParagraphs: -1,
+
+ // Filter
+ filter: null,
+
+ // How long to show the 'paste' warning
+ pasteWarningDuration: 0,
+
+ //DisAllowed functions
+ wordCountGreaterThanMaxLengthEvent: function(currentLength, maxLength) {
+ dispatchEvent('wordCountGreaterThanMaxLengthEvent', currentLength, maxLength);
+ },
+ charCountGreaterThanMaxLengthEvent: function(currentLength, maxLength) {
+ dispatchEvent('charCountGreaterThanMaxLengthEvent', currentLength, maxLength);
+ },
+
+ //Allowed Functions
+ wordCountLessThanMaxLengthEvent: function(currentLength, maxLength) {
+ dispatchEvent('wordCountLessThanMaxLengthEvent', currentLength, maxLength);
+ },
+ charCountLessThanMaxLengthEvent: function(currentLength, maxLength) {
+ dispatchEvent('charCountLessThanMaxLengthEvent', currentLength, maxLength);
+ }
+ };
+
+ // Get Config & Lang
+ var config = CKEDITOR.tools.extend(defaultConfig, editor.config.wordcount || {}, true);
+
+ if (config.showParagraphs) {
+ if (config.maxParagraphs > -1) {
+ if (config.showRemaining) {
+ defaultFormat += "%paragraphsCount% " + editor.lang.wordcount.ParagraphsRemaining;
+ } else {
+ defaultFormat += editor.lang.wordcount.Paragraphs + " %paragraphsCount%";
+
+ defaultFormat += "/" + config.maxParagraphs;
+ }
+ } else {
+ defaultFormat += editor.lang.wordcount.Paragraphs + " %paragraphsCount%";
+ }
+ }
+
+ if (config.showParagraphs && (config.showWordCount || config.showCharCount)) {
+ defaultFormat += ", ";
+ }
+
+ if (config.showWordCount) {
+ if (config.maxWordCount > -1) {
+ if (config.showRemaining) {
+ defaultFormat += "%wordCount% " + editor.lang.wordcount.WordCountRemaining;
+ } else {
+ defaultFormat += editor.lang.wordcount.WordCount + " %wordCount%";
+
+ defaultFormat += "/" + config.maxWordCount;
+ }
+ } else {
+ defaultFormat += editor.lang.wordcount.WordCount + " %wordCount%";
+ }
+ }
+
+ if (config.showCharCount && config.showWordCount) {
+ defaultFormat += ", ";
+ }
+
+ if (config.showCharCount) {
+ if (config.maxCharCount > -1) {
+ if (config.showRemaining) {
+ defaultFormat += "%charCount% " +
+ editor.lang.wordcount[config.countHTML
+ ? "CharCountWithHTMLRemaining"
+ : "CharCountRemaining"];
+ } else {
+ defaultFormat += editor.lang.wordcount[config.countHTML
+ ? "CharCountWithHTML"
+ : "CharCount"] +
+ " %charCount%";
+
+ defaultFormat += "/" + config.maxCharCount;
+ }
+ } else {
+ defaultFormat += editor.lang.wordcount[config.countHTML ? "CharCountWithHTML" : "CharCount"] +
+ " %charCount%";
+ }
+ }
+
+ var format = defaultFormat;
+
+ bbcodePluginLoaded = typeof editor.plugins.bbcode != 'undefined';
+
+ function counterId(editorInstance) {
+ return "cke_wordcount_" + editorInstance.name;
+ }
+
+ function counterElement(editorInstance) {
+ return document.getElementById(counterId(editorInstance));
+ }
+
+ function strip(html) {
+ if (bbcodePluginLoaded) {
+ // stripping out BBCode tags [...][/...]
+ return html.replace(/\[.*?\]/gi, '');
+ }
+
+ var tmp = document.createElement("div");
+
+ // Add filter before strip
+ html = filter(html);
+
+ tmp.innerHTML = html;
+
+ if (tmp.textContent == "" && typeof tmp.innerText == "undefined") {
+ return "";
+ }
+
+ return tmp.textContent || tmp.innerText;
+ }
+
+ /**
+ * Implement filter to add or remove before counting
+ * @param html
+ * @returns string
+ */
+ function filter(html) {
+ if (config.filter instanceof CKEDITOR.htmlParser.filter) {
+ var fragment = CKEDITOR.htmlParser.fragment.fromHtml(html),
+ writer = new CKEDITOR.htmlParser.basicWriter();
+ config.filter.applyTo(fragment);
+ fragment.writeHtml(writer);
+ return writer.getHtml();
+ }
+ return html;
+ }
+
+ function countCharacters(text) {
+ if (config.countHTML) {
+ return (filter(text).length);
+ }
+
+ var normalizedText;
+
+ // strip body tags
+ if (editor.config.fullPage) {
+ var i = text.search(new RegExp("", "i"));
+ if (i != -1) {
+ var j = text.search(new RegExp("", "i"));
+ text = text.substring(i + 6, j);
+ }
+
+ }
+
+ normalizedText = text;
+
+ if (!config.countSpacesAsChars) {
+ normalizedText = text.replace(/\s/g, "").replace(/ /g, "");
+ }
+
+ if (config.countLineBreaks) {
+ normalizedText = normalizedText.replace(/(\r\n|\n|\r)/gm, " ");
+ } else {
+ normalizedText = normalizedText.replace(/(\r\n|\n|\r)/gm, "").replace(/ /gi, " ");
+ }
+
+ normalizedText = strip(normalizedText).replace(/^([\t\r\n]*)$/, "");
+
+ return config.countBytesAsChars ? (countBytes(normalizedText)) : (normalizedText.length);
+ }
+
+ function countBytes(text) {
+ var count = 0, stringLength = text.length, i;
+ text = String(text || "");
+ for (i = 0; i < stringLength; i++) {
+ var partCount = encodeURI(text[i]).split("%").length;
+ count += partCount == 1 ? 1 : partCount - 1;
+ }
+ return count;
+ }
+
+ function countParagraphs(text) {
+ return (text.replace(/ /g, " ").replace(/(<([^>]+)>)/ig, "").replace(/^\s*$[\n\r]{1,}/gm, "++")
+ .split("++").length);
+ }
+
+ function countWords(text) {
+ var normalizedText = text.replace(/(\r\n|\n|\r)/gm, " ").replace(/^\s+|\s+$/g, "")
+ .replace(" ", " ");
+
+ normalizedText = strip(normalizedText);
+
+ var words = normalizedText.split(/\s+/);
+
+ for (var wordIndex = words.length - 1; wordIndex >= 0; wordIndex--) {
+ if (words[wordIndex].match(/^([\s\t\r\n]*)$/)) {
+ words.splice(wordIndex, 1);
+ }
+ }
+
+ return (words.length);
+ }
+
+ function limitReached(editorInstance, notify) {
+ limitReachedNotified = true;
+ limitRestoredNotified = false;
+
+ if (!config.warnOnLimitOnly) {
+ if (config.hardLimit) {
+ editorInstance.execCommand('undo');
+ }
+ }
+
+ if (!notify) {
+ counterElement(editorInstance).className = "cke_path_item cke_wordcountLimitReached";
+ editorInstance.fire("limitReached", { firedBy: "wordCount.limitReached" }, editor);
+ }
+ }
+
+ function limitRestored(editorInstance) {
+ limitRestoredNotified = true;
+ limitReachedNotified = false;
+
+ if (!config.warnOnLimitOnly) {
+ editorInstance.fire('saveSnapshot');
+ }
+
+ counterElement(editorInstance).className = "cke_path_item";
+ }
+
+ function updateCounter(editorInstance) {
+ if (!counterElement(editorInstance)) {
+ return;
+ }
+
+ var paragraphs = 0,
+ wordCount = 0,
+ charCount = 0,
+ text;
+
+ // BeforeGetData and getData events are fired when calling
+ // getData(). We can prevent this by passing true as an
+ // argument to getData(). This allows us to fire the events
+ // manually with additional event data: firedBy. This additional
+ // data helps differentiate calls to getData() made by
+ // wordCount plugin from calls made by other plugins/code.
+ editorInstance.fire("beforeGetData", { firedBy: "wordCount.updateCounter" }, editor);
+ text = editorInstance.getData(true);
+ editorInstance.fire("getData", { dataValue: text, firedBy: "wordCount.updateCounter" }, editor);
+
+ if (text) {
+ if (config.showCharCount) {
+ charCount = countCharacters(text);
+ }
+
+ if (config.showParagraphs) {
+ paragraphs = countParagraphs(text);
+ }
+
+ if (config.showWordCount) {
+ wordCount = countWords(text);
+ }
+ }
+
+ var html = format;
+ if (config.showRemaining) {
+ if (config.maxCharCount >= 0) {
+ html = html.replace("%charCount%", config.maxCharCount - charCount);
+ } else {
+ html = html.replace("%charCount%", charCount);
+ }
+
+ if (config.maxWordCount >= 0) {
+ html = html.replace("%wordCount%", config.maxWordCount - wordCount);
+ } else {
+ html = html.replace("%wordCount%", wordCount);
+ }
+
+ if (config.maxParagraphs >= 0) {
+ html = html.replace("%paragraphsCount%", config.maxParagraphs - paragraphs);
+ } else {
+ html = html.replace("%paragraphsCount%", paragraphs);
+ }
+ } else {
+ html = html.replace("%wordCount%", wordCount).replace("%charCount%", charCount).replace("%paragraphsCount%", paragraphs);
+ }
+
+ (editorInstance.config.wordcount || (editorInstance.config.wordcount = {})).wordCount = wordCount;
+ (editorInstance.config.wordcount || (editorInstance.config.wordcount = {})).charCount = charCount;
+
+ if (CKEDITOR.env.gecko) {
+ counterElement(editorInstance).innerHTML = html;
+ } else {
+ counterElement(editorInstance).innerText = html;
+ }
+
+ if (charCount == lastCharCount && wordCount == lastWordCount && paragraphs == lastParagraphs) {
+ if (charCount == config.maxCharCount || wordCount == config.maxWordCount || paragraphs > config.maxParagraphs) {
+ editorInstance.fire('saveSnapshot');
+ }
+ return true;
+ }
+
+ //If the limit is already over, allow the deletion of characters/words. Otherwise,
+ //the user would have to delete at one go the number of offending characters
+ var deltaWord = wordCount - lastWordCount;
+ var deltaChar = charCount - lastCharCount;
+ var deltaParagraphs = paragraphs - lastParagraphs;
+
+ lastWordCount = wordCount;
+ lastCharCount = charCount;
+ lastParagraphs = paragraphs;
+
+ if (lastWordCount == -1) {
+ lastWordCount = wordCount;
+ }
+ if (lastCharCount == -1) {
+ lastCharCount = charCount;
+ }
+ if (lastParagraphs == -1) {
+ lastParagraphs = paragraphs;
+ }
+
+ // Check for word limit and/or char limit
+ if ((config.maxWordCount > -1 && wordCount > config.maxWordCount && deltaWord > 0) ||
+ (config.maxCharCount > -1 && charCount > config.maxCharCount && deltaChar > 0) ||
+ (config.maxParagraphs > -1 && paragraphs > config.maxParagraphs && deltaParagraphs > 0)) {
+
+ limitReached(editorInstance, limitReachedNotified);
+ } else if ((config.maxWordCount == -1 || wordCount <= config.maxWordCount) &&
+ (config.maxCharCount == -1 || charCount <= config.maxCharCount) &&
+ (config.maxParagraphs == -1 || paragraphs <= config.maxParagraphs)) {
+
+ limitRestored(editorInstance);
+ } else {
+ editorInstance.fire('saveSnapshot');
+ }
+
+ // update instance
+ editorInstance.wordCount =
+ {
+ paragraphs: paragraphs,
+ wordCount: wordCount,
+ charCount: charCount
+ };
+
+
+ // Fire Custom Events
+ if (config.charCountGreaterThanMaxLengthEvent && config.charCountLessThanMaxLengthEvent) {
+ if (charCount > config.maxCharCount && config.maxCharCount > -1) {
+ config.charCountGreaterThanMaxLengthEvent(charCount, config.maxCharCount);
+ } else {
+ config.charCountLessThanMaxLengthEvent(charCount, config.maxCharCount);
+ }
+ }
+
+ if (config.wordCountGreaterThanMaxLengthEvent && config.wordCountLessThanMaxLengthEvent) {
+ if (wordCount > config.maxWordCount && config.maxWordCount > -1) {
+ config.wordCountGreaterThanMaxLengthEvent(wordCount, config.maxWordCount);
+
+ } else {
+ config.wordCountLessThanMaxLengthEvent(wordCount, config.maxWordCount);
+ }
+ }
+
+ return true;
+ }
+
+ function isCloseToLimits() {
+ if (config.maxWordCount > -1 && config.maxWordCount - lastWordCount < 5) {
+ return true;
+ }
+
+ if (config.maxCharCount > -1 && config.maxCharCount - lastCharCount < 20) {
+ return true;
+ }
+
+ if (config.maxParagraphs > -1 && config.maxParagraphs - lastParagraphs < 1) {
+ return true;
+ }
+
+ return false;
+ }
+
+ editor.on("key",
+ function(event) {
+ if (editor.mode === "source") {
+ clearTimeout(timeoutId);
+ timeoutId = setTimeout(
+ updateCounter.bind(this, event.editor),
+ 250
+ );
+ }
+ },
+ editor,
+ null,
+ 100);
+
+ editor.on("change",
+ function(event) {
+ var ms = isCloseToLimits() ? 5 : 250;
+ clearTimeout(timeoutId);
+ timeoutId = setTimeout(
+ updateCounter.bind(this, event.editor),
+ ms
+ );
+ },
+ editor,
+ null,
+ 100);
+
+ editor.on("uiSpace",
+ function(event) {
+ if (editor.elementMode === CKEDITOR.ELEMENT_MODE_INLINE) {
+ if (event.data.space == "top") {
+ event.data.html += " ";
+ }
+ } else {
+ if (event.data.space == "bottom") {
+ event.data.html += " ";
+ }
+ }
+
+ },
+ editor,
+ null,
+ 100);
+
+ editor.on("dataReady",
+ function(event) {
+ updateCounter(event.editor);
+ },
+ editor,
+ null,
+ 100);
+
+ editor.on("paste",
+ function(event) {
+ if (!config.warnOnLimitOnly && (config.maxWordCount > 0 || config.maxCharCount > 0 || config.maxParagraphs > 0)) {
+
+ // Check if pasted content is above the limits
+ var wordCount = -1,
+ charCount = -1,
+ paragraphs = -1;
+
+ // BeforeGetData and getData events are fired when calling
+ // getData(). We can prevent this by passing true as an
+ // argument to getData(). This allows us to fire the events
+ // manually with additional event data: firedBy. This additional
+ // data helps differentiate calls to getData() made by
+ // wordCount plugin from calls made by other plugins/code.
+ event.editor.fire("beforeGetData", { firedBy: "wordCount.onPaste" }, event.editor);
+ var text = event.editor.getData(true);
+ event.editor.fire("getData", { dataValue: text, firedBy: "wordCount.onPaste" }, event.editor);
+
+ text += event.data.dataValue;
+
+ if (config.showCharCount) {
+ charCount = countCharacters(text);
+ }
+
+ if (config.showWordCount) {
+ wordCount = countWords(text);
+ }
+
+ if (config.showParagraphs) {
+ paragraphs = countParagraphs(text);
+ }
+
+
+ // Instantiate the notification when needed and only have one instance
+ if (notification === null) {
+ notification = new CKEDITOR.plugins.notification(event.editor,
+ {
+ message: event.editor.lang.wordcount.pasteWarning,
+ type: 'warning',
+ duration: config.pasteWarningDuration
+ });
+ }
+
+ if (config.maxCharCount > 0 && charCount > config.maxCharCount && config.hardLimit) {
+ if (!notification.isVisible()) {
+ notification.show();
+ }
+ event.cancel();
+ }
+
+ if (config.maxWordCount > 0 && wordCount > config.maxWordCount && config.hardLimit) {
+ if (!notification.isVisible()) {
+ notification.show();
+ }
+ event.cancel();
+ }
+
+ if (config.maxParagraphs > 0 && paragraphs > config.maxParagraphs && config.hardLimit) {
+ if (!notification.isVisible()) {
+ notification.show();
+ }
+ event.cancel();
+ }
+ }
+ },
+ editor,
+ null,
+ 100);
+
+ editor.on("afterPaste",
+ function(event) {
+ updateCounter(event.editor);
+ },
+ editor,
+ null,
+ 100);
+ }
+ });
diff --git a/plugins/ckeditor/wordcount/samples/maxParagraphs.html b/plugins/ckeditor/wordcount/samples/maxParagraphs.html
new file mode 100644
index 0000000..372556c
--- /dev/null
+++ b/plugins/ckeditor/wordcount/samples/maxParagraphs.html
@@ -0,0 +1,26 @@
+
+
+
+
+ CKEditor
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/ckeditor/wordcount/samples/wordcount.html b/plugins/ckeditor/wordcount/samples/wordcount.html
new file mode 100644
index 0000000..5649b7f
--- /dev/null
+++ b/plugins/ckeditor/wordcount/samples/wordcount.html
@@ -0,0 +1,61 @@
+
+
+
+
+
+ WordCount — CKEditor Sample
+
+
+
+
+
+
+
+
+
+
+ CKEditor Samples » WordCount Plugin
+
+
+
+
+ WordCount Plugin for CKEditor that counts the words an shows the word count in the footer of the editor..
+
+
+ In order to use the new plugin, include it in the config.extraPlugins configuration setting.
+
+
+CKEDITOR.replace( 'textarea_id', {
+ extraPlugins: 'wordcount'
+} );
+
+
+
+
+
+
+
+
+
diff --git a/plugins/ckeditor/wordcount/samples/wordcountWithMaxCount.html b/plugins/ckeditor/wordcount/samples/wordcountWithMaxCount.html
new file mode 100644
index 0000000..dd46ed2
--- /dev/null
+++ b/plugins/ckeditor/wordcount/samples/wordcountWithMaxCount.html
@@ -0,0 +1,110 @@
+
+
+
+
+
+ WordCount — CKEditor Sample
+
+
+
+
+
+
+
+
+
+
+
+ CKEditor Samples » WordCount Plugin
+
+
+
+
+ WordCount Plugin for CKEditor that counts the words an shows the word count in the footer of the editor..
+
+
+ In order to use the new plugin, include it in the config.extraPlugins configuration setting.
+
+
+CKEDITOR.replace( 'textarea_id', {
+ extraPlugins: 'wordcount',
+ maxWordCount: 4,
+ maxCharCount: 10,
+ // optional events
+ paragraphsCountGreaterThanMaxLengthEvent: function (currentLength, maxLength) {
+ $("#informationparagraphs").css("background-color", "crimson").css("color", "white").text(currentLength + "/" + maxLength + " - paragraphs").show();
+ },
+ wordCountGreaterThanMaxLengthEvent: function (currentLength, maxLength) {
+ $("#informationword").css("background-color", "crimson").css("color", "white").text(currentLength + "/" + maxLength + " - word").show();
+ },
+ charCountGreaterThanMaxLengthEvent: function (currentLength, maxLength) {
+ $("#informationchar").css("background-color", "crimson").css("color", "white").text(currentLength + "/" + maxLength + " - char").show();
+ },
+ charCountLessThanMaxLengthEvent: function (currentLength, maxLength) {
+ $("#informationchar").css("background-color", "white").css("color", "black").hide();
+ },
+ paragraphsCountLessThanMaxLengthEvent: function (currentLength, maxLength) {
+ $("#informationparagraphs").css("background-color", "white").css("color", "black").hide();
+ },
+ wordCountLessThanMaxLengthEvent: function (currentLength, maxLength) {
+ $("#informationword").css("background-color", "white").css("color", "black").hide();
+ }
+} );
+
+
+
+
+
+
+
+
+
+
+
+