# API Formatera

{% hint style="danger" %}
Uwaga!

W formaterach w Eximee Designer nie należy dodawać komentarzy - mogą one powodować błędy na wniosku!
{% endhint %}

## Implementacja nowego formatera <a href="#tworzenieformatera-implementacjanowegoformatera" id="tworzenieformatera-implementacjanowegoformatera"></a>

Po utworzeniu nowego formatera w przestrzeni roboczej otworzy się edytor tekstowy z szablonem implementacyjnym formatera.

Formater reprezentowany jest jako funkcja JavaScript o podanej w szablonie inicjalnie sygnaturze:

```
function formatText(input) {
         return { 
                formattedText: input.textToFormat,
                cursorPosition: input.cursorPosition 
          };
}
```

Opis sygnatury funkcji formatera:

<table><thead><tr><th width="214.9166259765625">Nazwa parametru</th><th width="150.3499755859375">Rodzaj</th><th width="103.300048828125">Typ</th><th>Opis</th></tr></thead><tbody><tr><td><strong>input.textToFormat</strong></td><td><strong>wejściowy</strong></td><td><strong>String</strong><br><strong>(JAVA)</strong></td><td><strong>Tekst do sformatowania.</strong><br>Należy przekonwertować typ JAVA zmiennej do typu <strong>JavaScript</strong> (new String(input.textToFormat); ) w celu wywołania metod dla typu <strong>String</strong> (np. replace())</td></tr><tr><td><strong>input.locale</strong></td><td><strong>wejściowy</strong></td><td><strong>String</strong><br><strong>(JAVA)</strong></td><td><strong>Łańcuch określający język, w jakim wyświetlany jest wniosek (np. "pl", "en").</strong><br>Należy przekonwertować typ JAVA zmiennej do typu <strong>JavaScript</strong> (new String(input.locale); ) w celu wywołania metod dla typu <strong>String</strong> (np. replace())</td></tr><tr><td><strong>input.cursorPosition</strong></td><td><strong>wejściowy</strong></td><td><strong>int</strong></td><td><strong>Pozycja kursora w polu tekstowym przed sformatowaniem</strong></td></tr><tr><td><strong>output.formattedText</strong></td><td><strong>wyjściowy</strong></td><td><strong>String</strong></td><td><strong>Tekst po sformatowaniu</strong></td></tr><tr><td><strong>output.cursorPosition</strong></td><td><strong>wyjściowy</strong></td><td><strong>String</strong></td><td><strong>Pozycja kursora w polu tekstowym po sformatowaniu</strong> - liczba całkowita z zakresu &#x3C;0,output.formattedText.length> - w przypadku podania liczby znajdującej się poza zakresem aplikacja webforms nie zmieni pozycji kursora (zostanie zachowane domyślne działanie przeglądarki)</td></tr></tbody></table>

Implementacja formatera powinna odbywać się przez zmianę wyłącznie wnętrza funkcji.

W celu prawidłowego działania formater musi być poprawną funkcją języka **JavaScript**. W przeciwnym wypadku podczas próby zapisu formatera w bieżącej przestrzeni użytkownika, wygenerowany zostanie odpowiedni systemowy komunikat błędu.

<details>

<summary>Przykładowy kod formatera (dodaje do liczby separator tysięczny oraz ustawia kursor zawsze na końcu):</summary>

```
function formatText(input) {
    if (typeof input.textToFormat == 'undefined') {
        return  {
            formattedText: "",
            cursorPosition: -1
        };
    }
     
    let number_format = function(number, decimals, dec_point, thousands_sep) {
        number = (number + '').replace(/[^0-9+\-Ee.]/g, '');
        let n = !isFinite(+number) ? 0 : +number, prec = !isFinite(+decimals) ? 0
                    : Math.abs(decimals), sep = (typeof thousands_sep === 'undefined') ? ','
                    : thousands_sep, dec = (typeof dec_point === 'undefined') ? '.'
                    : dec_point, s = '', toFixedFix = function(n, prec) {
            let k = Math.pow(10, prec);
            return '' + Math.round(n * k) / k;
        };
        s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
        if (s[0].length > 3) {
            s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
        }
        return s.join(dec);
    }
     
    let textToFormat = new String(input.textToFormat + "");
    textToFormat = textToFormat.replace(/\s+/g, '');
    textToFormat = textToFormat.replace(/,/g, '.')
    textToFormat = textToFormat.replace(/[^\d^\.]/g,'');
     
    let temp = parseFloat(textToFormat);
    if(isNaN(temp)){
        return {
            formattedText: "",
            cursorPosition: -1
        };
    }
    let resultText = number_format(temp, 2, ',', ' ');
     
    return {
        formattedText: resultText,
        cursorPosition: resultText.length
    };
}
```

</details>

Wersja z karetką ustawiającą się na naturalnej pozycji (uwzględniając separatory tysięcy). Poniższy formater nie zadziała dla Pola tekstowego (TextField) typu EMAIL z powodu ograniczeń JavaScriptowych (input type="email" nie ma zaimplementowanego pobierania pozycji karetki).

<details>

<summary>Wersja z karetką ustawiającą się na naturalnej pozycji</summary>

```
function formatText(input) {
 
    let spacesInInput;
    let localCursorPosition;
     
    if(input.cursorPosition) {
        localCursorPosition = input.cursorPosition;
    }
     
    if(input.textToFormat) {
        if(input.textToFormat.startsWith('0')) {
            localCursorPosition--;
        }
        spacesInInput = (input.textToFormat.match(/ /g) || []).length;
    } else {
        return  {
            formattedText: "",
            cursorPosition: -1
        };
    }
     
    let number_format = function(number, decimals, dec_point, thousands_sep) {
        number = (number + '').replace(/[^0-9+\-Ee.]/g, '');
        let n = !isFinite(+number) ? 0 : +number, prec = !isFinite(+decimals) ? 0
                    : Math.abs(decimals), sep = (typeof thousands_sep === 'undefined') ? ','
                    : thousands_sep, dec = (typeof dec_point === 'undefined') ? '.'
                    : dec_point, s = '', toFixedFix = function(n, prec) {
            let k = Math.pow(10, prec);
            return '' + Math.round(n * k) / k;
        };
        s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
        if (s[0].length > 3) {
            s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
        }
        return s.join(dec);
    }
     
    let textToFormat = new String(input.textToFormat + "");
    textToFormat = textToFormat.replace(/\s+/g, '');
    textToFormat = textToFormat.replace(/,/g, '.')
    textToFormat = textToFormat.replace(/[^\d^\.]/g,'');
     
    let temp = parseFloat(textToFormat);
    if(isNaN(temp)){
        return {
            formattedText: "",
            cursorPosition: -1
        };
    }
    let resultText = number_format(temp, 2, ',', ' ');
     
    let caretPosition = localCursorPosition ? localCursorPosition : resultText.length;
    let spacesAfterParse = (resultText.match(/ /g) || []).length;
 
    if(spacesAfterParse > spacesInInput) {
        caretPosition++;
    } else if(spacesAfterParse < spacesInInput) {
        caretPosition--;
    }
 
    return {
        formattedText: resultText,
        cursorPosition: caretPosition
    };
}
```

</details>

## Obsługa formaterów według wcześniejszego szablonu

Dla formaterów utworzonych według wcześniejszego szablonu widocznego poniżej, kursor po sformatowaniu tekstu zostanie ustawiony na końcu, jeśli przed sformatowaniem tekstu był ustawiony na końcu. Jeśli kursor był ustawiony w treści tekstu to kursor w polu po sformatowaniu tekstu zostanie ustawiony w tym samym miejscu, w którym był ustawiony przed sformatowaniem.

```
function formatText(textToFormat, locale) {
        return  formattedText;
}
```

Opis sygnatury funkcji wcześniejszego formatera:

| Nazwa parametru   | Rodzaj        | Typ        | Opis                                                                             |
| ----------------- | ------------- | ---------- | -------------------------------------------------------------------------------- |
| **textToFormat**  | **wejściowy** | **String** | **Tekst do sformatowania**                                                       |
| **locale**        | **wejściowy** | **String** | **Łańcuch określający język, w jakim wyświetlany jest wniosek (np. "pl", "en")** |
| **formattedText** | **wyjściowy** | **String** | **Tekst po sformatowaniu**                                                       |

## Ograniczenia <a href="#tworzenieformatera-ograniczenia" id="tworzenieformatera-ograniczenia"></a>

* W formaterach nie można korzystać z mechanizmów dziedziczenia prototypowego
* W formaterach, które formatują wyjścia z usługi obiekty, przekazywane do formatera są obiektami javowymi, w celu wykonania operacji na ciągach znaków należy je zmienić na obiekty JavaScriptowe (np: const textToFormat = new String(input.textToFormat + ""))

{% hint style="info" %}
**Wniosek demo:**\
demoFormatery
{% endhint %}
