commit c8bb6b97b9efe9da97f7c7859ecb0cb4e3752548 Author: andres.sanjuan Date: Fri Oct 2 20:33:12 2026 -0600 chore: version inicial del codigo fuente del LMS Estafeta diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d15b831 --- /dev/null +++ b/.gitignore @@ -0,0 +1,85 @@ +# ===================================================================== +# .gitignore — Plataforma LMS Estafeta +# Sube SOLO código fuente y configuración de ejemplo. +# Excluye dependencias, datos de usuarios, secretos, logs y temporales. +# ===================================================================== + +# --- Credenciales / configuración local (NUNCA versionar) --- +/config.php +/config.local.php +/env.php +.env +.env.* +*.pem +*.key + +# --- Dependencias (se regeneran con `composer install`) --- +/vendor/ +composer.phar +# NOTA: composer.json y composer.lock SÍ se versionan. + +# --- Datos de usuarios / paquetes SCORM / subidas (pesados + privados) --- +/data/recursos/ +/data/scormpkg/ +/data/tmpusers.xlsx +/data/*.xlsx +/data/imgcat/ +/data/files/ +# Se permite el .htaccess de protección de data/ +!/data/.htaccess + +# --- Multimedia generada / pesada --- +/Multimedia/ +multimedia/ + +# --- Logs / auditoría --- +/logs/* +!/logs/.htaccess + +# --- Base de datos: carpeta completa fuera del repositorio --- +# Contiene dumps con datos personales y herramientas locales. +/bd/ + +# --- Respaldos / archivos temporales del proyecto --- +*.back +*.bak +*.orig +*.rej +*~ +*.tmp +*.temp +*.log +*.swp +*.swo +.DS_Store +Thumbs.db +desktop.ini +/purge/ +/certificado/tmp/ +/tmp/ +/temp/ + +# --- Configuración de máquina local (php.ini/user.ini) --- +/config/php.ini +/config/.user.ini +!/config/.htaccess + +# --- IDE / editores --- +.idea/ +.vscode/ +*.sublime-project +*.sublime-workspace +*.code-workspace +nbproject/ +.project +.buildpath +.settings/ + +# --- OS --- +ehthumbs.db +$RECYCLE.BIN/ + +# --- Node (si en el futuro se agrega build de front) --- +node_modules/ +npm-debug.log* +yarn-error.log* diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..2fb5168 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,228 @@ +# CHANGELOG / Registro de cambios — Plataforma LMS Estafeta + +> Documento de seguimiento para agentes. Describe **todos los cambios de esta iteración**, el estado actual verificado del repositorio, archivos a subir a producción y pendientes. +> +> **Ruta local trabajada:** `C:\backup\htdocs\gitlab\Estafeta` +> **Ruta de ejecución del usuario (dev):** `C:\xampp\htdocs\git\Estafeta-plataform` +> **Producción:** `https://induccion-estafeta.com.mx/` +> **Rama/base:** sin control de versiones (copia de htdocs). + +--- + +## 0. Contexto y decisiones + +1. **Login:** por decisión del negocio se ingresa **solo con número de empleado**. No se implementó verificación de contraseña (omitido a propósito). Aun así se endureció la sesión y se agregó rate-limit. +2. **RTE:** se decide usar **únicamente `runtime/`** y **eliminar `runtimev2/`**. +3. **SCORM:** el RTE central `runtime/sco.php` sirve un contenedor con barra superior + botón "Regresar" e **iframe** que carga el paquete, con el API SCORM en la página padre (así Storyline/Rise lo encuentran subiendo por los frames). +4. Los endpoints de `admin/` (y los del front que devuelven JSON) **siempre responden JSON**; nunca deben emitir HTML de avisos/errores. + +--- + +## 1. Resumen por fases + +### Fase 1 — Seguridad base +- **`admin/auth_guard.php` (nuevo):** valida sesión + rol admin; responde `{"code":"403","msg":"No autorizado"}` si no. Fuerza `display_errors=0` y descarta salida previa (buffering) para no contaminar el JSON. +- **Guard añadido** a **113** endpoints `admin/*.php` con `require_once __DIR__.'/auth_guard.php';` (se excluyen `admin/index.php` y `admin/audit.php`, que son apoyo, no endpoints). +- **`data/.htaccess` (nuevo):** `Options -Indexes` + bloqueo de ejecución de scripts (los SCORM son estáticos → evita RCE/XSS por archivos subidos). +- **`runtime/sco.php`:** `display_errors`/`display_startup_errors` en `0`; se quitó `allow_url_include`. +- **Backups eliminados:** `admin/index.php.back`, `admin/usuarios.php.back`, `admin/usuarios.bak.php`, `admin/usuarios.bak.html`, `admin/usuarios_manager.bak.php`, `runtime/getUserDashBoard.php.back`, `runtime/runtime.js.back`, carpeta `admin/backup100322/`. + +### Fase 2 — Endurecimiento +- **`config.php`:** endurecimiento de sesión (`session.use_strict_mode`, `use_only_cookies`, `cookie_httponly`, `cookie_samesite=Lax`, `cookie_secure` si HTTPS). Solo aplica si no hay sesión activa. +- **`runtime/newlogin.php`:** reescrito con **consultas preparadas**, `session_regenerate_id(true)` (anti-fijación) y **rate-limit por IP** (60/10 min). Mantiene login por número de empleado. +- **`admin/usuarios_add.php` / `admin/usuarios_upadate.php`:** convertidos a **sentencias preparadas**. +- **CSRF:** token en `admin/index.php` (``), envío global en `js/admin.js` (`X-CSRF-Token` + `window.CSRF_TOKEN`), verificación en `auth_guard.php` para POST/PUT/DELETE, y cabecera `X-CSRF-Token` añadida a todos los uploads Uppy. +- **`runtimev2/api.php`:** corregido bug `=` → `==` en `LMSInitialize` (comparación de `lesson_status`/`score.raw`). + +### Fase 3 — Mantenibilidad y calidad +- **N+1 eliminado** en `runtime/getUserDashBoard.php`: los hijos se traen con una sola consulta `WHERE padre IN (...)`. +- **Auditoría:** `admin/audit.php` (nuevo) + `logs/.htaccess` (nuevo). Registra en `logs/admin.log`: fecha, IP, userid, numempl, archivo, acción, detalle. +- **Sentencias preparadas + auditoría** en: `admin/categorias_add.php`, `categorias_upadate.php`, `categorias_delete.php`, `recursos_add.php`, `recursos_update.php`, `recursos_delete.php`, `gamification_add.php`, `gamification_delete.php`. Los `*_delete` sanitizan ids con `intval`. +- **`runtimev2/` eliminada** (sin referencias en el proyecto). + +### Correcciones posteriores (vistas admin + dashboard) +- **polyfill.io eliminado** de `footer.php` y `runtime/rte.php` (dominio comprometido en 2024; causaba 404/CORS y rompía DataTables). +- **`JSON.parse` inseguro:** se añadió helper `parseJSON(resp)` (try/catch) y se reemplazaron todos los `JSON.parse(response)` en: `admin/usuarios.html`, `categorias.html`, `asignaciones.html`, `constancias.html`, `encuestas.html`, `evaluaciones.html`, `gamification.html`, `licencia.html`, `recursos.html`. +- **`admin/usuarios.php` y `admin/usuarios_manager.php`:** reescritos como DataTables server-side limpio y **con sentencias preparadas**; se eliminó el cifrado roto de la consulta y la propiedad `"query"` que rompía el `drawCallback` (`Cannot read properties of null (reading 'query')`). +- **`admin/usuarios.html`:** quitadas asignaciones `query = json.query`; reload con `ajax.reload(null, false)`. +- **`admin/usuarios_*_list.php` (8):** `mysqli_fetch_array` → `mysqli_fetch_assoc` (evita claves numéricas duplicadas en el JSON). +- **`admin/exportUsers.php`:** exporta según rol (`roladmin`), sin depender del `query` cifrado; `exportar()` envía `?roladmin=`. +- **`runtime/getUserDashBoard.php`:** blindado como endpoint JSON (`display_errors=0`, `Content-Type: application/json`, valida sesión y responde `{"code":"0","msg":"Sesión no válida"}` en lugar de HTML). +- **`dashboard.php`:** parseo tolerante de la respuesta (try/catch) con mensaje amigable. +- **`config.php`:** `ini_set` de sesión solo si no hay sesión activa (evita warnings). + +--- + +## 2. Archivos NUEVOS + +| Archivo | Propósito | +|---|---| +| `admin/auth_guard.php` | Guard de autenticación admin + verificación CSRF | +| `admin/audit.php` | Función `audit_log()` → escribe `logs/admin.log` | +| `admin/recursos_scorm_upload.php` | Subida de `.zip` SCORM: valida, descomprime en `data/scormpkg//` y devuelve la URL de inicio | +| `data/.htaccess` | `Options -Indexes` + bloqueo de ejecución de scripts en `data/` | +| `logs/.htaccess` | Protección de la carpeta de auditoría | +| `README.md` | Documentación general del proyecto (stack, funcionalidades, instalación, seguridad) | +| `CHANGELOG.md` | Este documento | + +--- + +## 3. Archivos MODIFICADOS (por área) + +### Configuración +- `config.php` — hardening de sesión (condicional). + +### Runtime / RTE +- `runtime/gotorte.php` — lanzador central; carga `runtime/sco.php` con `require` (sin redirect) y respaldo al `sco.php` del paquete. +- `runtime/sco.php` — contenedor con barra + botón Regresar, API en el padre, iframe con cache-busting, cierre de BD, `display_errors=0`. +- `runtime/commit.php` — `mysqli_close($link)`. +- `runtime/finish.php` — `mysqli_close($link)`. +- `runtime/runtime.js` — `pagehide` en lugar de `window.onunload`. +- `runtime/getUserDashBoard.php` — N+1 resuelto + endpoint JSON blindado. +- `runtime/newlogin.php` — consultas preparadas + anti-fijación + rate-limit. +- `runtime/rte.php` — removido polyfill.io. + +### Front (alumno) +- `dashboard.php` — scroll/resaltado de categoría al volver (`?idcat=`), parseo tolerante del dashboard. +- `recursos.php` — botón "Regresa al menú anterior" → `dashboard.php?idcat=`. +- `footer.php` — removido polyfill.io. + +### Admin — endpoints +- `admin/usuarios.php`, `admin/usuarios_manager.php` — server-side limpio + preparadas. +- `admin/usuarios_add.php`, `admin/usuarios_upadate.php` — preparadas + auditoría. +- `admin/categorias_add.php`, `admin/categorias_upadate.php`, `admin/categorias_delete.php` — preparadas + auditoría. +- `admin/recursos_add.php`, `admin/recursos_update.php`, `admin/recursos_delete.php` — preparadas + auditoría. +- `admin/gamification_add.php`, `admin/gamification_delete.php` — preparadas + auditoría. +- `admin/exportUsers.php` — export por rol sin query cifrado. +- `admin/usuarios_{centros,distritos,posiciones,sociedades,divisiones,unidades,ceco,supervisores}_list.php` — `fetch_assoc`. +- `admin/categorias.php` — normalización de imagen (`assetUrl` inline) + `'Raíz'`. +- `admin/usuarios.php`/`recursos.php` (endpoints de tabla) — columnas/normalizaciones. +- **113** `admin/*.php` — línea del guard añadida. + +### Admin — vistas (HTML) +- `admin/usuarios.html`, `categorias.html`, `asignaciones.html`, `constancias.html`, `encuestas.html`, `evaluaciones.html`, `gamification.html`, `licencia.html`, `recursos.html` — helper `parseJSON`, CSRF en Uppy, preselección por id en selects. +- `admin/index.php` — meta CSRF. + +### JS +- `js/admin.js` — `window.CSRF_TOKEN` + `$.ajaxSetup({ headers: { 'X-CSRF-Token': csrf } })`. + +### Data (paquete de ejemplo) +- `data/scormpkg/Premio_Nacional/index.html` — busca API subiendo al padre y redirige a Genially. +- `data/scormpkg/Premio_Nacional/sco.php`, `imsmanifest.xml`, XSDs — paquete creado. + +--- + +## 4. Archivos ELIMINADOS + +- Carpeta `runtimev2/` (completa). +- `admin/index.php.back`, `admin/usuarios.php.back`, `admin/usuarios.bak.php`, `admin/usuarios.bak.html`, `admin/usuarios_manager.bak.php`. +- `runtime/getUserDashBoard.php.back`, `runtime/runtime.js.back`. +- Carpeta `admin/backup100322/`. + +--- + +## 5. Estado verificado del repositorio + +- `runtimev2/` → **no existe**. Sin referencias en el proyecto. +- `admin/auth_guard.php`, `admin/audit.php`, `data/.htaccess`, `logs/.htaccess`, `README.md` → **existen**. +- Endpoints `admin/*.php` con guard: **113**. Sin guard: solo `audit.php` (helper) e `index.php` (layout). +- No quedan archivos `*.back`/`*.bak` (fuera de `vendor/` y `data/`). +- `php -l` sin errores en los archivos tocados. +- Pruebas con BD temporal (`estafeta_lms2`) realizadas y **eliminadas** al terminar: login, dashboard (con/sin sesión), usuarios server-side, listas, CRUD categorías/recursos con auditoría. + +--- + +## 6. Instrucciones para subir a producción (resumen) + +**Obligatorio subir:** +1. `config.php`, `footer.php`, `dashboard.php`, `recursos.php` +2. `runtime/` completo (gotorte, sco, commit, finish, runtime.js, getUserDashBoard, newlogin, rte) +3. `admin/` completo (incluye `auth_guard.php`, `audit.php`, `recursos_scorm_upload.php`, todos los `.php` con guard y todos los `.html`) +4. `js/admin.js` +5. `data/.htaccess` +6. `logs/` (carpeta con `.htaccess`) +7. `data/scormpkg/Premio_Nacional/` + +**Requisitos del servidor:** +- Permisos de escritura en `data/`, `data/scormpkg/`, `logs/`. +- `ZipArchive` habilitado en PHP. +- `upload_max_filesize` / `post_max_size` acordes al tamaño de los SCORM. + +**NO subir / ya no aplica:** +- `runtimev2/` (eliminada). +- `config.php` ya no contiene `assetUrl()` (se quitó). + +--- + +## 7. Pendientes / recomendaciones (no bloqueantes) + +1. **Credenciales:** mover `config.php` a variables de entorno y **rotar** la clave `wwserv_estafeta` (aparece comentada en el archivo). Hoy sigue en texto plano. +2. **SQL restante:** migrar a sentencias preparadas los endpoints de `constancias`, `encuestas`, `evaluaciones`, `licencia` y otros CRUD que aún interpolan SQL. +3. **Contraseñas:** la columna `password` usa `getEncrypt()` (no-op). Solo hashear si algún día se habilita login con contraseña. +4. **`session.save_path`** del `.htaccess` apunta a `ea-php73`; revisar con el PHP real en producción. +5. **polyfill.io dentro de `data/scormpkg/**`:** los paquetes antiguos aún lo referencian, pero no se usan (los sirve el RTE central). Limpiar opcionalmente. +6. **Tests automatizados** de flujos críticos (login, SCORM, alta de recursos). +7. **Consolidación de RTE** ya resuelta con la eliminación de `runtimev2/`; validar en producción el lanzamiento de Storyline/Rise/NOM-035. + +--- + +## 8. Notas de troubleshooting + +- **`Fatal error: Unknown database 'estafeta_lms2'`** (local): es solo del entorno local (falta la BD). En producción existe `wwserv_estafeta`. Opciones: crear/importar la BD local o hacer `dbConnect()` tolerante. +- **`Unexpected token '<' ... is not valid JSON`:** indica que un endpoint devolvió HTML (error PHP). Con los cambios, los endpoints JSON ya no deben emitir HTML; si reaparece, revisar en DevTools → Network la respuesta del endpoint y confirmar que el archivo subido es el nuevo. +- **`polyfill.io` CORS/404:** dominio comprometido; ya removido del proyecto. +- **Rutas RTE:** `runtime/sco.php` usa rutas raíz (`$_SERVER['DOCUMENT_ROOT']."/sessionManager.php"`). Si el LMS se sirve en subcarpeta, ajustar a `/gitlab/estafeta/...`. + +--- + +## 9. Corrección: vista de Usuarios (500 por columnas faltantes) + +**Síntoma:** `POST admin/usuarios.php`, `usuarios_{centros,distritos,posiciones,sociedades,divisiones,unidades,ceco,supervisores}_list.php` → `500 (Internal Server Error)`. + +**Causa raíz:** la BD local `estafeta_lms2` conserva el esquema **antiguo** de `user` +(solo `centrotrabajoid` / `distritoid` con FK a `centrotrabajo` / `distrito`). +El código actual lee/escribe columnas **denormalizadas** en `user` +(`centrotrabajonom`, `distritonom`, `posicion`, `sociedad`, `division`, +`unidad_organizativa`, `ceco`, `supervisor`). En PHP 8.1+ `mysqli` lanza +`mysqli_sql_exception` ante `Unknown column`, que antes terminaba en un fatal +sin control (HTTP 500). En PHP 7.4 solo devolvía resultados vacíos. + +**Cambios:** +1. `bd/migration_usuarios_org_fields.sql` (nuevo): agrega las columnas faltantes + a `user` (idempotente) y rellena `centrotrabajonom` / `distritonom` desde las + FK `centrotrabajo` / `distrito`. **Aplicar en cada entorno.** +2. `admin/auth_guard.php`: `set_exception_handler` que descarta la salida previa + y responde JSON (`{"code":"500",...}`) en cualquier excepción no controlada, + en lugar de HTML; registra el detalle en `error_log`. + +**Verificación local:** los 10 endpoints de usuarios + `usuarios.php` / +`usuarios_manager.php` responden JSON con datos; centros y distritos se +rellenan desde las FK. + +**Pendiente del entorno:** completar la BD local (faltan tablas `licencia`, +`evaluaciones`, `encuestas`, `constancias`, etc.); `usuarios_statistical.php` +falla por `Table 'estafeta_lms2.licencia' doesn't exist` (ahora responde JSON 500 +en vez de fatal). + +--- + +## 10. Corrección: traducción de DataTables (español) + +**Síntoma:** las tablas de `recursos`, `categorias`, `gamification` (y otras del +panel) mostraban la interfaz de DataTables en **inglés** (Search, Show entries, +Previous/Next, "No data available", etc.). + +**Causa raíz:** las vistas cargaban el idioma desde un CDN externo +(`https://cdn.datatables.net/plug-ins/.../i18n/Spanish.json`). Cuando el CDN no +está disponible (sin internet, bloqueado o CORS), DataTables cae a los textos por +defecto en inglés. `usuarios.html` ya usaba la copia local y sí se traducía. + +**Cambios:** se reemplazó la URL del CDN por la copia local `../json/Spanish.json` +(compatible con DataTables 1.10.20 incluida en `js/datatables.min.js`) en: +- `admin/categorias.html`, `gamification.html`, `recursos.html`, `constancias.html`, + `encuestas.html`, `evaluaciones.html`, `reporte_categoria.html`, `reporte_curso.html` +- `admin/reporte_categoria.php`, `reporte_curso.php`, `reporte_distrito.php`, + `reporte_categoria_completadav2.php`, `reporte_categoria_visitadosv2.php` + +**Verificación:** `http://localhost/git/LMS-Estafeta/json/Spanish.json` responde +HTTP 200; ya no quedan referencias a `cdn.datatables.net/plug-ins` en `admin/`. diff --git a/README.md b/README.md new file mode 100644 index 0000000..28b5740 --- /dev/null +++ b/README.md @@ -0,0 +1,220 @@ +# Plataforma LMS — Estafeta + +Plataforma de aprendizaje (LMS) desarrollada a la medida para **Grupo Estafeta**. Administra cursos/categorías, recursos SCORM, evaluaciones, encuestas, gamificación (insignias/sellos), constancias y reportes de avance de los colaboradores. + +> Sitio de producción: https://induccion-estafeta.com.mx/ + +--- + +## Tabla de contenido + +- [Stack utilizado](#stack-utilizado) +- [Arquitectura y estructura](#arquitectura-y-estructura) +- [Funcionalidades principales](#funcionalidades-principales) + - [Alumno / Colaborador](#alumno--colaborador) + - [Administración](#administración) + - [SCORM / RTE](#scorm--rte) + - [Reportes](#reportes) +- [Modelo de datos](#modelo-de-datos) +- [Requisitos](#requisitos) +- [Instalación](#instalación) +- [Configuración](#configuración) +- [Seguridad](#seguridad) +- [Convenciones](#convenciones) +- [Roadmap / pendientes](#roadmap--pendientes) + +--- + +## Stack utilizado + +**Backend** +- **PHP 7.4** (Apache + `mod_php`, ea-php74) +- **MySQL / MariaDB** (extensión `mysqli`) +- **Composer** con: + - `phpoffice/phpspreadsheet` — generación/lectura de Excel + - `mpdf/mpdf` — generación de PDF (constancias, reportes) + - `swiftmailer/swiftmailer` — envío de correo + +**Frontend** +- **HTML5, CSS3, JavaScript (jQuery 3.4.1)** +- **Bootstrap 4** + **bootstrap-select** +- **DataTables** (+ checkboxes, searchpanes, select) — tablas de administración +- **SweetAlert2** — modales/alertas +- **Uppy** — carga de archivos (imágenes, paquetes SCORM) +- **Trumbowyg** — editor WYSIWYG +- **Highcharts** — gráficas de reportes +- **Select2, Daterangepicker, Moment, Lodash, Owl Carousel, signature_pad** — apoyo de UI +- Librerías de exportación: **excelexportjs, js-xlsx, FileSaver** + +**SCORM** +- RTE propio en `runtime/` que implementa **SCORM 1.2** (API `LMSInitialize`, `LMSGetValue`, `LMSSetValue`, `LMSCommit`, `LMSFinish`) y lanza los paquetes en un `',i=Zt.open();if(null!==i&&i.document.write(r),i||"undefined"==typeof safari)return i;case"datauri":case"dataurl":return Zt.document.location.href=n;default:throw new Error('Output type "'+t+'" is not supported.')}}).foo=function(){try{return Ft.apply(this,arguments)}catch(t){var e=t.stack||"";~e.indexOf(" at ")&&(e=e.split(" at ")[1]);var n="Error in function "+e.split("\n")[0].split("<")[0]+": "+t.message;if(!Zt.console)throw new Error(n);Zt.console.error(n,t),Zt.alert&&alert(n)}},(Ft.foo.bar=Ft).foo),Vt=function(t){return!0===Array.isArray(V)&&-1":")"),Y=0):"[object Array]"===Object.prototype.toString.call(v[H])&&(W=v[H][1]*T,G=-v[H][2],V=(o?"<":"(")+v[H][0]+(o?">":")"),Y=1),void 0!==E&&void 0!==E[H]&&(X=E[H]+" Tw\n"),1===Y&&0=o.length-1;if(x&&!S){y+=" ";continue}if(x||S){if(S)g=b;else if(t.multiline&&a<(h+2)*(w+2)+2)continue t}else{if(!t.multiline)continue t;if(a<(h+2)*(w+2)+2)continue t;g=b}for(var _="",k=d;k<=g;k++)_+=o[k]+" ";switch(_=" "==_.substr(_.length-1)?_.substr(0,_.length-1):_,m=A(_,s+"px",i).width,t.Q){case 2:f=c-m-2;break;case 1:f=(c-m)/2;break;case 0:default:f=2}e+=f.toFixed(2)+" "+p.toFixed(2)+" Td\n",e+="("+_+") Tj\n",e+=-f.toFixed(2)+" 0 Td\n",p=-(s+2),m=0,d=g+1,w++,y=""}else;break}return r.text=e,r.fontSize=s,r},A=function(t,e,n){n=n||"helvetica";var r=h.internal.getFont(n),i=h.getStringUnitWidth(t,{font:r,fontSize:parseFloat(e),charSpace:0})*parseFloat(e);return{height:h.getStringUnitWidth("3",{font:r,fontSize:parseFloat(e),charSpace:0})*parseFloat(e)*1.5,width:i}},p={fields:[],xForms:[],acroFormDictionaryRoot:null,printedOut:!1,internal:null,isInitialized:!1},d=function(){var t=h.internal.acroformPlugin.acroFormDictionaryRoot.Fields;for(var e in t)if(t.hasOwnProperty(e)){var n=t[e];n.hasAnnotation&&m.call(h,n)}},g=function(t){h.internal.acroformPlugin.printedOut&&(h.internal.acroformPlugin.printedOut=!1,h.internal.acroformPlugin.acroFormDictionaryRoot=null),h.internal.acroformPlugin.acroFormDictionaryRoot||x.call(h),h.internal.acroformPlugin.acroFormDictionaryRoot.Fields.push(t)},m=function(t){var e={type:"reference",object:t};h.annotationPlugin.annotations[h.internal.getPageInfo(t.page).pageNumber].push(e)},y=function(){void 0!==h.internal.acroformPlugin.acroFormDictionaryRoot?h.internal.write("/AcroForm "+h.internal.acroformPlugin.acroFormDictionaryRoot.objId+" 0 R"):console.log("Root missing...")},w=function(){h.internal.events.unsubscribe(h.internal.acroformPlugin.acroFormDictionaryRoot._eventID),delete h.internal.acroformPlugin.acroFormDictionaryRoot._eventID,h.internal.acroformPlugin.printedOut=!0},v=function(t){var e=!t;t||(h.internal.newObjectDeferredBegin(h.internal.acroformPlugin.acroFormDictionaryRoot.objId),h.internal.out(h.internal.acroformPlugin.acroFormDictionaryRoot.getString()));t=t||h.internal.acroformPlugin.acroFormDictionaryRoot.Kids;for(var n in t)if(t.hasOwnProperty(n)){var r=t[n],i=r.Rect;r.Rect&&(r.Rect=l.call(this,r.Rect)),h.internal.newObjectDeferredBegin(r.objId);var o=r.objId+" 0 obj\n<<\n";if("object"===re(r)&&"function"==typeof r.getContent&&(o+=r.getContent()),r.Rect=i,r.hasAppearanceStream&&!r.appearanceStreamContent){var s=f.call(this,r);o+="/AP << /N "+s+" >>\n",h.internal.acroformPlugin.xForms.push(s)}if(r.appearanceStreamContent){for(var a in o+="/AP << ",r.appearanceStreamContent)if(r.appearanceStreamContent.hasOwnProperty(a)){var c=r.appearanceStreamContent[a];if(o+="/"+a+" ",o+="<< ",1<=Object.keys(c).length||Array.isArray(c))for(var n in c){var u;if(c.hasOwnProperty(n))"function"==typeof(u=c[n])&&(u=u.call(this,r)),o+="/"+n+" "+u+" ",0<=h.internal.acroformPlugin.xForms.indexOf(u)||h.internal.acroformPlugin.xForms.push(u)}else"function"==typeof(u=c)&&(u=u.call(this,r)),o+="/"+n+" "+u+" \n",0<=h.internal.acroformPlugin.xForms.indexOf(u)||h.internal.acroformPlugin.xForms.push(u);o+=" >>\n"}o+=">>\n"}o+=">>\nendobj\n",h.internal.out(o)}e&&b.call(this,h.internal.acroformPlugin.xForms)},b=function(t){for(var e in t)if(t.hasOwnProperty(e)){var n=e,r=t[e];h.internal.newObjectDeferredBegin(r&&r.objId);var i="";"object"===re(r)&&"function"==typeof r.getString&&(i=r.getString()),h.internal.out(i),delete t[n]}},x=function(){if(void 0!==this.internal&&(void 0===this.internal.acroformPlugin||!1===this.internal.acroformPlugin.isInitialized)){if(h=this,P.FieldNum=0,this.internal.acroformPlugin=JSON.parse(JSON.stringify(p)),this.internal.acroformPlugin.acroFormDictionaryRoot)throw new Error("Exception while creating AcroformDictionary");e=h.internal.scaleFactor,s=h.internal.pageSize.getHeight(),h.internal.acroformPlugin.acroFormDictionaryRoot=new I,h.internal.acroformPlugin.acroFormDictionaryRoot._eventID=h.internal.events.subscribe("postPutResources",w),h.internal.events.subscribe("buildDocument",d),h.internal.events.subscribe("putCatalog",y),h.internal.events.subscribe("postPutPages",v),h.internal.acroformPlugin.isInitialized=!0}},S=function(t){if(Array.isArray(t)){var e=" [";for(var n in t){if(t.hasOwnProperty(n))e+=t[n].toString(),e+=n>\n",this.stream&&(t+="stream\n",t+=this.stream,t+="\nendstream\n"),t+="endobj\n"},k.prototype.getContent=function(){var t="";return t+=function(t){var e="",n=Object.keys(t).filter(function(t){return"content"!=t&&"appearanceStreamContent"!=t&&"_"!=t.substring(0,1)});for(var r in n)if(n.hasOwnProperty(r)){var i=n[r],o=t[i];o&&(Array.isArray(o)?e+="/"+i+" "+S(o)+"\n":e+=o instanceof k?"/"+i+" "+o.objId+" 0 R\n":"/"+i+" "+o+"\n")}return e}(this)};var C=function(){var e;k.call(this),this.Type="/XObject",this.Subtype="/Form",this.FormType=1,this.BBox,this.Matrix,this.Resources="2 0 R",this.PieceInfo,Object.defineProperty(this,"Length",{enumerable:!0,get:function(){return void 0!==e?e.length:0}}),Object.defineProperty(this,"stream",{enumerable:!1,set:function(t){e=t.trim()},get:function(){return e||null}})};r(C,k);var I=function(){k.call(this);var t=[];Object.defineProperty(this,"Kids",{enumerable:!1,configurable:!0,get:function(){return 0>"},YesPushDown:function(t){var e=c(t),n=[],r=h.internal.getFont("zapfdingbats","normal").id;t.Q=1;var i=u(t,"3","ZapfDingbats",50);return n.push("0.749023 g"),n.push("0 0 "+M.internal.getWidth(t).toFixed(2)+" "+M.internal.getHeight(t).toFixed(2)+" re"),n.push("f"),n.push("BMC"),n.push("q"),n.push("0 0 1 rg"),n.push("/"+r+" "+i.fontSize.toFixed(2)+" Tf 0 g"),n.push("BT"),n.push(i.text),n.push("ET"),n.push("Q"),n.push("EMC"),e.stream=n.join("\n"),e},YesNormal:function(t){var e=c(t),n=h.internal.getFont("zapfdingbats","normal").id,r=[];t.Q=1;var i=M.internal.getHeight(t),o=M.internal.getWidth(t),s=u(t,"3","ZapfDingbats",.9*i);return r.push("1 g"),r.push("0 0 "+o.toFixed(2)+" "+i.toFixed(2)+" re"),r.push("f"),r.push("q"),r.push("0 0 1 rg"),r.push("0 0 "+(o-1).toFixed(2)+" "+(i-1).toFixed(2)+" re"),r.push("W"),r.push("n"),r.push("0 g"),r.push("BT"),r.push("/"+n+" "+s.fontSize.toFixed(2)+" Tf 0 g"),r.push(s.text),r.push("ET"),r.push("Q"),e.stream=r.join("\n"),e},OffPushDown:function(t){var e=c(t),n=[];return n.push("0.749023 g"),n.push("0 0 "+M.internal.getWidth(t).toFixed(2)+" "+M.internal.getHeight(t).toFixed(2)+" re"),n.push("f"),e.stream=n.join("\n"),e}},RadioButton:{Circle:{createAppearanceStream:function(t){var e={D:{Off:M.RadioButton.Circle.OffPushDown},N:{}};return e.N[t]=M.RadioButton.Circle.YesNormal,e.D[t]=M.RadioButton.Circle.YesPushDown,e},createMK:function(){return"<< /CA (l)>>"},YesNormal:function(t){var e=c(t),n=[],r=M.internal.getWidth(t)<=M.internal.getHeight(t)?M.internal.getWidth(t)/4:M.internal.getHeight(t)/4;r*=.9;var i=M.internal.Bezier_C;return n.push("q"),n.push("1 0 0 1 "+M.internal.getWidth(t)/2+" "+M.internal.getHeight(t)/2+" cm"),n.push(r+" 0 m"),n.push(r+" "+r*i+" "+r*i+" "+r+" 0 "+r+" c"),n.push("-"+r*i+" "+r+" -"+r+" "+r*i+" -"+r+" 0 c"),n.push("-"+r+" -"+r*i+" -"+r*i+" -"+r+" 0 -"+r+" c"),n.push(r*i+" -"+r+" "+r+" -"+r*i+" "+r+" 0 c"),n.push("f"),n.push("Q"),e.stream=n.join("\n"),e},YesPushDown:function(t){var e=c(t),n=[],r=M.internal.getWidth(t)<=M.internal.getHeight(t)?M.internal.getWidth(t)/4:M.internal.getHeight(t)/4,i=2*(r*=.9),o=i*M.internal.Bezier_C,s=r*M.internal.Bezier_C;return n.push("0.749023 g"),n.push("q"),n.push("1 0 0 1 "+(M.internal.getWidth(t)/2).toFixed(2)+" "+(M.internal.getHeight(t)/2).toFixed(2)+" cm"),n.push(i+" 0 m"),n.push(i+" "+o+" "+o+" "+i+" 0 "+i+" c"),n.push("-"+o+" "+i+" -"+i+" "+o+" -"+i+" 0 c"),n.push("-"+i+" -"+o+" -"+o+" -"+i+" 0 -"+i+" c"),n.push(o+" -"+i+" "+i+" -"+o+" "+i+" 0 c"),n.push("f"),n.push("Q"),n.push("0 g"),n.push("q"),n.push("1 0 0 1 "+(M.internal.getWidth(t)/2).toFixed(2)+" "+(M.internal.getHeight(t)/2).toFixed(2)+" cm"),n.push(r+" 0 m"),n.push(r+" "+s+" "+s+" "+r+" 0 "+r+" c"),n.push("-"+s+" "+r+" -"+r+" "+s+" -"+r+" 0 c"),n.push("-"+r+" -"+s+" -"+s+" -"+r+" 0 -"+r+" c"),n.push(s+" -"+r+" "+r+" -"+s+" "+r+" 0 c"),n.push("f"),n.push("Q"),e.stream=n.join("\n"),e},OffPushDown:function(t){var e=c(t),n=[],r=M.internal.getWidth(t)<=M.internal.getHeight(t)?M.internal.getWidth(t)/4:M.internal.getHeight(t)/4,i=2*(r*=.9),o=i*M.internal.Bezier_C;return n.push("0.749023 g"),n.push("q"),n.push("1 0 0 1 "+(M.internal.getWidth(t)/2).toFixed(2)+" "+(M.internal.getHeight(t)/2).toFixed(2)+" cm"),n.push(i+" 0 m"),n.push(i+" "+o+" "+o+" "+i+" 0 "+i+" c"),n.push("-"+o+" "+i+" -"+i+" "+o+" -"+i+" 0 c"),n.push("-"+i+" -"+o+" -"+o+" -"+i+" 0 -"+i+" c"),n.push(o+" -"+i+" "+i+" -"+o+" "+i+" 0 c"),n.push("f"),n.push("Q"),e.stream=n.join("\n"),e}},Cross:{createAppearanceStream:function(t){var e={D:{Off:M.RadioButton.Cross.OffPushDown},N:{}};return e.N[t]=M.RadioButton.Cross.YesNormal,e.D[t]=M.RadioButton.Cross.YesPushDown,e},createMK:function(){return"<< /CA (8)>>"},YesNormal:function(t){var e=c(t),n=[],r=M.internal.calculateCross(t);return n.push("q"),n.push("1 1 "+(M.internal.getWidth(t)-2).toFixed(2)+" "+(M.internal.getHeight(t)-2).toFixed(2)+" re"),n.push("W"),n.push("n"),n.push(r.x1.x.toFixed(2)+" "+r.x1.y.toFixed(2)+" m"),n.push(r.x2.x.toFixed(2)+" "+r.x2.y.toFixed(2)+" l"),n.push(r.x4.x.toFixed(2)+" "+r.x4.y.toFixed(2)+" m"),n.push(r.x3.x.toFixed(2)+" "+r.x3.y.toFixed(2)+" l"),n.push("s"),n.push("Q"),e.stream=n.join("\n"),e},YesPushDown:function(t){var e=c(t),n=M.internal.calculateCross(t),r=[];return r.push("0.749023 g"),r.push("0 0 "+M.internal.getWidth(t).toFixed(2)+" "+M.internal.getHeight(t).toFixed(2)+" re"),r.push("f"),r.push("q"),r.push("1 1 "+(M.internal.getWidth(t)-2).toFixed(2)+" "+(M.internal.getHeight(t)-2).toFixed(2)+" re"),r.push("W"),r.push("n"),r.push(n.x1.x.toFixed(2)+" "+n.x1.y.toFixed(2)+" m"),r.push(n.x2.x.toFixed(2)+" "+n.x2.y.toFixed(2)+" l"),r.push(n.x4.x.toFixed(2)+" "+n.x4.y.toFixed(2)+" m"),r.push(n.x3.x.toFixed(2)+" "+n.x3.y.toFixed(2)+" l"),r.push("s"),r.push("Q"),e.stream=r.join("\n"),e},OffPushDown:function(t){var e=c(t),n=[];return n.push("0.749023 g"),n.push("0 0 "+M.internal.getWidth(t).toFixed(2)+" "+M.internal.getHeight(t).toFixed(2)+" re"),n.push("f"),e.stream=n.join("\n"),e}}},createDefaultAppearanceStream:function(t){return"/F1 0 Tf 0 g"}};M.internal={Bezier_C:.551915024494,calculateCross:function(t){var e,n,r=M.internal.getWidth(t),i=M.internal.getHeight(t),o=(n=i)<(e=r)?n:e;return{x1:{x:(r-o)/2,y:(i-o)/2+o},x2:{x:(r-o)/2+o,y:(i-o)/2},x3:{x:(r-o)/2,y:(i-o)/2},x4:{x:(r-o)/2+o,y:(i-o)/2+o}}}},M.internal.getWidth=function(t){var e=0;return"object"===re(t)&&(e=a(t.Rect[2])),e},M.internal.getHeight=function(t){var e=0;return"object"===re(t)&&(e=a(t.Rect[3])),e},n.addField=function(t){return x.call(this),t instanceof U?this.addTextField.call(this,t):t instanceof F?this.addChoiceField.call(this,t):t instanceof O?this.addButton.call(this,t):t instanceof E?g.call(this,t):t&&g.call(this,t),t.page=h.internal.getCurrentPageInfo().pageNumber,this},n.addButton=function(t){x.call(this);var e=t||new P;e.FT="/Btn",e.Ff=o(e.Ff,t,h.internal.getPDFVersion()),g.call(this,e)},n.addTextField=function(t){x.call(this);var e=t||new P;e.FT="/Tx",e.Ff=o(e.Ff,t,h.internal.getPDFVersion()),g.call(this,e)},n.addChoiceField=function(t){x.call(this);var e=t||new P;e.FT="/Ch",e.Ff=o(e.Ff,t,h.internal.getPDFVersion()),g.call(this,e)},"object"==re(t)&&(t.ChoiceField=F,t.ListBox=q,t.ComboBox=j,t.EditBox=T,t.Button=O,t.PushButton=B,t.RadioButton=D,t.CheckBox=R,t.TextField=U,t.PasswordField=z,t.AcroForm={Appearance:M}),n.AcroFormChoiceField=F,n.AcroFormListBox=q,n.AcroFormComboBox=j,n.AcroFormEditBox=T,n.AcroFormButton=O,n.AcroFormPushButton=B,n.AcroFormRadioButton=D,n.AcroFormCheckBox=R,n.AcroFormTextField=U,n.AcroFormPasswordField=z,n.AcroFormAppearance=M,n.AcroForm={ChoiceField:F,ListBox:q,ComboBox:j,EditBox:T,Button:O,PushButton:B,RadioButton:D,CheckBox:R,TextField:U,PasswordField:z,Appearance:M}}(rt.API,"undefined"!=typeof window&&window||"undefined"!=typeof global&&global), +/** @license + * jsPDF addImage plugin + * Copyright (c) 2012 Jason Siefken, https://github.com/siefkenj/ + * 2013 Chris Dowling, https://github.com/gingerchris + * 2013 Trinh Ho, https://github.com/ineedfat + * 2013 Edwin Alejandro Perez, https://github.com/eaparango + * 2013 Norah Smith, https://github.com/burnburnrocket + * 2014 Diego Casorran, https://github.com/diegocr + * 2014 James Robb, https://github.com/jamesbrobb + * + * + */ +function(b){var x="addImage_",c={PNG:[[137,80,78,71]],TIFF:[[77,77,0,42],[73,73,42,0]],JPEG:[[255,216,255,224,void 0,void 0,74,70,73,70,0],[255,216,255,225,void 0,void 0,69,120,105,102,0,0]],JPEG2000:[[0,0,0,12,106,80,32,32]],GIF87a:[[71,73,70,56,55,97]],GIF89a:[[71,73,70,56,57,97]],BMP:[[66,77],[66,65],[67,73],[67,80],[73,67],[80,84]]};b.getImageFileTypeByImageData=function(t,e){var n,r;e=e||"UNKNOWN";var i,o,s,a="UNKNOWN";for(s in b.isArrayBufferView(t)&&(t=b.arrayBufferToBinaryString(t)),c)for(i=c[s],n=0;n>"),"trns"in e&&e.trns.constructor==Array){for(var o="",s=0,a=e.trns.length;s>"),i(e.data),r("endobj"),"smask"in e){var c="/Predictor "+e.p+" /Colors 1 /BitsPerComponent "+e.bpc+" /Columns "+e.w,u={w:e.w,h:e.h,cs:"DeviceGray",bpc:e.bpc,dp:c,data:e.smask};"f"in e&&(u.f=e.f),t.call(this,u)}e.cs===this.color_spaces.INDEXED&&(this.internal.newObject(),r("<< /Length "+e.pal.length+">>"),i(this.arrayBufferToBinaryString(new Uint8Array(e.pal))),r("endobj"))},S=function(){var t=this.internal.collections[x+"images"];for(var e in t)n.call(this,t[e])},_=function(){var t,e=this.internal.collections[x+"images"],n=this.internal.write;for(var r in e)n("/I"+(t=e[r]).i,t.n,"0","R")},k=function(t){return"function"==typeof b["process"+t.toUpperCase()]},A=function(t){return"object"===re(t)&&1===t.nodeType},C=function(t,e){if("IMG"===t.nodeName&&t.hasAttribute("src")){var n=""+t.getAttribute("src");if(0===n.indexOf("data:image/"))return unescape(n);!e&&/\.png(?:[?#].*)?$/i.test(n)&&(e="png")}if("CANVAS"===t.nodeName)var r=t;else{(r=document.createElement("canvas")).width=t.clientWidth||t.width,r.height=t.clientHeight||t.height;var i=r.getContext("2d");if(!i)throw"addImage requires canvas to be supported by browser.";i.drawImage(t,0,0,r.width,r.height)}return r.toDataURL("png"==(""+e).toLowerCase()?"image/png":"image/jpeg")},I=function(t,e){var n;if(e)for(var r in e)if(t===e[r].alias){n=e[r];break}return n};b.color_spaces={DEVICE_RGB:"DeviceRGB",DEVICE_GRAY:"DeviceGray",DEVICE_CMYK:"DeviceCMYK",CAL_GREY:"CalGray",CAL_RGB:"CalRGB",LAB:"Lab",ICC_BASED:"ICCBased",INDEXED:"Indexed",PATTERN:"Pattern",SEPARATION:"Separation",DEVICE_N:"DeviceN"},b.decode={DCT_DECODE:"DCTDecode",FLATE_DECODE:"FlateDecode",LZW_DECODE:"LZWDecode",JPX_DECODE:"JPXDecode",JBIG2_DECODE:"JBIG2Decode",ASCII85_DECODE:"ASCII85Decode",ASCII_HEX_DECODE:"ASCIIHexDecode",RUN_LENGTH_DECODE:"RunLengthDecode",CCITT_FAX_DECODE:"CCITTFaxDecode"},b.image_compression={NONE:"NONE",FAST:"FAST",MEDIUM:"MEDIUM",SLOW:"SLOW"},b.sHashCode=function(t){return t=t||"",Array.prototype.reduce&&t.split("").reduce(function(t,e){return(t=(t<<5)-t+e.charCodeAt(0))&t},0)},b.isString=function(t){return"string"==typeof t},b.validateStringAsBase64=function(t){var e=!0;return(t=t||"").length%4!=0&&(e=!1),!1===/[A-Za-z0-9\/]+/.test(t.substr(0,t.length-2))&&(e=!1),!1===/[A-Za-z0-9\/][A-Za-z0-9+\/]|[A-Za-z0-9+\/]=|==/.test(t.substr(-2))&&(e=!1),e},b.extractInfoFromBase64DataURI=function(t){return/^data:([\w]+?\/([\w]+?));\S*;*base64,(.+)$/g.exec(t)},b.supportsArrayBuffer=function(){return"undefined"!=typeof ArrayBuffer&&"undefined"!=typeof Uint8Array},b.isArrayBuffer=function(t){return!!this.supportsArrayBuffer()&&t instanceof ArrayBuffer},b.isArrayBufferView=function(t){return!!this.supportsArrayBuffer()&&("undefined"!=typeof Uint32Array&&(t instanceof Int8Array||t instanceof Uint8Array||"undefined"!=typeof Uint8ClampedArray&&t instanceof Uint8ClampedArray||t instanceof Int16Array||t instanceof Uint16Array||t instanceof Int32Array||t instanceof Uint32Array||t instanceof Float32Array||t instanceof Float64Array))},b.binaryStringToUint8Array=function(t){for(var e=t.length,n=new Uint8Array(e),r=0;r>18]+r[(258048&e)>>12]+r[(4032&e)>>6]+r[63&e];return 1==s?n+=r[(252&(e=i[a]))>>2]+r[(3&e)<<4]+"==":2==s&&(n+=r[(64512&(e=i[a]<<8|i[a+1]))>>10]+r[(1008&e)>>4]+r[(15&e)<<2]+"="),n},b.createImageInfo=function(t,e,n,r,i,o,s,a,c,u,h,l,f){var p={alias:a,w:e,h:n,cs:r,bpc:i,i:s,data:t};return o&&(p.f=o),c&&(p.dp=c),u&&(p.trns=u),h&&(p.pal=h),l&&(p.smask=l),f&&(p.p=f),p},b.addImage=function(t,e,n,r,i,o,s,a,c){var u="";if("string"!=typeof e){var h=o;o=i,i=r,r=n,n=e,e=h}if("object"===re(t)&&!A(t)&&"imageData"in t){var l=t;t=l.imageData,e=l.format||e,n=l.x||n||0,r=l.y||r||0,i=l.w||i,o=l.h||o,s=l.alias||s,a=l.compression||a,c=l.rotation||l.angle||c}if("string"==typeof t&&(t=unescape(t)),isNaN(n)||isNaN(r))throw console.error("jsPDF.addImage: Invalid coordinates",arguments),new Error("Invalid coordinates passed to jsPDF.addImage");var f,p,d,g,m,y,w,v=function(){var t=this.internal.collections[x+"images"];return t||(this.internal.collections[x+"images"]=t={},this.internal.events.subscribe("putResources",S),this.internal.events.subscribe("putXobjectDict",_)),t}.call(this);if(!(f=I(t,v))&&(A(t)&&(t=C(t,e)),(null==(w=s)||0===w.length)&&(s="string"==typeof(y=t)&&b.sHashCode(y)),!(f=I(s,v)))){if(this.isString(t)&&(""!==(u=this.convertStringToImageData(t))?t=u:void 0!==(u=this.loadImageFile(t))&&(t=u)),e=this.getImageFileTypeByImageData(t,e),!k(e))throw new Error("addImage does not support files of type '"+e+"', please ensure that a plugin for '"+e+"' support is added.");if(this.supportsArrayBuffer()&&(t instanceof Uint8Array||(p=t,t=this.binaryStringToUint8Array(t))),!(f=this["process"+e.toUpperCase()](t,(m=0,(g=v)&&(m=Object.keys?Object.keys(g).length:function(t){var e=0;for(var n in t)t.hasOwnProperty(n)&&e++;return e}(g)),m),s,((d=a)&&"string"==typeof d&&(d=d.toUpperCase()),d in b.image_compression?d:b.image_compression.NONE),p)))throw new Error("An unkwown error occurred whilst processing the image")}return function(t,e,n,r,i,o,s,a){var c=function(t,e,n){return t||e||(e=t=-96),t<0&&(t=-1*n.w*72/t/this.internal.scaleFactor),e<0&&(e=-1*n.h*72/e/this.internal.scaleFactor),0===t&&(t=e*n.w/n.h),0===e&&(e=t*n.h/n.w),[t,e]}.call(this,n,r,i),u=this.internal.getCoordinateString,h=this.internal.getVerticalCoordinateString;if(n=c[0],r=c[1],s[o]=i,a){a*=Math.PI/180;var l=Math.cos(a),f=Math.sin(a),p=function(t){return t.toFixed(4)},d=[p(l),p(f),p(-1*f),p(l),0,0,"cm"]}this.internal.write("q"),a?(this.internal.write([1,"0","0",1,u(t),h(e+r),"cm"].join(" ")),this.internal.write(d.join(" ")),this.internal.write([u(n),"0","0",u(r),"0","0","cm"].join(" "))):this.internal.write([u(n),"0","0",u(r),u(t),h(e+r),"cm"].join(" ")),this.isAdvancedAPI()&&this.internal.write([1,0,0,-1,0,0,"cm"].join(" ")),this.internal.write("/I"+i.i+" Do"),this.internal.write("Q")}.call(this,n,r,i,o,f,f.i,v,c),this},b.convertStringToImageData=function(t){var e,n="";this.isString(t)&&(null!==(e=this.extractInfoFromBase64DataURI(t))?b.validateStringAsBase64(e[3])&&(n=atob(e[3])):b.validateStringAsBase64(t)&&(n=atob(t)));return n};var u=function(t,e){return t.subarray(e,e+5)};b.processJPEG=function(t,e,n,r,i,o){var s,a=this.decode.DCT_DECODE;if(!this.isString(t)&&!this.isArrayBuffer(t)&&!this.isArrayBufferView(t))return null;if(this.isString(t)&&(s=function(t){var e;if(255===!t.charCodeAt(0)||216===!t.charCodeAt(1)||255===!t.charCodeAt(2)||224===!t.charCodeAt(3)||!t.charCodeAt(6)==="J".charCodeAt(0)||!t.charCodeAt(7)==="F".charCodeAt(0)||!t.charCodeAt(8)==="I".charCodeAt(0)||!t.charCodeAt(9)==="F".charCodeAt(0)||0===!t.charCodeAt(10))throw new Error("getJpegSize requires a binary string jpeg file");for(var n=256*t.charCodeAt(4)+t.charCodeAt(5),r=4,i=t.length;r>",u.content=m;var f=u.objId+" 0 R";m="<>";else if(c.options.pageNumber)switch(m="<>",this.internal.write(m))}}this.internal.write("]")}}]),n.createAnnotation=function(t){switch(t.type){case"link":this.link(t.bounds.x,t.bounds.y,t.bounds.w,t.bounds.h,t);break;case"text":case"freetext":this.annotationPlugin.annotations[this.internal.getCurrentPageInfo().pageNumber].push(t)}},n.link=function(t,e,n,r,i){this.annotationPlugin.annotations[this.internal.getCurrentPageInfo().pageNumber].push({x:t,y:e,w:n,h:r,options:i,type:"link"})},n.textWithLink=function(t,e,n,r){var i=this.getTextWidth(t),o=this.internal.getLineHeight()/this.internal.scaleFactor;return this.text(t,e,n),n+=.2*o,this.link(e,n-o,i,o,r),i},n.getTextWidth=function(t){var e=this.internal.getFontSize();return this.getStringUnitWidth(t)*e/this.internal.scaleFactor},n.getLineHeight=function(){return this.internal.getLineHeight()}, +/** + * @license + * Copyright (c) 2017 Aras Abbasi + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ +function(t){var s=Object.keys({ar:"Arabic (Standard)","ar-DZ":"Arabic (Algeria)","ar-BH":"Arabic (Bahrain)","ar-EG":"Arabic (Egypt)","ar-IQ":"Arabic (Iraq)","ar-JO":"Arabic (Jordan)","ar-KW":"Arabic (Kuwait)","ar-LB":"Arabic (Lebanon)","ar-LY":"Arabic (Libya)","ar-MA":"Arabic (Morocco)","ar-OM":"Arabic (Oman)","ar-QA":"Arabic (Qatar)","ar-SA":"Arabic (Saudi Arabia)","ar-SY":"Arabic (Syria)","ar-TN":"Arabic (Tunisia)","ar-AE":"Arabic (U.A.E.)","ar-YE":"Arabic (Yemen)",fa:"Persian","fa-IR":"Persian/Iran",ur:"Urdu"}),l={1569:[65152],1570:[65153,65154,65153,65154],1571:[65155,65156,65155,65156],1572:[65157,65158],1573:[65159,65160,65159,65160],1574:[65161,65162,65163,65164],1575:[65165,65166,65165,65166],1576:[65167,65168,65169,65170],1577:[65171,65172],1578:[65173,65174,65175,65176],1579:[65177,65178,65179,65180],1580:[65181,65182,65183,65184],1581:[65185,65186,65187,65188],1582:[65189,65190,65191,65192],1583:[65193,65194,65193],1584:[65195,65196,65195],1585:[65197,65198,65197],1586:[65199,65200,65199],1587:[65201,65202,65203,65204],1588:[65205,65206,65207,65208],1589:[65209,65210,65211,65212],1590:[65213,65214,65215,65216],1591:[65217,65218,65219,65220],1592:[65221,65222,65223,65224],1593:[65225,65226,65227,65228],1594:[65229,65230,65231,65232],1601:[65233,65234,65235,65236],1602:[65237,65238,65239,65240],1603:[65241,65242,65243,65244],1604:[65245,65246,65247,65248],1605:[65249,65250,65251,65252],1606:[65253,65254,65255,65256],1607:[65257,65258,65259,65260],1608:[65261,65262,65261],1609:[65263,65264,64488,64489],1610:[65265,65266,65267,65268],1649:[64336,64337],1655:[64477],1657:[64358,64359,64360,64361],1658:[64350,64351,64352,64353],1659:[64338,64339,64340,64341],1662:[64342,64343,64344,64345],1663:[64354,64355,64356,64357],1664:[64346,64347,64348,64349],1667:[64374,64375,64376,64377],1668:[64370,64371,64372,64373],1670:[64378,64379,64380,64381],1671:[64382,64383,64384,64385],1672:[64392,64393],1676:[64388,64389],1677:[64386,64387],1678:[64390,64391],1681:[64396,64397],1688:[64394,64395,64394],1700:[64362,64363,64364,64365],1702:[64366,64367,64368,64369],1705:[64398,64399,64400,64401],1709:[64467,64468,64469,64470],1711:[64402,64403,64404,64405],1713:[64410,64411,64412,64413],1715:[64406,64407,64408,64409],1722:[64414,64415],1723:[64416,64417,64418,64419],1726:[64426,64427,64428,64429],1728:[64420,64421],1729:[64422,64423,64424,64425],1733:[64480,64481],1734:[64473,64474],1735:[64471,64472],1736:[64475,64476],1737:[64482,64483],1739:[64478,64479],1740:[64508,64509,64510,64511],1744:[64484,64485,64486,64487],1746:[64430,64431],1747:[64432,64433]},f={1570:[65269,65270,65269,65270],1571:[65271,65272,65271,65272],1573:[65273,65274,65273,65274],1575:[65275,65276,65275,65276]},p={1570:[65153,65154,65153,65154],1571:[65155,65156,65155,65156],1573:[65159,65160,65159,65160],1575:[65165,65166,65165,65166]},d={1612:64606,1613:64607,1614:64608,1615:64609,1616:64610},e=[1570,1571,1573,1575],n=[1569,1570,1571,1572,1573,1575,1577,1583,1584,1585,1586,1608,1688],o=0,a=1,c=2,u=3;function g(t){return void 0!==t&&void 0!==l[t.charCodeAt(0)]}function h(t){return void 0!==t&&0<=n.indexOf(t.charCodeAt(0))}function m(t){return void 0!==t&&0<=e.indexOf(t.charCodeAt(0))}function y(t){return g(t)&&2<=l[t.charCodeAt(0)].length}function w(t,e,n,r){return g(t)?(r=r||{},l=Object.assign(l,r),!y(t)||!g(e)&&!g(n)||!g(n)&&h(e)||h(t)&&!g(e)||h(t)&&m(e)||h(t)&&h(e)?(l=Object.assign(l,p),o):g(i=t)&&4==l[i.charCodeAt(0)].length&&g(e)&&!h(e)&&g(n)&&y(n)?(l=Object.assign(l,p),u):h(t)||!g(n)?(l=Object.assign(l,p),a):(l=Object.assign(l,p),c)):-1;var i}var v=t.processArabic=function(t,e){t=t||"",e=e||!1;var n,r,i,o="",s=0,a=0,c="",u="",h="";for(s=0;s>"),this.internal.out("endobj")}),this.internal.events.subscribe("putCatalog",function(){this.internal.out("/OpenAction "+e+" 0 R")})}return this},( +/** + * @license + * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ +r=rt.API).events.push(["initialized",function(){this.canvas.pdf=this}]),r.canvas={getContext:function(t){return(this.pdf.context2d._canvas=this).pdf.context2d},childNodes:[],style:{},autoContext2dResizeX:!0,autoContext2dResizeY:!0},Object.defineProperty(r.canvas,"width",{get:function(){return this._width},set:function(t){this._width=t,this.autoContext2dResizeX&&(this.getContext("2d").pageWrapX=t+1)}}),Object.defineProperty(r.canvas,"height",{get:function(){return this._height},set:function(t){this._height=t,this.autoContext2dResizeY&&(this.getContext("2d").pageWrapY=t+1)}}), +/** + * @license + * ==================================================================== + * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com + * 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br + * 2013 Lee Driscoll, https://github.com/lsdriscoll + * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria + * 2014 James Hall, james@parall.ax + * 2014 Diego Casorran, https://github.com/diegocr + * + * + * ==================================================================== + */ +C=rt.API,I={x:void 0,y:void 0,w:void 0,h:void 0,ln:void 0},P=1,p=function(t,e,n,r,i){I={x:t,y:e,w:n,h:r,ln:i}},d=function(){return I},F={left:0,top:0,bottom:0},C.setHeaderFunction=function(t){c=t},C.getTextDimensions=function(t,e){var n=this.table_font_size||this.internal.getFontSize(),r=(this.internal.getFont().fontStyle,(e=e||{}).scaleFactor||this.internal.scaleFactor),i=0,o=0,s=0;if("string"==typeof t)0!=(i=this.getStringUnitWidth(t)*n)&&(o=1);else if("[object Array]"===Object.prototype.toString.call(t)){for(var a=0;a=this.internal.pageSize.getHeight()-u.bottom&&(this.cellAddPage(),c=!0,this.printHeaders&&this.tableHeaderRow&&this.printHeaderRow(o,!0)),e=d().y+d().h,c&&(e=23)}if(void 0!==i[0])if(this.printingHeaderRow?this.rect(t,e,n,r,"FD"):this.rect(t,e,n,r),"right"===s){i instanceof Array||(i=[i]);for(var h=0;h=this.pageBreaks[r]){e++,0===this.lastBreak&&n++;var i=this.pageBreaks[r]-this.lastBreak;this.lastBreak=this.pageBreaks[r],n+=Math.floor(i/this.pageWrapY)}if(0===this.lastBreak)n+=Math.floor(t/this.pageWrapY)+1;return n+e}return this.pdf.internal.getCurrentPageInfo().pageNumber},_gotoPage:function(t){},drawImage:function(t,e,n,r,i,o,s,a,c){void 0!==o&&(e=o,n=s,r=a,i=c),e=this._wrapX(e),n=this._wrapY(n);var u,h=this._matrix_map_rect(this.ctx._transform,{x:e,y:n,w:r,h:i}),l=(this._matrix_map_rect(this.ctx._transform,{x:o,y:s,w:a,h:c}),/data:image\/(\w+).*/i.exec(t));u=null!=l?l[1]:"png",this.pdf.addImage(t,u,h.x,h.y,h.w,h.h)},_matrix_multiply:function(t,e){var n=e[0],r=e[1],i=e[2],o=e[3],s=e[4],a=e[5],c=n*t[0]+r*t[2],u=i*t[0]+o*t[2],h=s*t[0]+a*t[2]+t[4];return r=n*t[1]+r*t[3],o=i*t[1]+o*t[3],a=s*t[1]+a*t[3]+t[5],[n=c,r,i=u,o,s=h,a]},_matrix_rotation:function(t){return Math.atan2(t[2],t[0])},_matrix_decompose:function(t){var e=t[0],n=t[1],r=t[2],i=t[3],o=Math.sqrt(e*e+n*n),s=(e/=o)*r+(n/=o)*i;r-=e*s,i-=n*s;var a=Math.sqrt(r*r+i*i);return s/=a,e*(i/=a)>"),this.internal.out("endobj"),l=this.internal.newObject(),this.internal.out("<<"),this.internal.out("/S /JavaScript"),this.internal.out("/JS ("+f+")"),this.internal.out(">>"),this.internal.out("endobj")}),this.internal.events.subscribe("putCatalog",function(){void 0!==h&&void 0!==l&&this.internal.out("/Names <>")}),this},( +/** + * @license + * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ +g=rt.API).events.push(["postPutResources",function(){var t=this,e=/^(\d+) 0 obj$/;if(0> endobj")}var l=t.internal.newObject();for(t.internal.write("<< /Names [ "),r=0;r>","endobj"),t.internal.newObject(),t.internal.write("<< /Dests "+l+" 0 R"),t.internal.write(">>","endobj")}}]),g.events.push(["putCatalog",function(){0> \r\nendobj\r\n"},o.outline.count_r=function(t,e){for(var n=0;n>>24&255,f[l++]=a>>>16&255,f[l++]=a>>>8&255,f[l++]=255&a,q.arrayBufferToBinaryString(f)},m=function(t,e){var n=Math.LOG2E*Math.log(32768)-8<<4|8,r=n<<8;return r|=Math.min(3,(e-1&255)>>1)<<6,r|=0,[n,255&(r+=31-r%31)]},y=function(t,e){for(var n,r=1,i=0,o=t.length,s=0;0>>0},v=function(t,e,n,r){for(var i,o,s,a=t.length/e,c=new Uint8Array(t.length+a),u=O(),h=0;h>>1)&255;return o},k=function(t,e,n){var r,i,o,s,a=[],c=0,u=t.length;for(a[0]=4;c>>d&255,d+=o.bits;y[v]=x>>>d&255}if(16===o.bits){g=(C=new Uint32Array(o.decodePixels().buffer)).length,m=new Uint8Array(g*(32/o.pixelBitlength)*o.colors),y=new Uint8Array(g*(32/o.pixelBitlength));for(var x,S=1>>0&255,S&&(m[b++]=x>>>16&255,x=C[v++],m[b++]=x>>>0&255),y[_++]=x>>>16&255;p=8}r!==q.image_compression.NONE&&j()?(t=T(m,o.width*o.colors,o.colors,r),h=T(y,o.width,1,r)):(t=m,h=y,f=null)}if(3===o.colorType&&(l=this.color_spaces.INDEXED,u=o.palette,o.transparency.indexed)){var k=o.transparency.indexed,A=0;for(v=0,g=k.length;vr&&(i.push(t.slice(c,o)),a=0,c=o),a+=e[o],o++;return c!==o&&i.push(t.slice(c,o)),i},H=function(t,e,n){n||(n={});var r,i,o,s,a,c,u=[],h=[u],l=n.textIndent||0,f=0,p=0,d=t.split(" "),g=z.apply(this,[" ",n])[0];if(c=-1===n.lineIndent?d[0].length+2:n.lineIndent||0){var m=Array(c).join(" "),y=[];d.map(function(t){1<(t=t.split(/\s*\n/)).length?y=y.concat(t.map(function(t,e){return(e&&t.length?"\n":"")+t})):y.push(t[0])}),d=y,c=N.apply(this,[m,n])}for(o=0,s=d.length;o>")}),this.internal.viewerpreferences.isSubscribed=!0),this.internal.viewerpreferences.configuration=n,this}, +/** ==================================================================== + * jsPDF XMP metadata plugin + * Copyright (c) 2016 Jussi Utunen, u-jussi@suomi24.fi + * + * + * ==================================================================== + */ +Q=rt.API,tt=$=Z="",Q.addMetadata=function(t,e){return $=e||"http://jspdf.default.namespaceuri/",Z=t,this.internal.events.subscribe("postPutResources",function(){if(Z){var t='',e=unescape(encodeURIComponent('')),n=unescape(encodeURIComponent(t)),r=unescape(encodeURIComponent(Z)),i=unescape(encodeURIComponent("")),o=unescape(encodeURIComponent("")),s=n.length+r.length+i.length+e.length+o.length;tt=this.internal.newObject(),this.internal.write("<< /Type /Metadata /Subtype /XML /Length "+s+" >>"),this.internal.write("stream"),this.internal.write(e+n+r+i+o),this.internal.write("endstream"),this.internal.write("endobj")}else tt=""}),this.internal.events.subscribe("putCatalog",function(){tt&&this.internal.write("/Metadata "+tt+" 0 R")}),this},function(p,t){var e=p.API;var m=e.pdfEscape16=function(t,e){for(var n,r=e.metadata.Unicode.widths,i=["","0","00","000","0000"],o=[""],s=0,a=t.length;s<"+i+">");return r.length&&(o+="\n"+r.length+" beginbfchar\n"+r.join("\n")+"\nendbfchar\n"),o+="endcmap\nCMapName currentdict /CMap defineresource pop\nend\nend"};e.events.push(["putFont",function(t){!function(t,e,n,r){if(t.metadata instanceof p.API.TTFFont&&"Identity-H"===t.encoding){for(var i=t.metadata.Unicode.widths,o=t.metadata.subset.encode(t.metadata.glyIdsUsed,1),s="",a=0;a>"),r(s),e("endobj");var u=n(),h=d(t.metadata.toUnicode);e("<<"),e("/Length "+h.length),e("/Length1 "+h.length),e(">>"),r(h),e("endobj");var l=n();e("<<"),e("/Type /FontDescriptor"),e("/FontName /"+t.fontName),e("/FontFile2 "+c+" 0 R"),e("/FontBBox "+p.API.PDFObject.convert(t.metadata.bbox)),e("/Flags "+t.metadata.flags),e("/StemV "+t.metadata.stemV),e("/ItalicAngle "+t.metadata.italicAngle),e("/Ascent "+t.metadata.ascender),e("/Descent "+t.metadata.decender),e("/CapHeight "+t.metadata.capHeight),e(">>"),e("endobj");var f=n();e("<<"),e("/Type /Font"),e("/BaseFont /"+t.fontName),e("/FontDescriptor "+l+" 0 R"),e("/W "+p.API.PDFObject.convert(i)),e("/CIDToGIDMap /Identity"),e("/DW 1000"),e("/Subtype /CIDFontType2"),e("/CIDSystemInfo"),e("<<"),e("/Supplement 0"),e("/Registry (Adobe)"),e("/Ordering ("+t.encoding+")"),e(">>"),e(">>"),e("endobj"),t.objectNumber=n(),e("<<"),e("/Type /Font"),e("/Subtype /Type0"),e("/ToUnicode "+u+" 0 R"),e("/BaseFont /"+t.fontName),e("/Encoding /"+t.encoding),e("/DescendantFonts ["+f+" 0 R]"),e(">>"),e("endobj"),t.isAlreadyPutted=!0}}(t.font,t.out,t.newObject,t.putStream)}]);e.events.push(["putFont",function(t){!function(t,e,n,r){if(t.metadata instanceof p.API.TTFFont&&"WinAnsiEncoding"===t.encoding){t.metadata.Unicode.widths;for(var i=t.metadata.rawData,o="",s=0;s>"),e("endobj"),t.objectNumber=n(),s=0;s>"),e("endobj"),t.isAlreadyPutted=!0}}(t.font,t.out,t.newObject,t.putStream)}]);var u=function(t){var e,n,r=t.text||"",i=t.x,o=t.y,s=t.options||{},a=t.mutex||{},c=a.pdfEscape,u=a.activeFontKey,h=a.fonts,l=(a.activeFontSize,""),f=0,p="",d=h[n=u].encoding;if("Identity-H"!==h[n].encoding)return{text:r,x:i,y:o,options:s,mutex:a};for(p=r,n=u,"[object Array]"===Object.prototype.toString.call(r)&&(p=r[0]),f=0;f>7,i=1<<(7&n)+1;x[t++];x[t++];var o=null;r&&(o=t,t+=3*i);var s=!0,a=[],c=0,u=null,h=0,l=null;for(this.width=S,this.height=e;s&&t>2&7,t++;break;case 254:for(;;){if(0===(k=x[t++]))break;t+=k}break;default:throw"Unknown graphic control label: 0x"+x[t-1].toString(16)}break;case 44:var p=x[t++]|x[t++]<<8,d=x[t++]|x[t++]<<8,g=x[t++]|x[t++]<<8,m=x[t++]|x[t++]<<8,y=x[t++],w=y>>6&1,v=o,b=!1;if(y>>7){b=!0;v=t,t+=3*(1<<(7&y)+1)}var _=t;for(t++;;){var k;if(0===(k=x[t++]))break;t+=k}a.push({x:p,y:d,width:g,height:m,has_local_palette:b,palette_offset:v,data_offset:_,data_length:t-_,transparent_index:u,interlaced:!!w,delay:c,disposal:h});break;case 59:s=!1;break;default:throw"Unknown gif block: 0x"+x[t-1].toString(16)}this.numFrames=function(){return a.length},this.loopCount=function(){return l},this.frameInfo=function(t){if(t<0||t>=a.length)throw"Frame index out of range.";return a[t]},this.decodeAndBlitFrameBGRA=function(t,e){var n=this.frameInfo(t),r=n.width*n.height,i=new Uint8Array(r);bt(x,n.data_offset,i,r);var o=n.palette_offset,s=n.transparent_index;null===s&&(s=256);var a=n.width,c=S-a,u=a,h=4*(n.y*S+n.x),l=4*((n.y+n.height)*S+n.x),f=h,p=4*c;!0===n.interlaced&&(p+=4*(a+c)*7);for(var d=8,g=0,m=i.length;g>=1)),y===s)f+=4;else{var w=x[o+3*y],v=x[o+3*y+1],b=x[o+3*y+2];e[f++]=b,e[f++]=v,e[f++]=w,e[f++]=255}--u}},this.decodeAndBlitFrameRGBA=function(t,e){var n=this.frameInfo(t),r=n.width*n.height,i=new Uint8Array(r);bt(x,n.data_offset,i,r);var o=n.palette_offset,s=n.transparent_index;null===s&&(s=256);var a=n.width,c=S-a,u=a,h=4*(n.y*S+n.x),l=4*((n.y+n.height)*S+n.x),f=h,p=4*c;!0===n.interlaced&&(p+=4*(a+c)*7);for(var d=8,g=0,m=i.length;g>=1)),y===s)f+=4;else{var w=x[o+3*y],v=x[o+3*y+1],b=x[o+3*y+2];e[f++]=w,e[f++]=v,e[f++]=b,e[f++]=255}--u}}}function bt(t,e,n,r){for(var i=t[e++],o=1<>=c,h-=c,m!==o){if(m===s)break;for(var y=m>8,++w;var b=v;if(r>=8;null!==g&&a<4096&&(d[a++]=g<<8|b,u+1<=a&&c<12&&(++c,u=u<<1|1)),g=m}else a=s+1,u=(1<<(c=i+1))-1,g=null}return f!==r&&console.log("Warning, gif stream shorter than expected."),n}"undefined"!=typeof module&&module.exports?module.exports.saveAs=ie:"undefined"!=typeof define&&null!==define&&null!==define.amd&&define("FileSaver.js",function(){return ie}),rt.API.adler32cs=(ut="function"==typeof ArrayBuffer&&"function"==typeof Uint8Array,ht=ut?function(t){return t instanceof ArrayBuffer||!1}:function(){return!1},lt=function(t){return unescape(encodeURIComponent(t))},ft=65521,pt=function(t,e){for(var n=65535&t,r=t>>>16,i=0,o=e.length;i>>0},dt=function(t,e){for(var n=65535&t,r=t>>>16,i=0,o=e.length;i>>0},mt=(gt={}).Adler32=(((ct=(at=function(t){if(!(this instanceof at))throw new TypeError("Constructor cannot called be as a function.");if(!isFinite(t=null==t?1:+t))throw new Error("First arguments needs to be a finite number.");this.checksum=t>>>0}).prototype={}).constructor=at).from=((it=function(t){if(!(this instanceof at))throw new TypeError("Constructor cannot called be as a function.");if(null==t)throw new Error("First argument needs to be a string.");this.checksum=pt(1,t.toString())}).prototype=ct,it),at.fromUtf8=((ot=function(t){if(!(this instanceof at))throw new TypeError("Constructor cannot called be as a function.");if(null==t)throw new Error("First argument needs to be a string.");var e=lt(t.toString());this.checksum=pt(1,e)}).prototype=ct,ot),ut&&(at.fromBuffer=((st=function(t){if(!(this instanceof at))throw new TypeError("Constructor cannot called be as a function.");if(!ht(t))throw new Error("First argument needs to be ArrayBuffer.");var e=new Uint8Array(t);return this.checksum=dt(1,e)}).prototype=ct,st)),ct.update=function(t){if(null==t)throw new Error("First argument needs to be a string.");return t=t.toString(),this.checksum=pt(this.checksum,t)},ct.updateUtf8=function(t){if(null==t)throw new Error("First argument needs to be a string.");var e=lt(t.toString());return this.checksum=pt(this.checksum,e)},ut&&(ct.updateBuffer=function(t){if(!ht(t))throw new Error("First argument needs to be ArrayBuffer.");var e=new Uint8Array(t);return this.checksum=dt(this.checksum,e)}),ct.clone=function(){return new mt(this.checksum)},at),gt.from=function(t){if(null==t)throw new Error("First argument needs to be a string.");return pt(1,t.toString())},gt.fromUtf8=function(t){if(null==t)throw new Error("First argument needs to be a string.");var e=lt(t.toString());return pt(1,e)},ut&&(gt.fromBuffer=function(t){if(!ht(t))throw new Error("First argument need to be ArrayBuffer.");var e=new Uint8Array(t);return dt(1,e)}),gt), +/* + Copyright (c) 2008, Adobe Systems Incorporated + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Adobe Systems Incorporated nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + Copyright (c) 2013 Gildas Lormeau. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, + INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +function(t){var d=15,g=573,e=[0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,0,0,16,17,18,18,19,19,20,20,20,20,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29];function lt(){var p=this;function c(t,e){for(var n=0;n|=1&t,t>>>=1,n<<=1,0<--e;);return n>>>1}p.build_tree=function(t){var e,n,r,i=p.dyn_tree,o=p.stat_desc.static_tree,s=p.stat_desc.elems,a=-1;for(t.heap_len=0,t.heap_max=g,e=0;ep.max_code||(t.bl_count[i]++,o=0,h<=n&&(o=u[n-h]),s=a[2*n],t.opt_len+=s*(i+o),c&&(t.static_len+=s*(c[2*n+1]+o)));if(0!==f){do{for(i=l-1;0===t.bl_count[i];)i--;t.bl_count[i]--,t.bl_count[i+1]+=2,t.bl_count[l]--,f-=2}while(0p.max_code||(a[2*r+1]!=i&&(t.opt_len+=(i-a[2*r+1])*a[2*r],a[2*r+1]=i),n--)}}(t),function(t,e,n){var r,i,o,s=[],a=0;for(r=1;r<=d;r++)s[r]=a=a+n[r-1]<<1;for(i=0;i<=e;i++)0!==(o=t[2*i+1])&&(t[2*i]=c(s[o]++,o))}(i,p.max_code,t.bl_count)}}function ft(t,e,n,r,i){var o=this;o.static_tree=t,o.extra_bits=e,o.extra_base=n,o.elems=r,o.max_length=i}lt._length_code=[0,1,2,3,4,5,6,7,8,8,9,9,10,10,11,11,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28],lt.base_length=[0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224,0],lt.base_dist=[0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576],lt.d_code=function(t){return t<256?e[t]:e[256+(t>>>7)]},lt.extra_lbits=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],lt.extra_dbits=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],lt.extra_blbits=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],lt.bl_order=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],ft.static_ltree=[12,8,140,8,76,8,204,8,44,8,172,8,108,8,236,8,28,8,156,8,92,8,220,8,60,8,188,8,124,8,252,8,2,8,130,8,66,8,194,8,34,8,162,8,98,8,226,8,18,8,146,8,82,8,210,8,50,8,178,8,114,8,242,8,10,8,138,8,74,8,202,8,42,8,170,8,106,8,234,8,26,8,154,8,90,8,218,8,58,8,186,8,122,8,250,8,6,8,134,8,70,8,198,8,38,8,166,8,102,8,230,8,22,8,150,8,86,8,214,8,54,8,182,8,118,8,246,8,14,8,142,8,78,8,206,8,46,8,174,8,110,8,238,8,30,8,158,8,94,8,222,8,62,8,190,8,126,8,254,8,1,8,129,8,65,8,193,8,33,8,161,8,97,8,225,8,17,8,145,8,81,8,209,8,49,8,177,8,113,8,241,8,9,8,137,8,73,8,201,8,41,8,169,8,105,8,233,8,25,8,153,8,89,8,217,8,57,8,185,8,121,8,249,8,5,8,133,8,69,8,197,8,37,8,165,8,101,8,229,8,21,8,149,8,85,8,213,8,53,8,181,8,117,8,245,8,13,8,141,8,77,8,205,8,45,8,173,8,109,8,237,8,29,8,157,8,93,8,221,8,61,8,189,8,125,8,253,8,19,9,275,9,147,9,403,9,83,9,339,9,211,9,467,9,51,9,307,9,179,9,435,9,115,9,371,9,243,9,499,9,11,9,267,9,139,9,395,9,75,9,331,9,203,9,459,9,43,9,299,9,171,9,427,9,107,9,363,9,235,9,491,9,27,9,283,9,155,9,411,9,91,9,347,9,219,9,475,9,59,9,315,9,187,9,443,9,123,9,379,9,251,9,507,9,7,9,263,9,135,9,391,9,71,9,327,9,199,9,455,9,39,9,295,9,167,9,423,9,103,9,359,9,231,9,487,9,23,9,279,9,151,9,407,9,87,9,343,9,215,9,471,9,55,9,311,9,183,9,439,9,119,9,375,9,247,9,503,9,15,9,271,9,143,9,399,9,79,9,335,9,207,9,463,9,47,9,303,9,175,9,431,9,111,9,367,9,239,9,495,9,31,9,287,9,159,9,415,9,95,9,351,9,223,9,479,9,63,9,319,9,191,9,447,9,127,9,383,9,255,9,511,9,0,7,64,7,32,7,96,7,16,7,80,7,48,7,112,7,8,7,72,7,40,7,104,7,24,7,88,7,56,7,120,7,4,7,68,7,36,7,100,7,20,7,84,7,52,7,116,7,3,8,131,8,67,8,195,8,35,8,163,8,99,8,227,8],ft.static_dtree=[0,5,16,5,8,5,24,5,4,5,20,5,12,5,28,5,2,5,18,5,10,5,26,5,6,5,22,5,14,5,30,5,1,5,17,5,9,5,25,5,5,5,21,5,13,5,29,5,3,5,19,5,11,5,27,5,7,5,23,5],ft.static_l_desc=new ft(ft.static_ltree,lt.extra_lbits,257,286,d),ft.static_d_desc=new ft(ft.static_dtree,lt.extra_dbits,0,30,d),ft.static_bl_desc=new ft(null,lt.extra_blbits,0,19,7);function n(t,e,n,r,i){var o=this;o.good_length=t,o.max_lazy=e,o.nice_length=n,o.max_chain=r,o.func=i}var pt=[new n(0,0,0,0,0),new n(4,4,8,4,1),new n(4,5,16,8,1),new n(4,6,32,32,1),new n(4,4,16,16,2),new n(8,16,32,32,2),new n(8,16,128,128,2),new n(8,32,128,256,2),new n(32,128,258,1024,2),new n(32,258,258,4096,2)],dt=["need dictionary","stream end","","","stream error","data error","","buffer error","",""],gt=262;function mt(t,e,n,r){var i=t[2*e],o=t[2*n];return i>>8&255)}function $(t,e){var n,r=e;16-r>>16-W,W+=r-16):(H|=t<>>=8,W-=8)}function rt(t,e){var n,r,i;if(G.pending_buf[N+2*M]=t>>>8&255,G.pending_buf[N+2*M+1]=255&t,G.pending_buf[U+M]=255&e,M++,0===t?a[2*e]++:(o++,t--,a[2*(lt._length_code[e]+256+1)]++,E[2*lt.d_code(t)]++),0==(8191&M)&&2>>=3,o>>3,(i=G.static_len+3+7>>>3)<=r&&(r=i)):r=i=e+5,e+4<=r&&-1!=t?st(t,e,n):i==r?($(2+(n?1:0),3),it(ft.static_ltree,ft.static_dtree)):($(4+(n?1:0),3),function(t,e,n){var r;for($(t-257,5),$(e-1,5),$(n-4,4),r=0;r>=2),Ps&&0!=--r);return o<=P?o:P}function ht(t){return t.total_in=t.total_out=0,t.msg=null,G.pending=0,G.pending_out=0,u=113,l=0,V.dyn_tree=a,V.stat_desc=ft.static_l_desc,Y.dyn_tree=E,Y.stat_desc=ft.static_d_desc,X.dyn_tree=R,X.stat_desc=ft.static_bl_desc,W=H=0,L=8,J(),function(){var t;for(i=2*f,t=y[v-1]=0;t>1)&&(i=3),r|=i<<6,0!==C&&(r|=32),u=113,Q((a=r+=31-r%31)>>8&255),Q(255&a)),0!==G.pending){if(c.flush_pending(),0===c.avail_out)return l=-1,0}else if(0===c.avail_in&&e<=o&&4!=e)return c.msg=dt[7],-5;if(666==u&&0!==c.avail_in)return t.msg=dt[7],-5;if(0!==c.avail_in||0!==P||0!=e&&666!=u){switch(s=-1,pt[T].func){case 0:s=function(t){var e,n=65535;for(h-5t.avail_out&&(e=t.avail_out),0!==e&&(t.next_out.set(t.dstate.pending_buf.subarray(t.dstate.pending_out,t.dstate.pending_out+e),t.next_out_index),t.next_out_index+=e,t.dstate.pending_out+=e,t.total_out+=e,t.avail_out-=e,t.dstate.pending-=e,0===t.dstate.pending&&(t.dstate.pending_out=0))}};var o=t.zip||t;o.Deflater=o._jzlib_Deflater=function(t){var a=new i,c=new Uint8Array(512),e=t?t.level:-1;void 0===e&&(e=-1),a.deflateInit(e),a.next_out=c,this.append=function(t,e){var n,r=[],i=0,o=0,s=0;if(t.length){a.next_in_index=0,a.next_in=t,a.avail_in=t.length;do{if(a.next_out_index=0,a.avail_out=512,0!=a.deflate(0))throw new Error("deflating: "+a.msg);a.next_out_index&&(512==a.next_out_index?r.push(new Uint8Array(c)):r.push(new Uint8Array(c.subarray(0,a.next_out_index)))),s+=a.next_out_index,e&&0 "+a.toRGB()+" -> "+a.toHex());s.appendChild(c),s.appendChild(u),o.appendChild(s)}catch(t){}return o}},function(t){var n="+".charCodeAt(0),r="/".charCodeAt(0),i="0".charCodeAt(0),o="a".charCodeAt(0),s="A".charCodeAt(0),a="-".charCodeAt(0),c="_".charCodeAt(0),h=function(t){var e=t.charCodeAt(0);return e===n||e===a?62:e===r||e===c?63:e>16),u((65280&i)>>8),u(255&i);return 2===o?u(255&(i=h(t.charAt(e))<<2|h(t.charAt(e+1))>>4)):1===o&&(u((i=h(t.charAt(e))<<10|h(t.charAt(e+1))<<4|h(t.charAt(e+2))>>2)>>8&255),u(255&i)),s}(n),e,r)},i.prototype.parse=function(){return this.directory=new e(this.contents),this.head=new p(this),this.name=new b(this),this.cmap=new y(this),this.toUnicode=new Map,this.hhea=new g(this),this.maxp=new x(this),this.hmtx=new S(this),this.post=new w(this),this.os2=new m(this),this.loca=new I(this),this.glyf=new k(this),this.ascender=this.os2.exists&&this.os2.ascender||this.hhea.ascender,this.decender=this.os2.exists&&this.os2.decender||this.hhea.decender,this.lineGap=this.os2.exists&&this.os2.lineGap||this.hhea.lineGap,this.bbox=[this.head.xMin,this.head.yMin,this.head.xMax,this.head.yMax]},i.prototype.registerTTF=function(){var i,t,e,n,r;if(this.scaleFactor=1e3/this.head.unitsPerEm,this.bbox=function(){var t,e,n,r;for(r=[],t=0,e=(n=this.bbox).length;t>16)&&(t=-(1+(65535^t))),this.italicAngle=+(t+"."+e)):this.italicAngle=0,this.ascender=Math.round(this.ascender*this.scaleFactor),this.decender=Math.round(this.decender*this.scaleFactor),this.lineGap=Math.round(this.lineGap*this.scaleFactor),this.capHeight=this.os2.exists&&this.os2.capHeight||this.ascender,this.xHeight=this.os2.exists&&this.os2.xHeight||0,this.familyClass=(this.os2.exists&&this.os2.familyClass||0)>>8,this.isSerif=1===(r=this.familyClass)||2===r||3===r||4===r||5===r||7===r,this.isScript=10===this.familyClass,this.flags=0,this.post.isFixedPitch&&(this.flags|=1),this.isSerif&&(this.flags|=2),this.isScript&&(this.flags|=8),0!==this.italicAngle&&(this.flags|=64),this.flags|=32,!this.cmap.unicode)throw new Error("No unicode cmap for font")},i.prototype.characterToGlyph=function(t){var e;return(null!=(e=this.cmap.unicode)?e.codeMap[t]:void 0)||0},i.prototype.widthOfGlyph=function(t){var e;return e=1e3/this.head.unitsPerEm,this.hmtx.forGlyph(t).advance*e},i.prototype.widthOfString=function(t,e,n){var r,i,o,s,a;for(i=s=o=0,a=(t=""+t).length;0<=a?s>>24&255),this.writeByte(t>>16&255),this.writeByte(t>>8&255),this.writeByte(255&t)},t.prototype.readInt32=function(){var t;return 2147483648<=(t=this.readUInt32())?t-4294967296:t},t.prototype.writeInt32=function(t){return t<0&&(t+=4294967296),this.writeUInt32(t)},t.prototype.readUInt16=function(){return this.readByte()<<8|this.readByte()},t.prototype.writeUInt16=function(t){return this.writeByte(t>>8&255),this.writeByte(255&t)},t.prototype.readInt16=function(){var t;return 32768<=(t=this.readUInt16())?t-65536:t},t.prototype.writeInt16=function(t){return t<0&&(t+=65536),this.writeUInt16(t)},t.prototype.readString=function(t){var e,n,r;for(n=[],e=r=0;0<=t?r>24&255),this.writeByte(e>>16&255),this.writeByte(e>>8&255),this.writeByte(255&e),this.writeByte(n>>24&255),this.writeByte(n>>16&255),this.writeByte(n>>8&255),this.writeByte(255&n)},t.prototype.readInt=function(){return this.readInt32()},t.prototype.writeInt=function(t){return this.writeInt32(t)},t.prototype.read=function(t){var e,n;for(e=[],n=0;0<=t?n>8,c[4*u+1]=(16711680&n[u])>>16,c[4*u]=(4278190080&n[u])>>24;return c},e}(),P=function(){function t(t){this.font=t,this.subset={},this.unicodes={},this.next=33}return t.prototype.generateCmap=function(){var t,e,n,r,i;for(e in r=this.font.cmap.tables[0].codeMap,t={},i=this.subset)n=i[e],t[e]=r[n];return t},t.prototype.glyphsFor=function(t){var e,n,r,i,o,s,a;for(r={},o=0,s=t.length;o>"),e.join("\n")},s}()}(rt), +/* + # PNG.js + # Copyright (c) 2011 Devon Govett + # MIT LICENSE + # + # + */ +yt="undefined"!=typeof self&&self||"undefined"!=typeof window&&window||"undefined"!=typeof global&&global||Function('return typeof this === "object" && this.content')()||Function("return this")(),wt=function(){var u,n,r;function i(t){var e,n,r,i,o,s,a,c,u,h,l,f,p,d;for(this.data=t,this.pos=8,this.palette=[],this.imgData=[],this.transparency={},this.animation=null,this.text={},s=null;;){switch(e=this.readUInt32(),u=function(){var t,e;for(e=[],t=0;t<4;++t)e.push(String.fromCharCode(this.data[this.pos++]));return e}.call(this).join("")){case"IHDR":this.width=this.readUInt32(),this.height=this.readUInt32(),this.bits=this.data[this.pos++],this.colorType=this.data[this.pos++],this.compressionMethod=this.data[this.pos++],this.filterMethod=this.data[this.pos++],this.interlaceMethod=this.data[this.pos++];break;case"acTL":this.animation={numFrames:this.readUInt32(),numPlays:this.readUInt32()||1/0,frames:[]};break;case"PLTE":this.palette=this.read(e);break;case"fcTL":s&&this.animation.frames.push(s),this.pos+=4,s={width:this.readUInt32(),height:this.readUInt32(),xOffset:this.readUInt32(),yOffset:this.readUInt32()},o=this.readUInt16(),i=this.readUInt16()||100,s.delay=1e3*o/i,s.disposeOp=this.data[this.pos++],s.blendOp=this.data[this.pos++],s.data=[];break;case"IDAT":case"fdAT":for("fdAT"===u&&(this.pos+=4,e-=4),t=(null!=s?s.data:void 0)||this.imgData,f=0;0<=e?fr)throw new Error("More transparent colors than palette size");if(0<(h=r-this.transparency.indexed.length))for(p=0;0<=h?pthis.data.length)throw new Error("Incomplete or corrupt PNG file")}}i.load=function(t,e,n){var r;return"function"==typeof e&&(n=e),(r=new XMLHttpRequest).open("GET",t,!0),r.responseType="arraybuffer",r.onload=function(){var t;return t=new i(new Uint8Array(r.response||r.mozResponseArrayBuffer)),"function"==typeof(null!=e?e.getContext:void 0)&&t.render(e),"function"==typeof n?n(t):void 0},r.send(null)},i.prototype.read=function(t){var e,n;for(n=[],e=0;0<=t?e + * Chris G Jones + * Shaon Barman + * Vivien Nicolas <21@vingtetun.org> + * Justin D'Arcangelo + * Yury Delendik + * + * + */ +var xt=function(){function t(){this.pos=0,this.bufferLength=0,this.eof=!1,this.buffer=null}return t.prototype={ensureBuffer:function(t){var e=this.buffer,n=e?e.byteLength:0;if(t>t,this.codeSize=n-=t,this.bytesPos=o,e},t.prototype.getCode=function(t){for(var e=t[0],n=t[1],r=this.codeSize,i=this.codeBuf,o=this.bytes,s=this.bytesPos;r>16,h=65535&c;return(0==r||r>u,this.codeSize=r-u,this.bytesPos=s,h},t.prototype.generateHuffmanTable=function(t){for(var e=t.length,n=0,r=0;rn&&(n=t[r]);for(var i=1<>=1;for(r=h;r>=1)){var n,r;if(1==e)n=T,r=O;else if(2==e){for(var i=this.getBits(5)+257,o=this.getBits(5)+1,s=this.getBits(4)+4,a=Array(F.length),c=0;c>16;0>16)&&(y=this.getBits(y));var w=(65535&m)+y;d<=g+h&&(d=(C=this.ensureBuffer(g+h)).length);for(var v=0;v> 18 & 0x3f; + h2 = bits >> 12 & 0x3f; + h3 = bits >> 6 & 0x3f; + h4 = bits & 0x3f; // use hexets to index into b64, and append result to encoded string + + tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); + } while (i < data.length); + + enc = tmp_arr.join(""); + var r = data.length % 3; + return (r ? enc.slice(0, r - 3) : enc) + "===".slice(r || 3); + }; + } + + if (typeof global.atob === "undefined") { + global.atob = function (data) { + // discuss at: http://phpjs.org/functions/base64_decode/ + // original by: Tyler Akins (http://rumkin.com) + // improved by: Thunder.m + // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // input by: Aman Gupta + // input by: Brett Zamir (http://brett-zamir.me) + // bugfixed by: Onno Marsman + // bugfixed by: Pellentesque Malesuada + // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA=='); + // returns 1: 'Kevin van Zonneveld' + var o1, + o2, + o3, + h1, + h2, + h3, + h4, + bits, + i = 0, + ac = 0, + dec = "", + tmp_arr = []; + + if (!data) { + return data; + } + + data += ""; + + do { + // unpack four hexets into three octets using index points in b64 + h1 = b64.indexOf(data.charAt(i++)); + h2 = b64.indexOf(data.charAt(i++)); + h3 = b64.indexOf(data.charAt(i++)); + h4 = b64.indexOf(data.charAt(i++)); + bits = h1 << 18 | h2 << 12 | h3 << 6 | h4; + o1 = bits >> 16 & 0xff; + o2 = bits >> 8 & 0xff; + o3 = bits & 0xff; + + if (h3 == 64) { + tmp_arr[ac++] = String.fromCharCode(o1); + } else if (h4 == 64) { + tmp_arr[ac++] = String.fromCharCode(o1, o2); + } else { + tmp_arr[ac++] = String.fromCharCode(o1, o2, o3); + } + } while (i < data.length); + + dec = tmp_arr.join(""); + return dec; + }; + } + + if (!Array.prototype.map) { + Array.prototype.map = function (fun + /*, thisArg */ + ) { + if (this === void 0 || this === null || typeof fun !== "function") throw new TypeError(); + var t = Object(this), + len = t.length >>> 0, + res = new Array(len); + var thisArg = arguments.length > 1 ? arguments[1] : void 0; + + for (var i = 0; i < len; i++) { + // NOTE: Absolute correctness would demand Object.defineProperty + // be used. But this method is fairly new, and failure is + // possible only if Object.prototype or Array.prototype + // has a property |i| (very unlikely), so use a less-correct + // but more portable alternative. + if (i in t) res[i] = fun.call(thisArg, t[i], i, t); + } + + return res; + }; + } + + if (!Array.isArray) { + Array.isArray = function (arg) { + return Object.prototype.toString.call(arg) === "[object Array]"; + }; + } + + if (!Array.prototype.forEach) { + Array.prototype.forEach = function (fun, thisArg) { + + if (this === void 0 || this === null || typeof fun !== "function") throw new TypeError(); + var t = Object(this), + len = t.length >>> 0; + + for (var i = 0; i < len; i++) { + if (i in t) fun.call(thisArg, t[i], i, t); + } + }; + } + + if (!Object.keys) { + Object.keys = function () { + + var hasOwnProperty = Object.prototype.hasOwnProperty, + hasDontEnumBug = !{ + toString: null + }.propertyIsEnumerable("toString"), + dontEnums = ["toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "constructor"], + dontEnumsLength = dontEnums.length; + return function (obj) { + if (typeof obj !== "object" && (typeof obj !== "function" || obj === null)) { + throw new TypeError(); + } + + var result = [], + prop, + i; + + for (prop in obj) { + if (hasOwnProperty.call(obj, prop)) { + result.push(prop); + } + } + + if (hasDontEnumBug) { + for (i = 0; i < dontEnumsLength; i++) { + if (hasOwnProperty.call(obj, dontEnums[i])) { + result.push(dontEnums[i]); + } + } + } + + return result; + }; + }(); + } + + if (typeof Object.assign != "function") { + Object.assign = function (target) { + + if (target == null) { + throw new TypeError("Cannot convert undefined or null to object"); + } + + target = Object(target); + + for (var index = 1; index < arguments.length; index++) { + var source = arguments[index]; + + if (source != null) { + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + } + + return target; + }; + } + + if (!String.prototype.trim) { + String.prototype.trim = function () { + return this.replace(/^\s+|\s+$/g, ""); + }; + } + + if (!String.prototype.trimLeft) { + String.prototype.trimLeft = function () { + return this.replace(/^\s+/g, ""); + }; + } + + if (!String.prototype.trimRight) { + String.prototype.trimRight = function () { + return this.replace(/\s+$/g, ""); + }; + } + })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")()); // `self` is undefined in Firefox for Android content script context + // while `this` is nsIContentFrameMessageManager + // with an attribute `content` that corresponds to the window + + (function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : factory(); + })(window, function () { + /** + * @this {Promise} + */ + + function finallyConstructor(callback) { + var constructor = this.constructor; + return this.then(function (value) { + return constructor.resolve(callback()).then(function () { + return value; + }); + }, function (reason) { + return constructor.resolve(callback()).then(function () { + return constructor.reject(reason); + }); + }); + } // Store setTimeout reference so promise-polyfill will be unaffected by + // other code modifying setTimeout (like sinon.useFakeTimers()) + + + var setTimeoutFunc = setTimeout; + + function noop() {} // Polyfill for Function.prototype.bind + + + function bind(fn, thisArg) { + return function () { + fn.apply(thisArg, arguments); + }; + } + /** + * @constructor + * @param {Function} fn + */ + + + function Promise(fn) { + if (!(this instanceof Promise)) throw new TypeError('Promises must be constructed via new'); + if (typeof fn !== 'function') throw new TypeError('not a function'); + /** @type {!number} */ + + this._state = 0; + /** @type {!boolean} */ + + this._handled = false; + /** @type {Promise|undefined} */ + + this._value = undefined; + /** @type {!Array} */ + + this._deferreds = []; + doResolve(fn, this); + } + + function handle(self, deferred) { + while (self._state === 3) { + self = self._value; + } + + if (self._state === 0) { + self._deferreds.push(deferred); + + return; + } + + self._handled = true; + + Promise._immediateFn(function () { + var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; + + if (cb === null) { + (self._state === 1 ? resolve : reject)(deferred.promise, self._value); + return; + } + + var ret; + + try { + ret = cb(self._value); + } catch (e) { + reject(deferred.promise, e); + return; + } + + resolve(deferred.promise, ret); + }); + } + + function resolve(self, newValue) { + try { + // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure + if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.'); + + if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { + var then = newValue.then; + + if (newValue instanceof Promise) { + self._state = 3; + self._value = newValue; + finale(self); + return; + } else if (typeof then === 'function') { + doResolve(bind(then, newValue), self); + return; + } + } + + self._state = 1; + self._value = newValue; + finale(self); + } catch (e) { + reject(self, e); + } + } + + function reject(self, newValue) { + self._state = 2; + self._value = newValue; + finale(self); + } + + function finale(self) { + if (self._state === 2 && self._deferreds.length === 0) { + Promise._immediateFn(function () { + if (!self._handled) { + Promise._unhandledRejectionFn(self._value); + } + }); + } + + for (var i = 0, len = self._deferreds.length; i < len; i++) { + handle(self, self._deferreds[i]); + } + + self._deferreds = null; + } + /** + * @constructor + */ + + + function Handler(onFulfilled, onRejected, promise) { + this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; + this.onRejected = typeof onRejected === 'function' ? onRejected : null; + this.promise = promise; + } + /** + * Take a potentially misbehaving resolver function and make sure + * onFulfilled and onRejected are only called once. + * + * Makes no guarantees about asynchrony. + */ + + + function doResolve(fn, self) { + var done = false; + + try { + fn(function (value) { + if (done) return; + done = true; + resolve(self, value); + }, function (reason) { + if (done) return; + done = true; + reject(self, reason); + }); + } catch (ex) { + if (done) return; + done = true; + reject(self, ex); + } + } + + Promise.prototype['catch'] = function (onRejected) { + return this.then(null, onRejected); + }; + + Promise.prototype.then = function (onFulfilled, onRejected) { + // @ts-ignore + var prom = new this.constructor(noop); + handle(this, new Handler(onFulfilled, onRejected, prom)); + return prom; + }; + + Promise.prototype['finally'] = finallyConstructor; + + Promise.all = function (arr) { + return new Promise(function (resolve, reject) { + if (!arr || typeof arr.length === 'undefined') throw new TypeError('Promise.all accepts an array'); + var args = Array.prototype.slice.call(arr); + if (args.length === 0) return resolve([]); + var remaining = args.length; + + function res(i, val) { + try { + if (val && (typeof val === 'object' || typeof val === 'function')) { + var then = val.then; + + if (typeof then === 'function') { + then.call(val, function (val) { + res(i, val); + }, reject); + return; + } + } + + args[i] = val; + + if (--remaining === 0) { + resolve(args); + } + } catch (ex) { + reject(ex); + } + } + + for (var i = 0; i < args.length; i++) { + res(i, args[i]); + } + }); + }; + + Promise.resolve = function (value) { + if (value && typeof value === 'object' && value.constructor === Promise) { + return value; + } + + return new Promise(function (resolve) { + resolve(value); + }); + }; + + Promise.reject = function (value) { + return new Promise(function (resolve, reject) { + reject(value); + }); + }; + + Promise.race = function (values) { + return new Promise(function (resolve, reject) { + for (var i = 0, len = values.length; i < len; i++) { + values[i].then(resolve, reject); + } + }); + }; // Use polyfill for setImmediate for performance gains + + + Promise._immediateFn = typeof setImmediate === 'function' && function (fn) { + setImmediate(fn); + } || function (fn) { + setTimeoutFunc(fn, 0); + }; + + Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) { + if (typeof console !== 'undefined' && console) { + console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console + } + }; + /** @suppress {undefinedVars} */ + + + var globalNS = function () { + // the only reliable means to get the global object is + // `Function('return this')()` + // However, this causes CSP violations in Chrome apps. + if (typeof self !== 'undefined') { + return self; + } + + if (typeof window !== 'undefined') { + return window; + } + + if (typeof global !== 'undefined') { + return global; + } + + throw new Error('unable to locate global object'); + }(); + + if (!('Promise' in globalNS)) { + globalNS['Promise'] = Promise; + } else if (!globalNS.Promise.prototype['finally']) { + globalNS.Promise.prototype['finally'] = finallyConstructor; + } + }); + + function _typeof(obj) { + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); + } + + /** @license + * jsPDF - PDF Document creation from JavaScript + * Version 2.0.0 Built on 2019-01-22T15:32:38.220Z + * CommitID 0110a2202b + * + * Copyright (c) 2015-2018 yWorks GmbH, http://www.yworks.com + * 2015-2018 Lukas Holländer , https://github.com/HackbrettXXX + * 2010-2016 James Hall , https://github.com/MrRio/jsPDF + * 2010 Aaron Spike, https://github.com/acspike + * 2012 Willow Systems Corporation, willow-systems.com + * 2012 Pablo Hess, https://github.com/pablohess + * 2012 Florian Jenett, https://github.com/fjenett + * 2013 Warren Weckesser, https://github.com/warrenweckesser + * 2013 Youssef Beddad, https://github.com/lifof + * 2013 Lee Driscoll, https://github.com/lsdriscoll + * 2013 Stefan Slonevskiy, https://github.com/stefslon + * 2013 Jeremy Morel, https://github.com/jmorel + * 2013 Christoph Hartmann, https://github.com/chris-rock + * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria + * 2014 James Makes, https://github.com/dollaruw + * 2014 Diego Casorran, https://github.com/diegocr + * 2014 Steven Spungin, https://github.com/Flamenco + * 2014 Kenneth Glassey, https://github.com/Gavvers + * + * Licensed under the MIT License + * + * Contributor(s): + * siefkenj, ahwolf, rickygu, Midnith, saintclair, eaparango, + * kim3er, mfo, alnorth, Flamenco + */ + + /** + * Creates new jsPDF document object instance. + * @name jsPDF + * @class + * @param orientation {string/Object} Orientation of the first page. Possible values are "portrait" or "landscape" (or shortcuts "p" (Default), "l")
+ * Can also be an options object. + * @param unit {string} Measurement unit to be used when coordinates are specified.
+ * Possible values are "pt" (points), "mm" (Default), "cm", "in" or "px". + * @param format {string/Array} The format of the first page. Can be
  • a0 - a10
  • b0 - b10
  • c0 - c10
  • c0 - c10
  • dl
  • letter
  • government-letter
  • legal
  • junior-legal
  • ledger
  • tabloid
  • credit-card

+ * Default is "a4". If you want to use your own format just pass instead of one of the above predefined formats the size as an number-array , e.g. [595.28, 841.89] + * @returns {jsPDF} jsPDF-instance + * @description + * If the first parameter (orientation) is an object, it will be interpreted as an object of named parameters + * ``` + * { + * orientation: 'p', + * unit: 'mm', + * format: 'a4', + * hotfixes: [] // an array of hotfix strings to enable + * } + * ``` + */ + var jsPDF = function (global) { + + var pdfVersion = "1.3", + pageFormats = { + // Size in pt of various paper formats + a0: [2383.94, 3370.39], + a1: [1683.78, 2383.94], + a2: [1190.55, 1683.78], + a3: [841.89, 1190.55], + a4: [595.28, 841.89], + a5: [419.53, 595.28], + a6: [297.64, 419.53], + a7: [209.76, 297.64], + a8: [147.4, 209.76], + a9: [104.88, 147.4], + a10: [73.7, 104.88], + b0: [2834.65, 4008.19], + b1: [2004.09, 2834.65], + b2: [1417.32, 2004.09], + b3: [1000.63, 1417.32], + b4: [708.66, 1000.63], + b5: [498.9, 708.66], + b6: [354.33, 498.9], + b7: [249.45, 354.33], + b8: [175.75, 249.45], + b9: [124.72, 175.75], + b10: [87.87, 124.72], + c0: [2599.37, 3676.54], + c1: [1836.85, 2599.37], + c2: [1298.27, 1836.85], + c3: [918.43, 1298.27], + c4: [649.13, 918.43], + c5: [459.21, 649.13], + c6: [323.15, 459.21], + c7: [229.61, 323.15], + c8: [161.57, 229.61], + c9: [113.39, 161.57], + c10: [79.37, 113.39], + dl: [311.81, 623.62], + letter: [612, 792], + "government-letter": [576, 756], + legal: [612, 1008], + "junior-legal": [576, 360], + ledger: [1224, 792], + tabloid: [792, 1224], + "credit-card": [153, 243] + }; + /** + * jsPDF's Internal PubSub Implementation. + * Backward compatible rewritten on 2014 by + * Diego Casorran, https://github.com/diegocr + * + * @class + * @name PubSub + * @ignore + */ + + function PubSub(context) { + var topics = {}; + + this.subscribe = function (topic, callback, once) { + if (typeof callback !== "function") { + return false; + } + + if (!topics.hasOwnProperty(topic)) { + topics[topic] = {}; + } + + var id = Math.random().toString(35); + topics[topic][id] = [callback, !!once]; + return id; + }; + + this.unsubscribe = function (token) { + for (var topic in topics) { + if (topics[topic][token]) { + delete topics[topic][token]; + return true; + } + } + + return false; + }; + + this.publish = function (topic) { + if (topics.hasOwnProperty(topic)) { + var args = Array.prototype.slice.call(arguments, 1), + idr = []; + + for (var id in topics[topic]) { + var sub = topics[topic][id]; + + try { + sub[0].apply(context, args); + } catch (ex) { + if (global.console) { + console.error("jsPDF PubSub Error", ex.message, ex); + } + } + + if (sub[1]) idr.push(id); + } + + if (idr.length) idr.forEach(this.unsubscribe); + } + }; + } + /** + * @constructor + * @private + */ + + + function jsPDF(orientation, unit, format, compressPdf) { + var options = {}; + + if (_typeof(orientation) === "object") { + options = orientation; + orientation = options.orientation; + unit = options.unit || unit; + format = options.format || format; + compressPdf = options.compress || options.compressPdf || compressPdf; + } // Default options + + + unit = unit || "mm"; + format = format || "a4"; + orientation = ("" + (orientation || "P")).toLowerCase(); + + var format_as_string = ("" + format).toLowerCase(), + compress = !!compressPdf && typeof Uint8Array === "function", + textColor = options.textColor || "0 g", + drawColor = options.drawColor || "0 G", + activeFontSize = options.fontSize || 16, + activeCharSpace = options.charSpace || 0, + R2L = options.R2L || false, + lineHeightProportion = options.lineHeight || 1.15, + lineWidth = options.lineWidth || 0.200025, + // 2mm + fileId = "00000000000000000000000000000000", + objectNumber = 2, + // 'n' Current object number + outToPages = !1, + // switches where out() prints. outToPages true = push to pages obj. outToPages false = doc builder content + offsets = [], + // List of offsets. Activated and reset by buildDocument(). Pupulated by various calls buildDocument makes. + fonts = {}, + // collection of font objects, where key is fontKey - a dynamically created label for a given font. + fontmap = {}, + // mapping structure fontName > fontStyle > font key - performance layer. See addFont() + activeFontKey, + // will be string representing the KEY of the font as combination of fontName + fontStyle + fontStateStack = [], + // + patterns = {}, + // collection of pattern objects + patternMap = {}, + // see fonts + gStates = {}, + // collection of graphic state objects + gStatesMap = {}, + // see fonts + activeGState = null, + k, + // Scale factor + tmp, + page = 0, + currentPage, + pages = [], + pagesContext = [], + // same index as pages and pagedim + pagedim = [], + content = [], + additionalObjects = [], + lineCapID = 0, + lineJoinID = 0, + content_length = 0, + renderTargets = {}, + renderTargetMap = {}, + renderTargetStack = [], + pageX, + pageY, + pageMatrix, + // only used for FormObjects + pageWidth, + pageHeight, + pageMode, + zoomMode, + layoutMode, + creationDate, + documentProperties = { + title: "", + subject: "", + author: "", + keywords: "", + creator: "" + }, + API = {}, + ApiMode = { + COMPAT: "compat", + ADVANCED: "advanced" + }, + apiMode = ApiMode.COMPAT, + events = new PubSub(API), + hotfixes = options.hotfixes || [], + ///////////////////// + // Private functions + ///////////////////// + generateColorString = function generateColorString(options) { + var color; + var ch1 = options.ch1; + var ch2 = options.ch2; + var ch3 = options.ch3; + var ch4 = options.ch4; + var precision = options.precision; + var letterArray = options.pdfColorType === "draw" ? ["G", "RG", "K"] : ["g", "rg", "k"]; + + if (typeof ch1 === "string" && ch1.charAt(0) !== "#") { + var rgbColor = new RGBColor(ch1); + + if (rgbColor.ok) { + ch1 = rgbColor.toHex(); + } + } //convert short rgb to long form + + + if (typeof ch1 === "string" && /^#[0-9A-Fa-f]{3}$/.test(ch1)) { + ch1 = "#" + ch1[1] + ch1[1] + ch1[2] + ch1[2] + ch1[3] + ch1[3]; + } + + if (typeof ch1 === "string" && /^#[0-9A-Fa-f]{6}$/.test(ch1)) { + var hex = parseInt(ch1.substr(1), 16); + ch1 = hex >> 16 & 255; + ch2 = hex >> 8 & 255; + ch3 = hex & 255; + } + + if (typeof ch2 === "undefined" || typeof ch4 === "undefined" && ch1 === ch2 && ch2 === ch3) { + // Gray color space. + if (typeof ch1 === "string") { + color = ch1 + " " + letterArray[0]; + } else { + switch (options.precision) { + case 2: + color = f2(ch1 / 255) + " " + letterArray[0]; + break; + + case 3: + default: + color = f3(ch1 / 255) + " " + letterArray[0]; + } + } + } else if (typeof ch4 === "undefined" || _typeof(ch4) === "object") { + // assume RGB + if (typeof ch1 === "string") { + color = [ch1, ch2, ch3, letterArray[1]].join(" "); + } else { + switch (options.precision) { + case 2: + color = [f2(ch1 / 255), f2(ch2 / 255), f2(ch3 / 255), letterArray[1]].join(" "); + break; + + default: + case 3: + color = [f3(ch1 / 255), f3(ch2 / 255), f3(ch3 / 255), letterArray[1]].join(" "); + } + } // assume RGBA + + + if (ch4 && ch4.a === 0) { + //TODO Implement transparency. + //WORKAROUND use white for now + color = ["255", "255", "255", letterArray[1]].join(" "); + } + } else { + // assume CMYK + if (typeof ch1 === "string") { + color = [ch1, ch2, ch3, ch4, letterArray[2]].join(" "); + } else { + switch (options.precision) { + case 2: + color = [f2(ch1), f2(ch2), f2(ch3), f2(ch4), letterArray[2]].join(" "); + break; + + case 3: + default: + color = [f3(ch1), f3(ch2), f3(ch3), f3(ch4), letterArray[2]].join(" "); + } + } + } + + return color; + }, + convertDateToPDFDate = function convertDateToPDFDate(parmDate) { + var padd2 = function padd2(number) { + return ("0" + parseInt(number)).slice(-2); + }; + + var result = ""; + var tzoffset = parmDate.getTimezoneOffset(), + tzsign = tzoffset < 0 ? "+" : "-", + tzhour = Math.floor(Math.abs(tzoffset / 60)), + tzmin = Math.abs(tzoffset % 60), + timeZoneString = [tzsign, padd2(tzhour), "'", padd2(tzmin), "'"].join(""); + result = ["D:", parmDate.getFullYear(), padd2(parmDate.getMonth() + 1), padd2(parmDate.getDate()), padd2(parmDate.getHours()), padd2(parmDate.getMinutes()), padd2(parmDate.getSeconds()), timeZoneString].join(""); + return result; + }, + convertPDFDateToDate = function convertPDFDateToDate(parmPDFDate) { + var year = parseInt(parmPDFDate.substr(2, 4), 10); + var month = parseInt(parmPDFDate.substr(6, 2), 10) - 1; + var date = parseInt(parmPDFDate.substr(8, 2), 10); + var hour = parseInt(parmPDFDate.substr(10, 2), 10); + var minutes = parseInt(parmPDFDate.substr(12, 2), 10); + var seconds = parseInt(parmPDFDate.substr(14, 2), 10); + var timeZoneHour = parseInt(parmPDFDate.substr(16, 2), 10); + var timeZoneMinutes = parseInt(parmPDFDate.substr(20, 2), 10); + var resultingDate = new Date(year, month, date, hour, minutes, seconds, 0); + return resultingDate; + }, + setCreationDate = function setCreationDate(date) { + var tmpCreationDateString; + var regexPDFCreationDate = /^D:(20[0-2][0-9]|203[0-7]|19[7-9][0-9])(0[0-9]|1[0-2])([0-2][0-9]|3[0-1])(0[0-9]|1[0-9]|2[0-3])(0[0-9]|[1-5][0-9])(0[0-9]|[1-5][0-9])(\+0[0-9]|\+1[0-4]|\-0[0-9]|\-1[0-1])\'(0[0-9]|[1-5][0-9])\'?$/; + + if (_typeof(date) === undefined) { + date = new Date(); + } + + if (_typeof(date) === "object" && Object.prototype.toString.call(date) === "[object Date]") { + tmpCreationDateString = convertDateToPDFDate(date); + } else if (regexPDFCreationDate.test(date)) { + tmpCreationDateString = date; + } else { + tmpCreationDateString = convertDateToPDFDate(new Date()); + } + + creationDate = tmpCreationDateString; + return creationDate; + }, + getCreationDate = function getCreationDate(type) { + var result = creationDate; + + if (type === "jsDate") { + result = convertPDFDateToDate(creationDate); + } + + return result; + }, + setFileId = function setFileId(value) { + value = value || "12345678901234567890123456789012".split("").map(function () { + return "ABCDEF0123456789".charAt(Math.floor(Math.random() * 16)); + }).join(""); + fileId = value; + return fileId; + }, + getFileId = function getFileId() { + return fileId; + }, + f2 = function f2(number) { + return number.toFixed(2); // Ie, %.2f + }, + f3 = function f3(number) { + return number.toFixed(3); // Ie, %.3f + }, + // high precision float + hpf = function hpf(number) { + return number.toFixed(16).replace(/0+$/, ""); + }, + scaleByK = function scaleByK(coordinate) { + if (apiMode === ApiMode.COMPAT) { + return coordinate * k; + } else if (apiMode === ApiMode.ADVANCED) { + return coordinate; + } + }, + transformY = function transformY(y) { + if (apiMode === ApiMode.COMPAT) { + return pageHeight - y; + } else if (apiMode === ApiMode.ADVANCED) { + return y; + } + }, + transformScaleY = function transformScaleY(y) { + return scaleByK(transformY(y)); + }, + padd2Hex = function padd2Hex(hexString) { + var s = "00" + hexString; + return s.substr(s.length - 2); + }, + advancedApiModeTrap = function advancedApiModeTrap(methodName) { + if (apiMode !== ApiMode.ADVANCED) { + throw new Error(methodName + " is only available in 'advanced' API mode. " + "You need to call advancedAPI() first."); + } + }, + out = function out(string) { + string = typeof string === "string" ? string : string.toString(); + + if (outToPages) { + /* set by beginPage */ + pages[currentPage].push(string); + } else { + // +1 for '\n' that will be used to join 'content' + content_length += string.length + 1; + content.push(string); + } + }, + newObject = function newObject() { + // Begin a new object + objectNumber++; + offsets[objectNumber] = content_length; + out(objectNumber + " 0 obj"); + return objectNumber; + }, + // Does not output the object until after the pages have been output. + // Returns an object containing the objectId and content. + // All pages have been added so the object ID can be estimated to start right after. + // This does not modify the current objectNumber; It must be updated after the newObjects are output. + newAdditionalObject = function newAdditionalObject() { + var objId = pages.length * 2 + 1; + objId += additionalObjects.length; + var obj = { + objId: objId, + content: "" + }; + additionalObjects.push(obj); + return obj; + }, + // Does not output the object. The caller must call newObjectDeferredBegin(oid) before outputing any data + newObjectDeferred = function newObjectDeferred() { + objectNumber++; + + offsets[objectNumber] = function () { + return content_length; + }; + + return objectNumber; + }, + newObjectDeferredBegin = function newObjectDeferredBegin(oid) { + offsets[oid] = content_length; + }, + putStream = function putStream(str) { + out("stream"); + out(str); + out("endstream"); + }, + appendBuffer = function appendBuffer(buffer1, buffer2) { + var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength); + tmp.set(new Uint8Array(buffer1), 0); + tmp.set(new Uint8Array(buffer2), buffer1.byteLength); + return tmp; + }, + putPages = function putPages() { + var n, + p, + arr, + i, + deflater, + adler32, + adler32cs, + wPt, + hPt, + pageObjectNumbers = []; + adler32cs = global.adler32cs || jsPDF.API.adler32cs; + + if (compress && typeof adler32cs === "undefined") { + compress = false; + } // outToPages = false as set in endDocument(). out() writes to content. + + + for (n = 1; n <= page; n++) { + pageObjectNumbers.push(newObject()); + wPt = (pageWidth = pagedim[n].width) * k; + hPt = (pageHeight = pagedim[n].height) * k; + out("<>"); + out("endobj"); // Page content + + p = pages[n].join("\n"); + + if (apiMode === ApiMode.ADVANCED) { + // if the user forgot to switch back to COMPAT mode, we must balance the graphics stack again + p += "\nQ"; + } + + newObject(); + + if (compress) { + arr = []; + i = p.length; + + while (i--) { + arr[i] = p.charCodeAt(i); + } + + adler32 = adler32cs.from(p); + deflater = new Deflater(6); + p = deflater.append(new Uint8Array(arr)); + p = appendBuffer(p, deflater.flush()); + arr = new Uint8Array(p.byteLength + 6); + arr.set(new Uint8Array([120, 156])); + arr.set(p, 2); + arr.set(new Uint8Array([adler32 & 0xff, adler32 >> 8 & 0xff, adler32 >> 16 & 0xff, adler32 >> 24 & 0xff]), p.byteLength + 2); + var strings = [], + chunkSize = 0xffff; // There is a maximum stack size. We cannot call String.fromCharCode with as many arguments as we want + + for (var j = 0; j * chunkSize < arr.length; j++) { + strings.push(String.fromCharCode.apply(null, arr.subarray(j * chunkSize, (j + 1) * chunkSize))); + } + + p = strings.join(''); + out("<>"); + } else { + out("<>"); + } + + putStream(p); + out("endobj"); + } + + offsets[1] = content_length; + out("1 0 obj"); + out("<>"); + out("endobj"); + events.publish("postPutPages"); + }, + putFont = function putFont(font) { + events.publish("putFont", { + font: font, + out: out, + newObject: newObject, + putStream: putStream + }); + + if (font.isAlreadyPutted !== true) { + font.objectNumber = newObject(); + out("<<"); + out("/Type /Font"); + out("/BaseFont /" + font.postScriptName); + out("/Subtype /Type1"); + + if (typeof font.encoding === "string") { + out("/Encoding /" + font.encoding); + } + + out("/FirstChar 32"); + out("/LastChar 255"); + out(">>"); + out("endobj"); + } + }, + putFonts = function putFonts() { + for (var fontKey in fonts) { + if (fonts.hasOwnProperty(fontKey)) { + putFont(fonts[fontKey]); + } + } + }, + putXObject = function putXObject(xObject) { + xObject.objectNumber = newObject(); + out("<<"); + out("/Type /XObject"); + out("/Subtype /Form"); + out("/BBox [" + [hpf(xObject.x), hpf(xObject.y), hpf(xObject.x + xObject.width), hpf(xObject.y + xObject.height)].join(" ") + "]"); + out("/Matrix [" + xObject.matrix.toString() + "]"); // TODO: /Resources + + var p = xObject.pages[1].join("\n"); + out("/Length " + p.length); + out(">>"); + putStream(p); + out("endobj"); + }, + putXObjects = function putXObjects() { + for (var xObjectKey in renderTargets) { + if (renderTargets.hasOwnProperty(xObjectKey)) { + putXObject(renderTargets[xObjectKey]); + } + } + }, + interpolateAndEncodeRGBStream = function interpolateAndEncodeRGBStream(colors, numberSamples) { + var tValues = []; + var t; + var dT = 1.0 / (numberSamples - 1); + + for (t = 0.0; t < 1.0; t += dT) { + tValues.push(t); + } + + tValues.push(1.0); // add first and last control point if not present + + if (colors[0].offset != 0.0) { + var c0 = { + offset: 0.0, + color: colors[0].color + }; + colors.unshift(c0); + } + + if (colors[colors.length - 1].offset != 1.0) { + var c1 = { + offset: 1.0, + color: colors[colors.length - 1].color + }; + colors.push(c1); + } + + var out = ""; + var index = 0; + + for (var i = 0; i < tValues.length; i++) { + t = tValues[i]; + + while (t > colors[index + 1].offset) { + index++; + } + + var a = colors[index].offset; + var b = colors[index + 1].offset; + var d = (t - a) / (b - a); + var aColor = colors[index].color; + var bColor = colors[index + 1].color; + out += padd2Hex(Math.round((1 - d) * aColor[0] + d * bColor[0]).toString(16)) + padd2Hex(Math.round((1 - d) * aColor[1] + d * bColor[1]).toString(16)) + padd2Hex(Math.round((1 - d) * aColor[2] + d * bColor[2]).toString(16)); + } + + return out.trim(); + }, + putShadingPattern = function putShadingPattern(pattern, numberSamples) { + /* + Axial patterns shade between the two points specified in coords, radial patterns between the inner + and outer circle. + The user can specify an array (colors) that maps t-Values in [0, 1] to RGB colors. These are now + interpolated to equidistant samples and written to pdf as a sample (type 0) function. + */ + // The number of color samples that should be used to describe the shading. + // The higher, the more accurate the gradient will be. + numberSamples || (numberSamples = 21); + var funcObjectNumber = newObject(); + var stream = interpolateAndEncodeRGBStream(pattern.colors, numberSamples); + out("<< /FunctionType 0"); + out("/Domain [0.0 1.0]"); + out("/Size [" + numberSamples + "]"); + out("/BitsPerSample 8"); + out("/Range [0.0 1.0 0.0 1.0 0.0 1.0]"); + out("/Decode [0.0 1.0 0.0 1.0 0.0 1.0]"); + out("/Length " + stream.length); // The stream is Hex encoded + + out("/Filter /ASCIIHexDecode"); + out(">>"); + putStream(stream); + out("endobj"); + pattern.objectNumber = newObject(); + out("<< /ShadingType " + pattern.type); + out("/ColorSpace /DeviceRGB"); + var coords = "/Coords [" + hpf(parseFloat(pattern.coords[0])) + " " + // x1 + hpf(parseFloat(pattern.coords[1])) + " "; // y1 + + if (pattern.type === 2) { + // axial + coords += hpf(parseFloat(pattern.coords[2])) + " " + // x2 + hpf(parseFloat(pattern.coords[3])); // y2 + } else { + // radial + coords += hpf(parseFloat(pattern.coords[2])) + " " + // r1 + hpf(parseFloat(pattern.coords[3])) + " " + // x2 + hpf(parseFloat(pattern.coords[4])) + " " + // y2 + hpf(parseFloat(pattern.coords[5])); // r2 + } + + coords += "]"; + out(coords); + + if (pattern.matrix) { + out("/Matrix [" + pattern.matrix.toString() + "]"); + } + + out("/Function " + funcObjectNumber + " 0 R"); + out("/Extend [true true]"); + out(">>"); + out("endobj"); + }, + putTilingPattern = function putTilingPattern(pattern) { + var resourcesObjectNumber = newObject(); + out("<<"); + putResourceDictionary(); + out(">>"); + out("endobj"); + pattern.objectNumber = newObject(); + out("<< /Type /Pattern"); + out("/PatternType 1"); // tiling pattern + + out("/PaintType 1"); // colored tiling pattern + + out("/TilingType 1"); // constant spacing + + out("/BBox [" + pattern.boundingBox.map(hpf).join(" ") + "]"); + out("/XStep " + hpf(pattern.xStep)); + out("/YStep " + hpf(pattern.yStep)); + out("/Length " + pattern.stream.length); + out("/Resources " + resourcesObjectNumber + " 0 R"); // TODO: resources + + pattern.matrix && out("/Matrix [" + pattern.matrix.toString() + "]"); + out(">>"); + putStream(pattern.stream); + out("endobj"); + }, + putPatterns = function putPatterns() { + var patternKey; + + for (patternKey in patterns) { + if (patterns.hasOwnProperty(patternKey)) { + if (patterns[patternKey] instanceof API.ShadingPattern) { + putShadingPattern(patterns[patternKey]); + } else if (patterns[patternKey] instanceof API.TilingPattern) { + putTilingPattern(patterns[patternKey]); + } + } + } + }, + putGState = function putGState(gState) { + gState.objectNumber = newObject(); + out("<<"); + + for (var p in gState) { + switch (p) { + case "opacity": + out("/ca " + f2(gState[p])); + break; + + case "stroke-opacity": + out("/CA " + f2(gState[p])); + break; + } + } + + out(">>"); + out("endobj"); + }, + putGStates = function putGStates() { + var gStateKey; + + for (gStateKey in gStates) { + if (gStates.hasOwnProperty(gStateKey)) { + putGState(gStates[gStateKey]); + } + } + }, + putXobjectDict = function putXobjectDict() { + for (var xObjectKey in renderTargets) { + if (renderTargets.hasOwnProperty(xObjectKey) && renderTargets[xObjectKey].objectNumber >= 0) { + out("/" + xObjectKey + " " + renderTargets[xObjectKey].objectNumber + " 0 R"); + } + } + + events.publish("putXobjectDict"); + }, + putShadingPatternDict = function putShadingPatternDict() { + for (var patternKey in patterns) { + if (patterns.hasOwnProperty(patternKey) && patterns[patternKey] instanceof API.ShadingPattern && patterns[patternKey].objectNumber >= 0) { + out("/" + patternKey + " " + patterns[patternKey].objectNumber + " 0 R"); + } + } + + events.publish("putShadingPatternDict"); + }, + putTilingPatternDict = function putTilingPatternDict() { + for (var patternKey in patterns) { + if (patterns.hasOwnProperty(patternKey) && patterns[patternKey] instanceof API.TilingPattern && patterns[patternKey].objectNumber >= 0) { + out("/" + patternKey + " " + patterns[patternKey].objectNumber + " 0 R"); + } + } + + events.publish("putTilingPatternDict"); + }, + putGStatesDict = function putGStatesDict() { + var gStateKey; + + for (gStateKey in gStates) { + if (gStates.hasOwnProperty(gStateKey) && gStates[gStateKey].objectNumber >= 0) { + out("/" + gStateKey + " " + gStates[gStateKey].objectNumber + " 0 R"); + } + } + + events.publish("putGStateDict"); + }, + putResourceDictionary = function putResourceDictionary() { + out("/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]"); + out("/Font <<"); // Do this for each font, the '1' bit is the index of the font + + for (var fontKey in fonts) { + if (fonts.hasOwnProperty(fontKey)) { + out("/" + fontKey + " " + fonts[fontKey].objectNumber + " 0 R"); + } + } + + out(">>"); + out("/Shading <<"); + putShadingPatternDict(); + out(">>"); + out("/Pattern <<"); + putTilingPatternDict(); + out(">>"); + out("/ExtGState <<"); + putGStatesDict(); + out(">>"); + out("/XObject <<"); + putXobjectDict(); + out(">>"); + }, + putResources = function putResources() { + putFonts(); + putGStates(); + putXObjects(); + putPatterns(); + events.publish("putResources"); // Resource dictionary + + offsets[2] = content_length; + out("2 0 obj"); + out("<<"); + putResourceDictionary(); + out(">>"); + out("endobj"); + events.publish("postPutResources"); + }, + putAdditionalObjects = function putAdditionalObjects() { + events.publish("putAdditionalObjects"); + + for (var i = 0; i < additionalObjects.length; i++) { + var obj = additionalObjects[i]; + offsets[obj.objId] = content_length; + out(obj.objId + " 0 obj"); + out(obj.content); + out("endobj"); + } + + objectNumber += additionalObjects.length; + events.publish("postPutAdditionalObjects"); + }, + addToFontDictionary = function addToFontDictionary(fontKey, fontName, fontStyle) { + // this is mapping structure for quick font key lookup. + // returns the KEY of the font (ex: "F1") for a given + // pair of font name and type (ex: "Arial". "Italic") + if (!fontmap.hasOwnProperty(fontName)) { + fontmap[fontName] = {}; + } + + fontmap[fontName][fontStyle] = fontKey; + }, + addFont = function addFont(postScriptName, fontName, fontStyle, encoding, isStandardFont) { + isStandardFont = isStandardFont || false; + var fontKey = "F" + (Object.keys(fonts).length + 1).toString(10), + // This is FontObject + font = { + id: fontKey, + postScriptName: postScriptName, + fontName: fontName, + fontStyle: fontStyle, + encoding: encoding, + isStandardFont: isStandardFont, + metadata: {} + }; + var instance = this; + events.publish("addFont", { + font: font, + instance: instance + }); + + if (fontKey !== undefined) { + fonts[fontKey] = font; + addToFontDictionary(fontKey, fontName, fontStyle); + } + + return fontKey; + }, + addFonts = function addFonts() { + var HELVETICA = "helvetica", + TIMES = "times", + COURIER = "courier", + NORMAL = "normal", + BOLD = "bold", + ITALIC = "italic", + BOLD_ITALIC = "bolditalic", + ZAPF = "zapfdingbats", + SYMBOL = "symbol", + standardFonts = [["Helvetica", HELVETICA, NORMAL, "WinAnsiEncoding"], ["Helvetica-Bold", HELVETICA, BOLD, "WinAnsiEncoding"], ["Helvetica-Oblique", HELVETICA, ITALIC, "WinAnsiEncoding"], ["Helvetica-BoldOblique", HELVETICA, BOLD_ITALIC, "WinAnsiEncoding"], ["Courier", COURIER, NORMAL, "WinAnsiEncoding"], ["Courier-Bold", COURIER, BOLD, "WinAnsiEncoding"], ["Courier-Oblique", COURIER, ITALIC, "WinAnsiEncoding"], ["Courier-BoldOblique", COURIER, BOLD_ITALIC, "WinAnsiEncoding"], ["Times-Roman", TIMES, NORMAL, "WinAnsiEncoding"], ["Times-Bold", TIMES, BOLD, "WinAnsiEncoding"], ["Times-Italic", TIMES, ITALIC, "WinAnsiEncoding"], ["Times-BoldItalic", TIMES, BOLD_ITALIC, "WinAnsiEncoding"], ["ZapfDingbats", ZAPF, NORMAL, null], ["Symbol", SYMBOL, NORMAL, null]]; + + for (var i = 0, l = standardFonts.length; i < l; i++) { + var fontKey = addFont(standardFonts[i][0], standardFonts[i][1], standardFonts[i][2], standardFonts[i][3], true); // adding aliases for standard fonts, this time matching the capitalization + + var parts = standardFonts[i][0].split("-"); + addToFontDictionary(fontKey, parts[0], parts[1] || ""); + } + + events.publish("addFonts", { + fonts: fonts, + dictionary: fontmap + }); + }, + matrixMult = function matrixMult(m1, m2) { + return new Matrix(m1.a * m2.a + m1.b * m2.c, m1.a * m2.b + m1.b * m2.d, m1.c * m2.a + m1.d * m2.c, m1.c * m2.b + m1.d * m2.d, m1.e * m2.a + m1.f * m2.c + m2.e, m1.e * m2.b + m1.f * m2.d + m2.f); + }, + Matrix = function Matrix(a, b, c, d, e, f) { + this.a = a; + this.b = b; + this.c = c; + this.d = d; + this.e = e; + this.f = f; + }; + + Matrix.prototype = { + toString: function toString() { + return [hpf(this.a), hpf(this.b), hpf(this.c), hpf(this.d), hpf(this.e), hpf(this.f)].join(" "); + }, + inversed: function inversed() { + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + var quot = 1 / (a * d - b * c); + var aInv = d * quot; + var bInv = -b * quot; + var cInv = -c * quot; + var dInv = a * quot; + var eInv = -aInv * e - cInv * f; + var fInv = -bInv * e - dInv * f; + return new Matrix(aInv, bInv, cInv, dInv, eInv, fInv); + } + }; + + var unitMatrix = new Matrix(1, 0, 0, 1, 0, 0), + // Used (1) to save the current stream state to the XObjects stack and (2) to save completed form + // objects in the xObjects map. + RenderTarget = function RenderTarget() { + this.page = page; + this.currentPage = currentPage; + this.pages = pages.slice(0); + this.pagedim = pagedim.slice(0); + this.pagesContext = pagesContext.slice(0); + this.x = pageX; + this.y = pageY; + this.matrix = pageMatrix; + this.width = pageWidth; + this.height = pageHeight; + this.id = ""; // set by endFormObject() + + this.objectNumber = -1; // will be set by putXObject() + }; + + RenderTarget.prototype = { + restore: function restore() { + page = this.page; + currentPage = this.currentPage; + pagesContext = this.pagesContext; + pagedim = this.pagedim; + pages = this.pages; + pageX = this.x; + pageY = this.y; + pageMatrix = this.matrix; + pageWidth = this.width; + pageHeight = this.height; + } + }; + + var beginNewRenderTarget = function beginNewRenderTarget(x, y, width, height, matrix) { + // save current state + renderTargetStack.push(new RenderTarget()); // clear pages + + page = currentPage = 0; + pages = []; + pageX = x; + pageY = y; + pageMatrix = matrix; + beginPage(width, height); + }, + endFormObject = function endFormObject(key) { + // only add it if it is not already present (the keys provided by the user must be unique!) + if (renderTargetMap[key]) return; // save the created xObject + + var newXObject = new RenderTarget(); + var xObjectId = "Xo" + (Object.keys(renderTargets).length + 1).toString(10); + newXObject.id = xObjectId; + renderTargetMap[key] = xObjectId; + renderTargets[xObjectId] = newXObject; + events.publish("addFormObject", newXObject); // restore state from stack + + renderTargetStack.pop().restore(); + }, + + /** + * Adds a new pattern for later use. + * @param {String} key The key by it can be referenced later. The keys must be unique! + * @param {API.Pattern} pattern The pattern + */ + addPattern = function addPattern(key, pattern) { + // only add it if it is not already present (the keys provided by the user must be unique!) + if (patternMap[key]) return; + var prefix = pattern instanceof API.ShadingPattern ? "Sh" : "P"; + var patternKey = prefix + (Object.keys(patterns).length + 1).toString(10); + pattern.id = patternKey; + patternMap[key] = patternKey; + patterns[patternKey] = pattern; + events.publish("addPattern", pattern); + }, + + /** + * Adds a new Graphics State. Duplicates are automatically eliminated. + * @param {String} key Might also be null, if no later reference to this gState is needed + * @param {Object} gState The gState object + */ + addGState = function addGState(key, gState) { + // only add it if it is not already present (the keys provided by the user must be unique!) + if (key && gStatesMap[key]) return; + var duplicate = false; + + for (var s in gStates) { + if (gStates.hasOwnProperty(s)) { + if (gStates[s].equals(gState)) { + duplicate = true; + break; + } + } + } + + if (duplicate) { + gState = gStates[s]; + } else { + var gStateKey = "GS" + (Object.keys(gStates).length + 1).toString(10); + gStates[gStateKey] = gState; + gState.id = gStateKey; + } // several user keys may point to the same GState object + + + key && (gStatesMap[key] = gState.id); + events.publish("addGState", gState); + return gState; + }, + SAFE = function __safeCall(fn) { + fn.foo = function __safeCallWrapper() { + try { + return fn.apply(this, arguments); + } catch (e) { + var stack = e.stack || ""; + if (~stack.indexOf(" at ")) stack = stack.split(" at ")[1]; + var m = "Error in function " + stack.split("\n")[0].split("<")[0] + ": " + e.message; + + if (global.console) { + global.console.error(m, e); + if (global.alert) alert(m); + } else { + throw new Error(m); + } + } + }; + + fn.foo.bar = fn; + return fn.foo; + }, + to8bitStream = function to8bitStream(text, flags) { + /** + * PDF 1.3 spec: + * "For text strings encoded in Unicode, the first two bytes must be 254 followed by + * 255, representing the Unicode byte order marker, U+FEFF. (This sequence conflicts + * with the PDFDocEncoding character sequence thorn ydieresis, which is unlikely + * to be a meaningful beginning of a word or phrase.) The remainder of the + * string consists of Unicode character codes, according to the UTF-16 encoding + * specified in the Unicode standard, version 2.0. Commonly used Unicode values + * are represented as 2 bytes per character, with the high-order byte appearing first + * in the string." + * + * In other words, if there are chars in a string with char code above 255, we + * recode the string to UCS2 BE - string doubles in length and BOM is prepended. + * + * HOWEVER! + * Actual *content* (body) text (as opposed to strings used in document properties etc) + * does NOT expect BOM. There, it is treated as a literal GID (Glyph ID) + * + * Because of Adobe's focus on "you subset your fonts!" you are not supposed to have + * a font that maps directly Unicode (UCS2 / UTF16BE) code to font GID, but you could + * fudge it with "Identity-H" encoding and custom CIDtoGID map that mimics Unicode + * code page. There, however, all characters in the stream are treated as GIDs, + * including BOM, which is the reason we need to skip BOM in content text (i.e. that + * that is tied to a font). + * + * To signal this "special" PDFEscape / to8bitStream handling mode, + * API.text() function sets (unless you overwrite it with manual values + * given to API.text(.., flags) ) + * flags.autoencode = true + * flags.noBOM = true + * + * =================================================================================== + * `flags` properties relied upon: + * .sourceEncoding = string with encoding label. + * "Unicode" by default. = encoding of the incoming text. + * pass some non-existing encoding name + * (ex: 'Do not touch my strings! I know what I am doing.') + * to make encoding code skip the encoding step. + * .outputEncoding = Either valid PDF encoding name + * (must be supported by jsPDF font metrics, otherwise no encoding) + * or a JS object, where key = sourceCharCode, value = outputCharCode + * missing keys will be treated as: sourceCharCode === outputCharCode + * .noBOM + * See comment higher above for explanation for why this is important + * .autoencode + * See comment higher above for explanation for why this is important + */ + var i, l, sourceEncoding, encodingBlock, outputEncoding, newtext, isUnicode, ch, bch; + flags = flags || {}; + sourceEncoding = flags.sourceEncoding || "Unicode"; + outputEncoding = flags.outputEncoding; // This 'encoding' section relies on font metrics format + // attached to font objects by, among others, + // "Willow Systems' standard_font_metrics plugin" + // see jspdf.plugin.standard_font_metrics.js for format + // of the font.metadata.encoding Object. + // It should be something like + // .encoding = {'codePages':['WinANSI....'], 'WinANSI...':{code:code, ...}} + // .widths = {0:width, code:width, ..., 'fof':divisor} + // .kerning = {code:{previous_char_code:shift, ..., 'fof':-divisor},...} + + if ((flags.autoencode || outputEncoding) && fonts[activeFontKey].metadata && fonts[activeFontKey].metadata[sourceEncoding] && fonts[activeFontKey].metadata[sourceEncoding].encoding) { + encodingBlock = fonts[activeFontKey].metadata[sourceEncoding].encoding; // each font has default encoding. Some have it clearly defined. + + if (!outputEncoding && fonts[activeFontKey].encoding) { + outputEncoding = fonts[activeFontKey].encoding; + } // Hmmm, the above did not work? Let's try again, in different place. + + + if (!outputEncoding && encodingBlock.codePages) { + outputEncoding = encodingBlock.codePages[0]; // let's say, first one is the default + } + + if (typeof outputEncoding === "string") { + outputEncoding = encodingBlock[outputEncoding]; + } // we want output encoding to be a JS Object, where + // key = sourceEncoding's character code and + // value = outputEncoding's character code. + + + if (outputEncoding) { + isUnicode = false; + newtext = []; + + for (i = 0, l = text.length; i < l; i++) { + ch = outputEncoding[text.charCodeAt(i)]; + + if (ch) { + newtext.push(String.fromCharCode(ch)); + } else { + newtext.push(text[i]); + } // since we are looping over chars anyway, might as well + // check for residual unicodeness + + + if (newtext[i].charCodeAt(0) >> 8) { + /* more than 255 */ + isUnicode = true; + } + } + + text = newtext.join(""); + } + } + + i = text.length; // isUnicode may be set to false above. Hence the triple-equal to undefined + + while (isUnicode === undefined && i !== 0) { + if (text.charCodeAt(i - 1) >> 8) { + /* more than 255 */ + isUnicode = true; + } + + i--; + } + + if (!isUnicode) { + return text; + } + + newtext = flags.noBOM ? [] : [254, 255]; + + for (i = 0, l = text.length; i < l; i++) { + ch = text.charCodeAt(i); + bch = ch >> 8; // divide by 256 + + if (bch >> 8) { + /* something left after dividing by 256 second time */ + throw new Error("Character at position " + i + " of string '" + text + "' exceeds 16bits. Cannot be encoded into UCS-2 BE"); + } + + newtext.push(bch); + newtext.push(ch - (bch << 8)); + } + + return String.fromCharCode.apply(undefined, newtext); + }, + pdfEscape = function pdfEscape(text, flags) { + /** + * Replace '/', '(', and ')' with pdf-safe versions + * + * Doing to8bitStream does NOT make this PDF display unicode text. For that + * we also need to reference a unicode font and embed it - royal pain in the rear. + * + * There is still a benefit to to8bitStream - PDF simply cannot handle 16bit chars, + * which JavaScript Strings are happy to provide. So, while we still cannot display + * 2-byte characters property, at least CONDITIONALLY converting (entire string containing) + * 16bit chars to (USC-2-BE) 2-bytes per char + BOM streams we ensure that entire PDF + * is still parseable. + * This will allow immediate support for unicode in document properties strings. + */ + return to8bitStream(text, flags).replace(/\\/g, "\\\\").replace(/\(/g, "\\(").replace(/\)/g, "\\)"); + }, + putInfo = function putInfo() { + out("/Producer (jsPDF " + jsPDF.version + ")"); + + for (var key in documentProperties) { + if (documentProperties.hasOwnProperty(key) && documentProperties[key]) { + out("/" + key.substr(0, 1).toUpperCase() + key.substr(1) + " (" + pdfEscape(documentProperties[key]) + ")"); + } + } + + out("/CreationDate (" + creationDate + ")"); + }, + putCatalog = function putCatalog() { + out("/Type /Catalog"); + out("/Pages 1 0 R"); // PDF13ref Section 7.2.1 + + if (!zoomMode) zoomMode = "fullwidth"; + + switch (zoomMode) { + case "fullwidth": + out("/OpenAction [3 0 R /FitH null]"); + break; + + case "fullheight": + out("/OpenAction [3 0 R /FitV null]"); + break; + + case "fullpage": + out("/OpenAction [3 0 R /Fit]"); + break; + + case "original": + out("/OpenAction [3 0 R /XYZ null null 1]"); + break; + + default: + var pcn = "" + zoomMode; + if (pcn.substr(pcn.length - 1) === "%") zoomMode = parseInt(zoomMode) / 100; + + if (typeof zoomMode === "number") { + out("/OpenAction [3 0 R /XYZ null null " + f2(zoomMode) + "]"); + } + + } + + if (!layoutMode) layoutMode = "continuous"; + + switch (layoutMode) { + case "continuous": + out("/PageLayout /OneColumn"); + break; + + case "single": + out("/PageLayout /SinglePage"); + break; + + case "two": + case "twoleft": + out("/PageLayout /TwoColumnLeft"); + break; + + case "tworight": + out("/PageLayout /TwoColumnRight"); + break; + } + + if (pageMode) { + /** + * A name object specifying how the document should be displayed when opened: + * UseNone : Neither document outline nor thumbnail images visible -- DEFAULT + * UseOutlines : Document outline visible + * UseThumbs : Thumbnail images visible + * FullScreen : Full-screen mode, with no menu bar, window controls, or any other window visible + */ + out("/PageMode /" + pageMode); + } + + events.publish("putCatalog"); + }, + putTrailer = function putTrailer() { + out("/Size " + (objectNumber + 1)); + out("/Root " + objectNumber + " 0 R"); + out("/Info " + (objectNumber - 1) + " 0 R"); + out("/ID [ <" + fileId + "> <" + fileId + "> ]"); + }, + beginPage = function beginPage(width, height) { + outToPages = true; + pages[++page] = []; + pagedim[page] = { + width: Number(width) || pageWidth, + height: Number(height) || pageHeight + }; + pagesContext[page] = {}; + + _setPage(page); + }, + _addPage = function _addPage(width, height) { + // Dimensions are stored as user units and converted to points on output + var orientation = typeof height === "string" && height.toLowerCase(); + + if (typeof width === "string") { + var format = width.toLowerCase(); + + if (pageFormats.hasOwnProperty(format)) { + width = pageFormats[format][0] / k; + height = pageFormats[format][1] / k; + } + } + + if (Array.isArray(width)) { + height = width[1]; + width = width[0]; + } + + if (orientation) { + switch (orientation.substr(0, 1)) { + case "l": + if (height > width) orientation = "s"; + break; + + case "p": + if (width > height) orientation = "s"; + break; + } + + if (orientation === "s") { + tmp = width; + width = height; + height = tmp; + } + } + + beginPage(width, height); // Set line width + + out(hpf(lineWidth * k) + " w"); // Set draw color + + out(drawColor); // resurrecting non-default line caps, joins + + if (lineCapID !== 0) { + out(lineCapID + " J"); + } + + if (lineJoinID !== 0) { + out(lineJoinID + " j"); + } + + events.publish("addPage", { + pageNumber: page + }); + }, + _deletePage = function _deletePage(n) { + if (n > 0 && n <= page) { + pages.splice(n, 1); + pagedim.splice(n, 1); + page--; + + if (currentPage > page) { + currentPage = page; + } + + this.setPage(currentPage); + } + }, + _setPage = function _setPage(n) { + if (n > 0 && n <= page) { + currentPage = n; + pageWidth = pagedim[n].width; + pageHeight = pagedim[n].height; + } + }, + + /** + * Returns a document-specific font key - a label assigned to a + * font name + font type combination at the time the font was added + * to the font inventory. + * + * Font key is used as label for the desired font for a block of text + * to be added to the PDF document stream. + * @private + * @function + * @param {String} fontName can be undefined on "falthy" to indicate "use current" + * @param {String} fontStyle can be undefined on "falthy" to indicate "use current" + * @returns {String} Font key. + */ + _getFont = function getFont(fontName, fontStyle, options) { + var key = undefined, + fontNameLowerCase; + options = options || {}; + fontName = fontName !== undefined ? fontName : fonts[activeFontKey].fontName; + fontStyle = fontStyle !== undefined ? fontStyle : fonts[activeFontKey].fontStyle; + fontNameLowerCase = fontName.toLowerCase(); + + if (fontmap[fontNameLowerCase] !== undefined && fontmap[fontNameLowerCase][fontStyle] !== undefined) { + key = fontmap[fontNameLowerCase][fontStyle]; + } else if (fontmap[fontName] !== undefined && fontmap[fontName][fontStyle] !== undefined) { + key = fontmap[fontName][fontStyle]; + } else { + if (options.disableWarning === false) { + console.warn("Unable to look up font label for font '" + fontName + "', '" + fontStyle + "'. Refer to getFontList() for available fonts."); + } + } + + if (!key && !options.noFallback) { + key = fontmap["times"][fontStyle]; + + if (key == null) { + key = fontmap["times"]["normal"]; + } + } + + return key; + }, + buildDocument = function buildDocument() { + outToPages = false; // switches out() to content + + objectNumber = 2; + content_length = 0; + content = []; + offsets = []; + additionalObjects = []; // Added for AcroForm + + events.publish("buildDocument"); // putHeader() + + out("%PDF-" + pdfVersion); + out("%\xBA\xDF\xAC\xE0"); + putPages(); // Must happen after putPages + // Modifies current object Id + + putAdditionalObjects(); + putResources(); // Info + + newObject(); + out("<<"); + putInfo(); + out(">>"); + out("endobj"); // Catalog + + newObject(); + out("<<"); + putCatalog(); + out(">>"); + out("endobj"); // Cross-ref + + var o = content_length, + i, + p = "0000000000"; + out("xref"); + out("0 " + (objectNumber + 1)); + out(p + " 65535 f "); + + for (i = 1; i <= objectNumber; i++) { + var offset = offsets[i]; + + if (typeof offset === "function") { + out((p + offsets[i]()).slice(-10) + " 00000 n "); + } else { + out((p + offsets[i]).slice(-10) + " 00000 n "); + } + } // Trailer + + + out("trailer"); + out("<<"); + putTrailer(); + out(">>"); + out("startxref"); + out("" + o); + out("%%EOF"); + outToPages = true; + return content.join("\n"); + }, + getStyle = function getStyle(style) { + // see path-painting operators in PDF spec + // The default in MrRio's implementation is "S" (stroke), whereas the default in the yWorks implementation + // was "n" (none). Although this has nothing to do with transforms, we should use the API switch here. + var op = apiMode === ApiMode.COMPAT ? "S" : "n"; + + if (style === "D") { + op = "S"; // stroke + } else if (style === "F") { + op = "f"; // fill + } else if (style === "FD" || style === "DF") { + op = "B"; // both + } else if (style === "f" || style === "f*" || style === "B" || style === "B*") { + /* + Allow direct use of these PDF path-painting operators: + - f fill using nonzero winding number rule + - f* fill using even-odd rule + - B fill then stroke with fill using non-zero winding number rule + - B* fill then stroke with fill using even-odd rule + */ + op = style; + } + + return op; + }, + // puts the style for the previously drawn path. If a patternKey is provided, the pattern is used to fill + // the path. Use patternMatrix to transform the pattern to rhe right location. + putStyle = function putStyle(style, patternKey, patternData) { + if (style === null || apiMode === ApiMode.ADVANCED && style === undefined) { + return; + } + + style = getStyle(style); // stroking / filling / both the path + + if (!patternKey) { + out(style); + return; + } + + if (!patternData) { + patternData = { + matrix: unitMatrix + }; + } + + if (patternData instanceof Matrix) { + patternData = { + matrix: patternData + }; + } + + patternData.key = patternKey; + patternData || (patternData = unitMatrix); + fillWithPattern(patternData, style); + }, + fillWithPattern = function fillWithPattern(patternData, style) { + var patternId = patternMap[patternData.key]; + var pattern = patterns[patternId]; + + if (pattern instanceof API.ShadingPattern) { + out("q"); + out(clipRuleFromStyle(style)); + + if (pattern.gState) { + API.setGState(pattern.gState); + } + + out(patternData.matrix.toString() + " cm"); + out("/" + patternId + " sh"); + out("Q"); + } else if (pattern instanceof API.TilingPattern) { + // pdf draws patterns starting at the bottom left corner and they are not affected by the global transformation, + // so we must flip them + var matrix = new Matrix(1, 0, 0, -1, 0, pageHeight); + + if (patternData.matrix) { + matrix = matrixMult(patternData.matrix || unitMatrix, matrix); // we cannot apply a matrix to the pattern on use so we must abuse the pattern matrix and create new instances + // for each use + + patternId = pattern.createClone(patternData.key, patternData.boundingBox, patternData.xStep, patternData.yStep, matrix).id; + } + + out("q"); + out("/Pattern cs"); + out("/" + patternId + " scn"); + + if (pattern.gState) { + API.setGState(pattern.gState); + } + + out(style); + out("Q"); + } + }, + clipRuleFromStyle = function clipRuleFromStyle(style) { + switch (style) { + case "f": + case "F": + return "W n"; + + case "f*": + return "W* n"; + + case "B": + return "W S"; + + case "B*": + return "W* S"; + // these two are for compatibility reasons (in the past, calling any primitive method with a shading pattern + // and "n"/"S" as style would still fill/fill and stroke the path) + + case "S": + return "W S"; + + case "n": + return "W n"; + } + }, + getArrayBuffer = function getArrayBuffer() { + var data = buildDocument(), + len = data.length, + ab = new ArrayBuffer(len), + u8 = new Uint8Array(ab); + + while (len--) { + u8[len] = data.charCodeAt(len); + } + + return ab; + }, + getBlob = function getBlob() { + return new Blob([getArrayBuffer()], { + type: "application/pdf" + }); + }, + _output = SAFE(function (type, options) { + if (typeof options === "string") { + options = { + filename: options + }; + } else { + options = options || {}; + options.filename = options.filename || "generated.pdf"; + } + + var datauri = ("" + type).substr(0, 6) === "dataur" ? "data:application/pdf;filename=" + options.filename + ";base64," + btoa(buildDocument()) : 0; + + switch (type) { + case undefined: + return buildDocument(); + + case "save": + if ((typeof navigator === "undefined" ? "undefined" : _typeof(navigator)) === "object" && navigator.getUserMedia) { + if (global.URL === undefined || global.URL.createObjectURL === undefined) { + return API.output("dataurlnewwindow"); + } + } + + saveAs(getBlob(), options.filename); + + if (typeof saveAs.unload === "function") { + if (global.setTimeout) { + setTimeout(saveAs.unload, 911); + } + } + + break; + + case "arraybuffer": + return getArrayBuffer(); + + case "blob": + return getBlob(); + + case "bloburi": + case "bloburl": + // User is responsible of calling revokeObjectURL + return global.URL && global.URL.createObjectURL(getBlob()) || void 0; + + case "datauristring": + case "dataurlstring": + return datauri; + + case "dataurlnewwindow": + var htmlForNewWindow = "" + "" + "" + '' + ""; + var nW = global.open(); + + if (nW !== null) { + nW.document.write(htmlForNewWindow); + } + + if (nW || typeof safari === "undefined") return nW; + + /* pass through */ + + case "datauri": + case "dataurl": + return global.document.location.href = datauri; + + default: + throw new Error('Output type "' + type + '" is not supported.'); + } // @TODO: Add different output options + + }), + + /** + * Used to see if a supplied hotfix was requested when the pdf instance was created. + * @param {string} hotfixName - The name of the hotfix to check. + * @returns {boolean} + */ + hasHotfix = function hasHotfix(hotfixName) { + return Array.isArray(hotfixes) === true && hotfixes.indexOf(hotfixName) > -1; + }; + + switch (unit) { + case "pt": + k = 1; + break; + + case "mm": + k = 72 / 25.4000508; + break; + + case "cm": + k = 72 / 2.54000508; + break; + + case "in": + k = 72; + break; + + case "px": + if (hasHotfix("px_scaling") == true) { + k = 72 / 96; + } else { + k = 96 / 72; + } + + break; + + case "pc": + k = 12; + break; + + case "em": + k = 12; + break; + + case "ex": + k = 6; + break; + + default: + throw "Invalid unit: " + unit; + } + + setCreationDate(); + setFileId(); //--------------------------------------- + // Public API + + /** + * Object exposing internal API to plugins + * @public + * @ignore + */ + + API.internal = { + pdfEscape: pdfEscape, + getStyle: getStyle, + + /** + * Returns {FontObject} describing a particular font. + * @public + * @function + * @param {String} fontName (Optional) Font's family name + * @param {String} fontStyle (Optional) Font's style variation name (Example:"Italic") + * @returns {FontObject} + */ + getFont: function getFont() { + return fonts[_getFont.apply(API, arguments)]; + }, + getFontSize: function getFontSize() { + return activeFontSize; + }, + getCharSpace: function getCharSpace() { + return activeCharSpace; + }, + getTextColor: function getTextColor() { + var colorEncoded = textColor.split(" "); + + if (colorEncoded.length === 2 && colorEncoded[1] === "g") { + // convert grayscale value to rgb so that it can be converted to hex for consistency + var floatVal = parseFloat(colorEncoded[0]); + colorEncoded = [floatVal, floatVal, floatVal, "r"]; + } + + var colorAsHex = "#"; + + for (var i = 0; i < 3; i++) { + colorAsHex += ("0" + Math.floor(parseFloat(colorEncoded[i]) * 255).toString(16)).slice(-2); + } + + return colorAsHex; + }, + getLineHeight: function getLineHeight() { + return activeFontSize * lineHeightProportion; + }, + write: function write(string1 + /*, string2, string3, etc */ + ) { + out(arguments.length === 1 ? string1 : Array.prototype.join.call(arguments, " ")); + }, + getCoordinateString: function getCoordinateString(value) { + return hpf(scaleByK(value)); + }, + getVerticalCoordinateString: function getVerticalCoordinateString(value) { + return hpf(transformScaleY(value)); + }, + collections: {}, + newObject: newObject, + newAdditionalObject: newAdditionalObject, + newObjectDeferred: newObjectDeferred, + newObjectDeferredBegin: newObjectDeferredBegin, + putStream: putStream, + events: events, + // ratio that you use in multiplication of a given "size" number to arrive to 'point' + // units of measurement. + // scaleFactor is set at initialization of the document and calculated against the stated + // default measurement units for the document. + // If default is "mm", k is the number that will turn number in 'mm' into 'points' number. + // through multiplication. + scaleFactor: k, + pageSize: { + getWidth: function getWidth() { + return pageWidth; + }, + getHeight: function getHeight() { + return pageHeight; + } + }, + output: function output(type, options) { + return _output(type, options); + }, + getNumberOfPages: function getNumberOfPages() { + return pages.length - 1; + }, + pages: pages, + out: out, + f2: f2, + getPageInfo: function getPageInfo(pageNumberOneBased) { + var objId = (pageNumberOneBased - 1) * 2 + 3; + return { + objId: objId, + pageNumber: pageNumberOneBased, + pageContext: pagesContext[pageNumberOneBased] + }; + }, + getCurrentPageInfo: function getCurrentPageInfo() { + var objId = (currentPage - 1) * 2 + 3; + return { + objId: objId, + pageNumber: currentPage, + pageContext: pagesContext[currentPage] + }; + }, + getPDFVersion: function getPDFVersion() { + return pdfVersion; + }, + hasHotfix: hasHotfix //Expose the hasHotfix check so plugins can also check them. + + }; + + function advancedAPI() { + // prepend global change of basis matrix + // (Now, instead of converting every coordinate to the pdf coordinate system, we apply a matrix + // that does this job for us (however, texts, images and similar objects must be drawn bottom up)) + this.saveGraphicsState(); + out(new Matrix(k, 0, 0, -k, 0, pageHeight * k).toString() + " cm"); + this.setFontSize(this.getFontSize() / k); + apiMode = ApiMode.ADVANCED; + } + + function compatAPI() { + this.restoreGraphicsState(); + apiMode = ApiMode.COMPAT; + } + /** + * @callback ApiSwitchBody + * @param {jsPDF} pdf + */ + + /** + * For compatibility reasons jsPDF offers two API modes which differ in the way they convert between the the usual + * screen coordinates and the PDF coordinate system. + * - "compat": Offers full compatibility across all plugins but does not allow arbitrary transforms + * - "advanced": Allows arbitrary transforms and more advanced features like pattern fills. Some plugins might + * not support this mode, though. + * Initial mode is "compat". + * + * You can either provide a callback to the body argument, which means that jsPDF will automatically switch back to + * the original API mode afterwards; or you can omit the callback and switch back manually using {@link compatAPI}. + * + * Note, that the calls to {@link saveGraphicsState} and {@link restoreGraphicsState} need to be balanced within the + * callback or between calls of this method and its counterpart {@link compatAPI}. Calls to {@link beginFormObject} + * or {@link beginTilingPattern} need to be closed by their counterparts before switching back to "compat" API mode. + * + * @param {ApiSwitchBody=} body When provided, this callback will be called after the API mode has been switched. + * The API mode will be switched back automatically afterwards. + * @returns {jsPDF} + * @methodOf jsPDF# + * @name advancedAPI + */ + + + API.advancedAPI = function (body) { + var doSwitch = apiMode === ApiMode.COMPAT; + + if (doSwitch) { + advancedAPI.call(this); + } + + if (typeof body !== "function") { + return this; + } + + body(this); + + if (doSwitch) { + compatAPI.call(this); + } + + return this; + }; + /** + * Switches to "compat" API mode. See {@link advancedAPI} for more details. + * + * @param {ApiSwitchBody=} body When provided, this callback will be called after the API mode has been switched. + * The API mode will be switched back automatically afterwards. + * @return {jsPDF} + * @methodOf jsPDF# + * @name compatApi + */ + + + API.compatAPI = function (body) { + var doSwitch = apiMode === ApiMode.ADVANCED; + + if (doSwitch) { + compatAPI.call(this); + } + + if (typeof body !== "function") { + return this; + } + + body(this); + + if (doSwitch) { + advancedAPI.call(this); + } + + return this; + }; + /** + * @return {boolean} True iff the current API mode is "advanced". See {@link advancedAPI}. + * @methodOf jsPDF# + * @name isAdvancedAPI + */ + + + API.isAdvancedAPI = function () { + return apiMode === ApiMode.ADVANCED; + }; + /** + * Inserts a debug comment into the pdf. + * @param {String} text + * @returns {jsPDF} + * @methodOf jsPDF# + * @name comment + */ + + + API.comment = function (text) { + out("#" + text); + return this; + }; + /** + * An object representing a pdf graphics state. + * @param parameters A parameter object that contains all properties this graphics state wants to set. + * Supported are: opacity, stroke-opacity + * @constructor + */ + + + API.GState = function (parameters) { + var supported = "opacity,stroke-opacity".split(","); + + for (var p in parameters) { + if (parameters.hasOwnProperty(p) && supported.indexOf(p) >= 0) { + this[p] = parameters[p]; + } + } + + this.id = ""; // set by addGState() + + this.objectNumber = -1; // will be set by putGState() + }; + + API.GState.prototype.equals = function equals(other) { + var ignore = "id,objectNumber,equals"; + if (!other || _typeof(other) !== _typeof(this)) return false; + var count = 0; + + for (var p in this) { + if (ignore.indexOf(p) >= 0) continue; + if (this.hasOwnProperty(p) && !other.hasOwnProperty(p)) return false; + if (this[p] !== other[p]) return false; + count++; + } + + for (var p in other) { + if (other.hasOwnProperty(p) && ignore.indexOf(p) < 0) count--; + } + + return count === 0; + }; + /** + * Adds a new {@link GState} for later use. See {@link setGState}. + * @param {String} key + * @param {GState} gState + * @function + * @instance + * @returns {jsPDF} + * + * @methodOf jsPDF# + * @name addPage + */ + + + API.addGState = function (key, gState) { + addGState(key, gState); + return this; + }; + /** + * Adds (and transfers the focus to) new page to the PDF document. + * @param {String/Array} format The format of the new page. Can be
  • a0 - a10
  • b0 - b10
  • c0 - c10
  • c0 - c10
  • dl
  • letter
  • government-letter
  • legal
  • junior-legal
  • ledger
  • tabloid
  • credit-card

+ * Default is "a4". If you want to use your own format just pass instead of one of the above predefined formats the size as an number-array , e.g. [595.28, 841.89] + * @param {string} orientation Orientation of the new page. Possible values are "portrait" or "landscape" (or shortcuts "p" (Default), "l") + * @function + * @instance + * @returns {jsPDF} + * + * @memberOf jsPDF + * @name addPage + */ + + + API.addPage = function (format, orientation) { + _addPage.apply(this, arguments); + + return this; + }; + /** + * Adds (and transfers the focus to) new page to the PDF document. + * @function + * @instance + * @returns {jsPDF} + * + * @memberOf jsPDF + * @name setPage + * @param {number} page Switch the active page to the page number specified + * @example + * doc = jsPDF() + * doc.addPage() + * doc.addPage() + * doc.text('I am on page 3', 10, 10) + * doc.setPage(1) + * doc.text('I am on page 1', 10, 10) + */ + + + API.setPage = function (page) { + _setPage.apply(this, arguments); + + return this; + }; + /** + * @name insertPage + * @memberOf jsPDF + * + * @function + * @instance + * @param {Object} beforePage + * @returns {jsPDF} + */ + + + API.insertPage = function (beforePage) { + this.addPage(); + this.movePage(currentPage, beforePage); + return this; + }; + /** + * @name movePage + * @memberOf jsPDF + * @function + * @instance + * @param {Object} targetPage + * @param {Object} beforePage + * @returns {jsPDF} + */ + + + API.movePage = function (targetPage, beforePage) { + var tmpPagesContext, tmpPagedim, tmpPages, i; + + if (targetPage > beforePage) { + tmpPages = pages[targetPage]; + tmpPagedim = pagedim[targetPage]; + tmpPagesContext = pagesContext[targetPage]; + + for (i = targetPage; i > beforePage; i--) { + pages[i] = pages[i - 1]; + pagedim[i] = pagedim[i - 1]; + pagesContext[i] = pagesContext[i - 1]; + } + + pages[beforePage] = tmpPages; + pagedim[beforePage] = tmpPagedim; + pagesContext[beforePage] = tmpPagesContext; + this.setPage(beforePage); + } else if (targetPage < beforePage) { + tmpPages = pages[targetPage]; + tmpPagedim = pagedim[targetPage]; + tmpPagesContext = pagesContext[targetPage]; + + for (i = targetPage; i < beforePage; i++) { + pages[i] = pages[i + 1]; + pagedim[i] = pagedim[i + 1]; + pagesContext[i] = pagesContext[i + 1]; + } + + pages[beforePage] = tmpPages; + pagedim[beforePage] = tmpPagedim; + pagesContext[beforePage] = tmpPagesContext; + this.setPage(beforePage); + } + + return this; + }; + /** + * @name deletePage + * @memberOf jsPDF + * @function + * @instance + * @returns {jsPDF} + */ + + + API.deletePage = function () { + _deletePage.apply(this, arguments); + + return this; + }; + /** + * @name setCreationDate + * @memberOf jsPDF + * @function + * @instance + * @param {Object} date + * @returns {jsPDF} + */ + + + API.setCreationDate = function (date) { + setCreationDate(date); + return this; + }; + /** + * @name getCreationDate + * @memberOf jsPDF + * @function + * @instance + * @param {Object} type + * @returns {Object} + */ + + + API.getCreationDate = function (type) { + return getCreationDate(type); + }; + /** + * @name setFileId + * @memberOf jsPDF + * @function + * @instance + * @param {string} value GUID + * @returns {jsPDF} + */ + + + API.setFileId = function (value) { + setFileId(value); + return this; + }; + /** + * @name getFileId + * @memberOf jsPDF + * @function + * @instance + * + * @returns {string} GUID + */ + + + API.getFileId = function () { + return getFileId(); + }; + /** + * Set the display mode options of the page like zoom and layout. + * + * @param {integer|String} zoom You can pass an integer or percentage as + * a string. 2 will scale the document up 2x, '200%' will scale up by the + * same amount. You can also set it to 'fullwidth', 'fullheight', + * 'fullpage', or 'original'. + * + * Only certain PDF readers support this, such as Adobe Acrobat + * + * @param {string} layout Layout mode can be: 'continuous' - this is the + * default continuous scroll. 'single' - the single page mode only shows one + * page at a time. 'twoleft' - two column left mode, first page starts on + * the left, and 'tworight' - pages are laid out in two columns, with the + * first page on the right. This would be used for books. + * @param {string} pmode 'UseOutlines' - it shows the + * outline of the document on the left. 'UseThumbs' - shows thumbnails along + * the left. 'FullScreen' - prompts the user to enter fullscreen mode. + * + * @returns {jsPDF} + * @function + * @instance + * @name setDisplayMode + * @methodOf jsPDF# + */ + + + API.setDisplayMode = function (zoom, layout, pmode) { + zoomMode = zoom; + layoutMode = layout; + pageMode = pmode; + var validPageModes = [undefined, null, "UseNone", "UseOutlines", "UseThumbs", "FullScreen"]; + + if (validPageModes.indexOf(pmode) == -1) { + throw new Error('Page mode must be one of UseNone, UseOutlines, UseThumbs, or FullScreen. "' + pmode + '" is not recognized.'); + } + + return this; + }; + /** + * Saves the current graphics state ("pushes it on the stack"). It can be restored by {@link restoreGraphicsState} + * later. Here, the general pdf graphics state is meant, also including the current transformation matrix, + * fill and stroke colors etc. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name saveGraphicsState + */ + + + API.saveGraphicsState = function () { + out("q"); // as we cannot set font key and size independently we must keep track of both + + fontStateStack.push({ + key: activeFontKey, + size: activeFontSize, + color: textColor + }); + return this; + }; + /** + * Restores a previously saved graphics state saved by {@link saveGraphicsState} ("pops the stack"). + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name restoreGraphicsState + */ + + + API.restoreGraphicsState = function () { + out("Q"); // restore previous font state + + var fontState = fontStateStack.pop(); + activeFontKey = fontState.key; + activeFontSize = fontState.size; + textColor = fontState.color; + activeGState = null; + return this; + }; + /** + * Appends this matrix to the left of all previously applied matrices. + * + * Only available in "advanced" API mode. + * + * @param {Matrix} matrix + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setCurrentTransformationMatrix + */ + + + API.setCurrentTransformationMatrix = function (matrix) { + advancedApiModeTrap("setCurrentTransformationMatrix()"); + out(matrix.toString() + " cm"); + return this; + }; + /** + * Starts a new pdf form object, which means that all conseequent draw calls target a new independent object + * until {@link endFormObject} is called. The created object can be referenced and drawn later using + * {@link doFormObject}. Nested form objects are possible. + * x, y, width, height set the bounding box that is used to clip the content. + * + * Only available in "advanced" API mode. + * + * @param {number} x + * @param {number} y + * @param {number} width + * @param {number} height + * @param {Matrix} matrix The matrix that will be applied to convert the form objects coordinate system to + * the parent's. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name beginFormObject + */ + + + API.beginFormObject = function (x, y, width, height, matrix) { + advancedApiModeTrap("beginFormObject()"); // The user can set the output target to a new form object. Nested form objects are possible. + // Currently, they use the resource dictionary of the surrounding stream. This should be changed, as + // the PDF-Spec states: + // "In PDF 1.2 and later versions, form XObjects may be independent of the content streams in which + // they appear, and this is strongly recommended although not requiredIn PDF 1.2 and later versions, + // form XObjects may be independent of the content streams in which they appear, and this is strongly + // recommended although not required" + + beginNewRenderTarget(x, y, width, height, matrix); + return this; + }; + /** + * Completes and saves the form object. Only available in "advanced" API mode. + * @param {String} key The key by which this form object can be referenced. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name endFormObject + */ + + + API.endFormObject = function (key) { + advancedApiModeTrap("endFormObject()"); + endFormObject(key); + return this; + }; + /** + * Draws the specified form object by referencing to the respective pdf XObject created with + * {@link API.beginFormObject} and {@link endFormObject}. + * The location is determined by matrix. + * + * Only available in "advanced" API mode. + * + * @param {String} key The key to the form object. + * @param {Matrix} matrix The matrix applied before drawing the form object. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name doFormObject + */ + + + API.doFormObject = function (key, matrix) { + advancedApiModeTrap("doFormObject()"); + var xObject = renderTargets[renderTargetMap[key]]; + out("q"); + out(matrix.toString() + " cm"); + out("/" + xObject.id + " Do"); + out("Q"); + return this; + }; + /** + * Returns the form object specified by key. + * @param key {String} + * @returns {{x: number, y: number, width: number, height: number, matrix: Matrix}} + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name getFormObject + */ + + + API.getFormObject = function (key) { + var xObject = renderTargets[renderTargetMap[key]]; + return { + x: xObject.x, + y: xObject.y, + width: xObject.width, + height: xObject.height, + matrix: xObject.matrix + }; + }; + /** + * A matrix object for 2D homogenous transformations: + * | a b 0 | + * | c d 0 | + * | e f 1 | + * pdf multiplies matrices righthand: v' = v x m1 x m2 x ... + * @param {number} a + * @param {number} b + * @param {number} c + * @param {number} d + * @param {number} e + * @param {number} f + * @constructor + */ + + + API.Matrix = Matrix; + /** + * Multiplies two matrices. (see {@link Matrix}) + * @param {Matrix} m1 + * @param {Matrix} m2 + * @methodOf jsPDF# + * @name matrixMult + */ + + API.matrixMult = matrixMult; + /** + * The unit matrix (equivalent to new Matrix(1, 0, 0, 1, 0, 0)). + * @type {Matrix} + * @fieldOf jsPDF# + * @name unitMatrix + */ + + API.unitMatrix = unitMatrix; + + var Pattern = function Pattern(gState, matrix) { + this.gState = gState; + this.matrix = matrix; + this.id = ""; // set by addPattern() + + this.objectNumber = -1; // will be set by putPattern() + }; + /** + * A pattern describing a shading pattern. + * + * Only available in "advanced" API mode. + * + * @param {String} type One of "axial" or "radial" + * @param {Array} coords Either [x1, y1, x2, y2] for "axial" type describing the two interpolation points + * or [x1, y1, r, x2, y2, r2] for "radial" describing inner and the outer circle. + * @param {Array} colors An array of objects with the fields "offset" and "color". "offset" describes + * the offset in parameter space [0, 1]. "color" is an array of length 3 describing RGB values in [0, 255]. + * @param {GState=} gState An additional graphics state that gets applied to the pattern (optional). + * @param {Matrix=} matrix A matrix that describes the transformation between the pattern coordinate system + * and the use coordinate system (optional). + * @constructor + * @extends API.Pattern + */ + + + API.ShadingPattern = function (type, coords, colors, gState, matrix) { + advancedApiModeTrap("ShadingPattern"); // see putPattern() for information how they are realized + + this.type = type === "axial" ? 2 : 3; + this.coords = coords; + this.colors = colors; + Pattern.call(this, gState, matrix); + }; + /** + * A PDF Tiling pattern. + * + * Only available in "advanced" API mode. + * + * @param {Array.} boundingBox The bounding box at which one pattern cell gets clipped. + * @param {Number} xStep Horizontal spacing between pattern cells. + * @param {Number} yStep Vertical spacing between pattern cells. + * @param {API.GState=} gState An additional graphics state that gets applied to the pattern (optional). + * @param {Matrix=} matrix A matrix that describes the transformation between the pattern coordinate system + * and the use coordinate system (optional). + * @constructor + * @extends API.Pattern + */ + + + API.TilingPattern = function (boundingBox, xStep, yStep, gState, matrix) { + advancedApiModeTrap("TilingPattern"); + this.boundingBox = boundingBox; + this.xStep = xStep; + this.yStep = yStep; + this.stream = ""; // set by endTilingPattern(); + + this.cloneIndex = 0; + Pattern.call(this, gState, matrix); + }; + + API.TilingPattern.prototype = { + createClone: function createClone(patternKey, boundingBox, xStep, yStep, matrix) { + var clone = new API.TilingPattern(boundingBox || this.boundingBox, xStep || this.xStep, yStep || this.yStep, this.gState, matrix || this.matrix); + clone.stream = this.stream; + var key = patternKey + "$$" + this.cloneIndex++ + "$$"; + addPattern(key, clone); + return clone; + } + }; + /** + * Adds a new {@link API.ShadingPattern} for later use. Only available in "advanced" API mode. + * @param {String} key + * @param {Pattern} pattern + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name addPattern + */ + + API.addShadingPattern = function (key, pattern) { + advancedApiModeTrap("addShadingPattern()"); + addPattern(key, pattern); + return this; + }; + /** + * Begins a new tiling pattern. All subsequent render calls are drawn to this pattern until {@link API.endTilingPattern} + * gets called. Only available in "advanced" API mode. + * @param {API.Pattern} pattern + * @methodOf jsPDF# + * @name beginTilingPattern + */ + + + API.beginTilingPattern = function (pattern) { + advancedApiModeTrap("beginTilingPattern()"); + beginNewRenderTarget(pattern.boundingBox[0], pattern.boundingBox[1], pattern.boundingBox[2] - pattern.boundingBox[0], pattern.boundingBox[3] - pattern.boundingBox[1], pattern.matrix); + }; + /** + * Ends a tiling pattern and sets the render target to the one active before {@link API.beginTilingPattern} has been called. + * + * Only available in "advanced" API mode. + * + * @param {string} key A unique key that is used to reference this pattern at later use. + * @param {API.Pattern} pattern The pattern to end. + * @methodOf jsPDF# + * @name endTilingPattern + */ + + + API.endTilingPattern = function (key, pattern) { + advancedApiModeTrap("endTilingPattern()"); // retrieve the stream + + pattern.stream = pages[currentPage].join("\n"); + addPattern(key, pattern); + events.publish("endTilingPattern", pattern); // restore state from stack + + renderTargetStack.pop().restore(); + }; + /** + * Adds text to page. Supports adding multiline text when 'text' argument is an Array of Strings. + * + * @function + * @param {String|Array} text String or array of strings to be added to the page. Each line is shifted one line down + * per font, spacing settings declared before this call. + * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Object} options Collection of settings signalling how the text must be encoded. Defaults are sane. If you + * think you want to pass some flags, you likely can read the source. + * @param {number|Matrix} transform If transform is a number the text will be rotated by this value around the + * anchor set by x and y. + * + * If it is a Matrix, this matrix gets directly applied to the text, which allows shearing + * effects etc.; the x and y offsets are then applied AFTER the coordinate system has been established by this + * matrix. This means passing a rotation matrix that is equivalent to some rotation angle will in general yield a + * DIFFERENT result. A matrix is only allowed in "advanced" API mode. + * + * @param align {string} + * @returns {jsPDF} + * @methodOf jsPDF# + * @name text + */ + + + API.text = function (text, x, y, options, transform) { + /** + * Inserts something like this into PDF + * BT + * /F1 16 Tf % Font name + size + * 16 TL % How many units down for next line in multiline text + * 0 g % color + * 28.35 813.54 Td % position + * (line one) Tj + * T* (line two) Tj + * T* (line three) Tj + * ET + */ + if (transform !== undefined && transform instanceof Matrix) { + advancedApiModeTrap("The transform parameter of text() with a Matrix value"); + } + + var xtra = ""; + var isHex = false; + var lineHeight = lineHeightProportion; + var scope = this; + + function ESC(s) { + s = s.split("\t").join(Array(options.TabLen || 9).join(" ")); + return pdfEscape(s, flags); + } + + function transformTextToSpecialArray(text) { + //we don't want to destroy original text array, so cloning it + var sa = text.concat(); + var da = []; + var len = sa.length; + var curDa; //we do array.join('text that must not be PDFescaped") + //thus, pdfEscape each component separately + + while (len--) { + curDa = sa.shift(); + + if (typeof curDa === "string") { + da.push(curDa); + } else { + if (Object.prototype.toString.call(text) === "[object Array]" && curDa.length === 1) { + da.push(curDa[0]); + } else { + da.push([curDa[0], curDa[1], curDa[2]]); + } + } + } + + return da; + } + + function processTextByFunction(text, processingFunction) { + var result; + + if (typeof text === "string") { + result = processingFunction(text)[0]; + } else if (Object.prototype.toString.call(text) === "[object Array]") { + //we don't want to destroy original text array, so cloning it + var sa = text.concat(); + var da = []; + var len = sa.length; + var curDa; + var tmpResult; //we do array.join('text that must not be PDFescaped") + //thus, pdfEscape each component separately + + while (len--) { + curDa = sa.shift(); + + if (typeof curDa === "string") { + da.push(processingFunction(curDa)[0]); + } else if (Object.prototype.toString.call(curDa) === "[object Array]" && curDa[0] === "string") { + tmpResult = processingFunction(curDa[0], curDa[1], curDa[2]); + da.push([tmpResult[0], tmpResult[1], tmpResult[2]]); + } + } + + result = da; + } + + return result; + } //backwardsCompatibility + + + var tmp; // Pre-August-2012 the order of arguments was function(x, y, text, flags) + // in effort to make all calls have similar signature like + // function(data, coordinates... , miscellaneous) + // this method had its args flipped. + // code below allows backward compatibility with old arg order. + + if (typeof text === "number") { + tmp = y; + y = x; + x = text; + text = tmp; + } + + var flags = arguments[3]; + var angle = arguments[4]; + var align = arguments[5]; + + if (_typeof(flags) !== "object" || flags === null) { + if (typeof angle === "string") { + align = angle; + angle = null; + } + + if (typeof flags === "string") { + align = flags; + flags = null; + } + + if (typeof flags === "number") { + angle = flags; + flags = null; + } + + options = { + flags: flags, + angle: angle, + align: align + }; + } //Check if text is of type String + + + var textIsOfTypeString = false; + var tmpTextIsOfTypeString = true; + + if (typeof text === "string") { + textIsOfTypeString = true; + } else if (Object.prototype.toString.call(text) === "[object Array]") { + //we don't want to destroy original text array, so cloning it + var sa = text.concat(); + var da = []; + var len = sa.length; + var curDa; //we do array.join('text that must not be PDFescaped") + //thus, pdfEscape each component separately + + while (len--) { + curDa = sa.shift(); + + if (typeof curDa !== "string" || Object.prototype.toString.call(curDa) === "[object Array]" && typeof curDa[0] !== "string") { + tmpTextIsOfTypeString = false; + } + } + + textIsOfTypeString = tmpTextIsOfTypeString; + } + + if (textIsOfTypeString === false) { + throw new Error('Type of text must be string or Array. "' + text + '" is not recognized.'); + } //Escaping + + + var activeFontEncoding = fonts[activeFontKey].encoding; + + if (activeFontEncoding === "WinAnsiEncoding" || activeFontEncoding === "StandardEncoding") { + text = processTextByFunction(text, function (text, posX, posY) { + return [ESC(text), posX, posY]; + }); + } //If there are any newlines in text, we assume + //the user wanted to print multiple lines, so break the + //text up into an array. If the text is already an array, + //we assume the user knows what they are doing. + //Convert text into an array anyway to simplify + //later code. + + + if (typeof text === "string") { + if (text.match(/[\r?\n]/)) { + text = text.split(/\r\n|\r|\n/g); + } else { + text = [text]; + } + } //multiline + + + var maxWidth = options.maxWidth || 0; + + if (maxWidth > 0) { + if (typeof text === "string") { + text = scope.splitTextToSize(text, maxWidth); + } else if (Object.prototype.toString.call(text) === "[object Array]") { + text = scope.splitTextToSize(text.join(" "), maxWidth); + } + } //creating Payload-Object to make text byRef + + + var payload = { + text: text, + x: x, + y: y, + options: options, + mutex: { + pdfEscape: pdfEscape, + activeFontKey: activeFontKey, + fonts: fonts, + activeFontSize: activeFontSize + } + }; + events.publish("preProcessText", payload); + text = payload.text; + options = payload.options; //angle + + var angle = options.angle; + var transformationMatrix = null; + + if (angle && typeof angle === "number") { + angle *= Math.PI / 180; + + if (apiMode === ApiMode.ADVANCED) { + angle = -angle; + } + + var c = Math.cos(angle), + s = Math.sin(angle); + transformationMatrix = new Matrix(c, s, -s, c, 0, 0); + } else if (angle && angle instanceof Matrix) { + transformationMatrix = angle; + } //charSpace + + + var charSpace = options.charSpace; + + if (charSpace !== undefined) { + xtra += charSpace + " Tc\n"; + } //lang + + + var lang = options.lang; + var tmpRenderingMode = -1; + var parmRenderingMode = options.renderingMode || options.stroke; + var pageContext = scope.internal.getCurrentPageInfo().pageContext; + + switch (parmRenderingMode) { + case 0: + case false: + case "fill": + tmpRenderingMode = 0; + break; + + case 1: + case true: + case "stroke": + tmpRenderingMode = 1; + break; + + case 2: + case "fillThenStroke": + tmpRenderingMode = 2; + break; + + case 3: + case "invisible": + tmpRenderingMode = 3; + break; + + case 4: + case "fillAndAddForClipping": + tmpRenderingMode = 4; + break; + + case 5: + case "strokeAndAddPathForClipping": + tmpRenderingMode = 5; + break; + + case 6: + case "fillThenStrokeAndAddToPathForClipping": + tmpRenderingMode = 6; + break; + + case 7: + case "addToPathForClipping": + tmpRenderingMode = 7; + break; + } + + var usedRenderingMode = pageContext.usedRenderingMode || -1; //if the coder wrote it explicitly to use a specific + //renderingMode, then use it + + if (tmpRenderingMode !== -1) { + xtra += tmpRenderingMode + " Tr\n"; //otherwise check if we used the rendering Mode already + //if so then set the rendering Mode... + } else if (usedRenderingMode !== -1) { + xtra += "0 Tr\n"; + } + + if (tmpRenderingMode !== -1) { + pageContext.usedRenderingMode = tmpRenderingMode; + } //align + + + var align = options.align || "left"; + var leading = activeFontSize * lineHeight; + var pageWidth = scope.internal.pageSize.getWidth(); + var k = scope.internal.scaleFactor; + var activeFont = fonts[activeFontKey]; + var charSpace = options.charSpace || activeCharSpace; + var maxWidth = options.maxWidth || 0; + var lineWidths; + var flags = {}; + var wordSpacingPerLine = []; + + if (Object.prototype.toString.call(text) === "[object Array]") { + var da = transformTextToSpecialArray(text); + var newY; + var maxLineLength; + var lineWidths; + + if (align !== "left") { + lineWidths = da.map(function (v) { + return scope.getStringUnitWidth(v, { + font: activeFont, + charSpace: charSpace, + fontSize: activeFontSize + }) * activeFontSize / k; + }); + } + + var maxLineLength = Math.max.apply(Math, lineWidths); //The first line uses the "main" Td setting, + //and the subsequent lines are offset by the + //previous line's x coordinate. + + var prevWidth = 0; + var delta; + var newX; + var xOffset = 0; + + if (align === "right") { + xOffset = -lineWidths[0]; + text = []; + + for (var i = 0, len = da.length; i < len; i++) { + delta = maxLineLength - lineWidths[i]; + + if (i === 0) { + newX = 0; + newY = 0; + } else { + newX = prevWidth - lineWidths[i]; + newY = leading; + } + + text.push([da[i], newX, newY]); + prevWidth = lineWidths[i]; + } + } else if (align === "center") { + xOffset = -lineWidths[0] / 2; + text = []; + + for (var i = 0, len = da.length; i < len; i++) { + delta = (maxLineLength - lineWidths[i]) / 2; + + if (i === 0) { + newX = 0; + newY = 0; + } else { + newX = (prevWidth - lineWidths[i]) / 2; + newY = leading; + } + + text.push([da[i], newX, newY]); + prevWidth = lineWidths[i]; + } + } else if (align === "left") { + text = []; + + for (var i = 0, len = da.length; i < len; i++) { + text.push(da[i]); + } + } else if (align === "justify") { + text = []; + var maxWidth = maxWidth !== 0 ? maxWidth : pageWidth; + + for (var i = 0, len = da.length; i < len; i++) { + newX = 0; + newY = i === 0 ? 0 : leading; + + if (i < len - 1) { + wordSpacingPerLine.push((maxWidth - lineWidths[i]) / (da[i].split(" ").length - 1)); + } + + text.push([da[i], newX, newY]); + } + } else { + throw new Error('Unrecognized alignment option, use "left", "center", "right" or "justify".'); + } + } //R2L + + + var doReversing = typeof options.R2L === "boolean" ? options.R2L : R2L; + + if (doReversing === true) { + text = processTextByFunction(text, function (text, posX, posY) { + return [text.split("").reverse().join(""), posX, posY]; + }); + } //creating Payload-Object to make text byRef + + + var payload = { + text: text, + x: x, + y: y, + options: options, + mutex: { + pdfEscape: pdfEscape, + activeFontKey: activeFontKey, + fonts: fonts, + activeFontSize: activeFontSize + } + }; + events.publish("postProcessText", payload); + text = payload.text; + isHex = payload.mutex.isHex; + var da = transformTextToSpecialArray(text); + text = []; + var variant = 0; + var len = da.length; + var posX; + var posY; + var content; + var wordSpacing = ""; + + for (var i = 0; i < len; i++) { + wordSpacing = ""; + + if (Object.prototype.toString.call(da[i]) !== "[object Array]") { + content = (isHex ? "<" : "(") + da[i] + (isHex ? ">" : ")"); + variant = 0; + } else if (Object.prototype.toString.call(da[i]) === "[object Array]") { + posX = da[i][1] * k; // x offset must always be scaled! + // y offset/leading must NOT be scaled by k as it is dependent of the font size, which is always given + // in plain pt + + posY = -da[i][2]; + content = (isHex ? "<" : "(") + da[i][0] + (isHex ? ">" : ")"); + variant = 1; + } + + if (wordSpacingPerLine !== undefined && wordSpacingPerLine[i] !== undefined) { + wordSpacing = wordSpacingPerLine[i] + " Tw\n"; + } + + if (variant === 1 && i > 0) { + text.push(wordSpacing + hpf(posX) + " " + hpf(posY) + " " + " Td\n" + content); + } else { + text.push(wordSpacing + content); + } + } + + if (variant === 0) { + text = text.join(" Tj\nT* "); + } else { + text = text.join(" Tj\n"); + } + + if (apiMode === ApiMode.ADVANCED && transformationMatrix === null) { + transformationMatrix = unitMatrix; + } + + if (transformationMatrix !== null) { + // It is kind of more intuitive to apply a plain rotation around the text anchor set by x and y + // but when the user supplies an arbitrary transformation matrix, the x and y offsets should be applied + // in the coordinate system established by this matrix + if (typeof angle === "number") { + transformationMatrix = matrixMult(transformationMatrix, new Matrix(1, 0, 0, 1, scaleByK(x), transformScaleY(y))); + } else { + transformationMatrix = matrixMult(new Matrix(1, 0, 0, 1, scaleByK(x), transformScaleY(y)), transformationMatrix); + } + + transformationMatrix = matrixMult( // xOffset must always be scaled! + new Matrix(1, 0, 0, 1, xOffset * k, 0), transformationMatrix); + + if (apiMode === ApiMode.ADVANCED) { + transformationMatrix = matrixMult(new Matrix(1, 0, 0, -1, 0, 0), transformationMatrix); + } + + text = transformationMatrix.toString() + " Tm\n" + text; + } else { + text = hpf(scaleByK(x + xOffset)) + " " + hpf(transformScaleY(y)) + " " + " Td\n" + text; + } + + text += " Tj\n"; + var result = "BT\n/" + activeFontKey + " " + activeFontSize + " Tf\n" + // font face, style, size + (activeFontSize * lineHeight).toFixed(2) + " TL\n" + // line spacing + textColor + "\n"; + result += xtra; + result += text; + result += "ET"; + out(result); + return scope; + }; + /** + * Letter spacing method to print text with gaps + * + * @function + * @instance + * @param {String|Array} text String to be added to the page. + * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {number} spacing Spacing (in units declared at inception) + * @returns {jsPDF} + * @methodOf jsPDF# + * @name lstext + * @deprecated We'll be removing this function. It doesn't take character width into account. + */ + + + API.lstext = function (text, x, y, spacing) { + console.warn("jsPDF.lstext is deprecated"); + + for (var i = 0, len = text.length; i < len; i++, x += spacing) { + this.text(text[i], x, y); + } + + return this; + }; + /** + * Draws a line from (x1, y1) to (x2, y2). No extra call to {@link API.stroke} is needed. + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @return {jsPDF} + * @methodOf jsPDF# + * @name line + */ + + + API.line = function (x1, y1, x2, y2) { + if (apiMode === ApiMode.COMPAT) { + return this.lines([[x2 - x1, y2 - y1]], x1, y1, [1, 1], "D"); + } else { + return this.lines([[x2 - x1, y2 - y1]], x1, y1, [1, 1]).stroke(); + } + }; + /** + * Begin a new subpath by moving the current point to coordinates (x, y). The PDF "m" operator. + * @param {number} x + * @param {number} y + * @methodOf jsPDF# + * @name moveTo + */ + + + API.moveTo = function (x, y) { + out(hpf(scaleByK(x)) + " " + hpf(transformScaleY(y)) + " m"); + }; + /** + * Append a straight line segment from the current point to the point (x, y). The PDF "l" operator. + * @param {number} x + * @param {number} y + * @methodOf jsPDF# + * @name lineTo + */ + + + API.lineTo = function (x, y) { + out(hpf(scaleByK(x)) + " " + hpf(transformScaleY(y)) + " l"); + }; + /** + * Append a cubic Bézier curve to the current path. The curve shall extend from the current point to the point + * (x3, y3), using (x1, y1) and (x2, y2) as Bézier control points. The new current point shall be (x3, x3). + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {number} x3 + * @param {number} y3 + * @methodOf jsPDF# + * @name curveTo + */ + + + API.curveTo = function (x1, y1, x2, y2, x3, y3) { + out([hpf(scaleByK(x1)), hpf(transformScaleY(y1)), hpf(scaleByK(x2)), hpf(transformScaleY(y2)), hpf(scaleByK(x3)), hpf(transformScaleY(y3)), "c"].join(" ")); + }; // PDF supports these path painting and clip path operators: + // + // S - stroke + // s - close/stroke + // f (F) - fill non-zero + // f* - fill evenodd + // B - fill stroke nonzero + // B* - fill stroke evenodd + // b - close fill stroke nonzero + // b* - close fill stroke evenodd + // n - nothing (consume path) + // W - clip nonzero + // W* - clip evenodd + // + // In order to keep the API small, we omit the close-and-fill/stroke operators and provide a separate close() + // method. + + /** + * Close the current path. The PDF "h" operator. + * @return jsPDF + * @methodOf jsPDF# + * @name close + */ + + + API.close = function () { + out("h"); + return this; + }; + /** + * Stroke the path. The PDF "S" operator. + * @return jsPDF + * @methodOf jsPDF# + * @name stroke + */ + + + API.stroke = function () { + out("S"); + return this; + }; + /** + * @typedef {Object} PatternData + * @property {string} key The key of the pattern + * @property {Matrix} matrix The matrix that gets applied to the pattern right before drawing. + * @property {number[]|undefined} boundingBox Only relevant for tiling patterns. The bounding box at which one + * pattern cell gets clipped + * @property {number|undefined} xStep Only relevant for tiling patterns. Horizontal spacing between pattern cells + * @property {number|undefined} yStep Only relevant for tiling patterns. Vertical spacing between pattern cells + */ + + /** + * Fill the current path using the nonzero winding number rule. If a pattern is provided, the path will be filled + * with this pattern, otherwise with the current fill color. Equivalent to the PDF "f" operator. + * @param {PatternData=} pattern If provided the path will be filled with this pattern + * @return jsPDF + * @methodOf jsPDF# + * @name fill + */ + + + API.fill = function (pattern) { + fillWithOptionalPattern("f", pattern); + return this; + }; + /** + * Fill the current path using the even-odd rule. The PDF f* operator. + * @see API.fill + * @param {PatternData=} pattern Optional pattern + * @return jsPDF + * @methodOf jsPDF# + * @name fillEvenOdd + */ + + + API.fillEvenOdd = function (pattern) { + fillWithOptionalPattern("f*", pattern); + return this; + }; + /** + * Fill using the nonzero winding number rule and then stroke the current Path. The PDF "B" operator. + * @see API.fill + * @param {PatternData=} pattern Optional pattern + * @return jsPDF + * @methodOf jsPDF# + * @name fillStroke + */ + + + API.fillStroke = function (pattern) { + fillWithOptionalPattern("B", pattern); + return this; + }; + /** + * Fill using the even-odd rule and then stroke the current Path. The PDF "B" operator. + * @see API.fill + * @param {PatternData=} pattern Optional pattern + * @return jsPDF + * @methodOf jsPDF# + * @name fillStrokeEvenOdd + */ + + + API.fillStrokeEvenOdd = function (pattern) { + fillWithOptionalPattern("B*", pattern); + return this; + }; + + function fillWithOptionalPattern(style, pattern) { + if (_typeof(pattern) === "object") { + fillWithPattern(pattern, style); + } else { + out(style); + } + } + /** + * Modify the current clip path by intersecting it with the current path using the nonzero winding number rule. Note + * that this will NOT consume the current path. In order to only use this path for clipping call + * {@link API.discardPath} afterwards. + * + * When in "compat" API mode this method has a historical bug and will always stroke the path as well, use + * {@link API.clip_fixed} instead. + * @return jsPDF + * @methodOf jsPDF# + * @name clip + */ + + + API.clip = function () { + if (apiMode === ApiMode.COMPAT) { + // By patrick-roberts, github.com/MrRio/jsPDF/issues/328 + // Call .clip() after calling .rect() with a style argument of null + out("W"); // clip + + out("S"); // stroke path; necessary for clip to work + } else { + out("W"); + } + + return this; + }; + /** + * Modify the current clip path by intersecting it with the current path using the even-odd rule. Note + * that this will NOT consume the current path. In order to only use this path for clipping call + * {@link API.discardPath} afterwards. + * + * @return jsPDF + * @methodOf jsPDF# + * @name clipEvenOdd + */ + + + API.clipEvenOdd = function () { + out("W*"); + return this; + }; + /** + * Consumes the current path without any effect. Mainly used in combination with {@link clip} or + * {@link clipEvenOdd}. The PDF "n" operator. + * @return {jsPDF} + * @methodOf jsPDF# + * @name discardPath + */ + + + API.discardPath = function () { + out("n"); + return this; + }; + /** + * This fixes the previous function clip(). Perhaps the 'stroke path' hack was due to the missing 'n' instruction? + * We introduce the fixed version so as to not break API. + * @param fillRule + * @deprecated Don't use this method when in "advanced" API mode. + * @methodOf jsPDF# + * @name clip_fixed + */ + + + API.clip_fixed = function (fillRule) { + // Call .clip() after calling drawing ops with a style argument of null + // W is the PDF clipping op + if ("evenodd" === fillRule) { + out("W*"); + } else { + out("W"); + } // End the path object without filling or stroking it. + // This operator is a path-painting no-op, used primarily for the side effect of changing the current clipping path + // (see Section 4.4.3, “Clipping Path Operators”) + + + out("n"); + }; + /** + * @typedef {Object} PatternData + * {Matrix|undefined} matrix + * {Number|undefined} xStep + * {Number|undefined} yStep + * {Array.|undefined} boundingBox + */ + + /** + * Adds series of curves (straight lines or cubic bezier curves) to canvas, starting at `x`, `y` coordinates. + * All data points in `lines` are relative to last line origin. + * `x`, `y` become x1,y1 for first line / curve in the set. + * For lines you only need to specify [x2, y2] - (ending point) vector against x1, y1 starting point. + * For bezier curves you need to specify [x2,y2,x3,y3,x4,y4] - vectors to control points 1, 2, ending point. All vectors are against the start of the curve - x1,y1. + * + * @example .lines([[2,2],[-2,2],[1,1,2,2,3,3],[2,1]], 212,110, 10) // line, line, bezier curve, line + * @param {Array} lines Array of *vector* shifts as pairs (lines) or sextets (cubic bezier curves). + * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} scale (Defaults to [1.0,1.0]) x,y Scaling factor for all vectors. Elements can be any floating number Sub-one makes drawing smaller. Over-one grows the drawing. Negative flips the direction. + * @param {String=} style A string specifying the painting style or null. Valid styles include: + * 'S' [default] - stroke, + * 'F' - fill, + * and 'DF' (or 'FD') - fill then stroke. + * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple + * method calls. The last drawing method call used to define the shape should not have a null style argument. + * + * In "advanced" API mode this parameter is deprecated. + * @param {Boolean=} closed If true, the path is closed with a straight line from the end of the last curve to the starting point. + * @param {String=} patternKey The pattern key for the pattern that should be used to fill the path. Deprecated! + * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that + * will modify the pattern on use. Deprecated! + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name lines + */ + + + API.lines = function (lines, x, y, scale, style, closed, patternKey, patternData) { + var scalex, scaley, i, l, leg, x2, y2, x3, y3, x4, y4; // Pre-August-2012 the order of arguments was function(x, y, lines, scale, style) + // in effort to make all calls have similar signature like + // function(content, coordinateX, coordinateY , miscellaneous) + // this method had its args flipped. + // code below allows backward compatibility with old arg order. + + if (typeof lines === "number") { + var tmp = y; + y = x; + x = lines; + lines = tmp; + } + + scale = scale || [1, 1]; // starting point + + this.moveTo(x, y); + scalex = scale[0]; + scaley = scale[1]; + l = lines.length; //, x2, y2 // bezier only. In page default measurement "units", *after* scaling + //, x3, y3 // bezier only. In page default measurement "units", *after* scaling + // ending point for all, lines and bezier. . In page default measurement "units", *after* scaling + + x4 = x; // last / ending point = starting point for first item. + + y4 = y; // last / ending point = starting point for first item. + + for (i = 0; i < l; i++) { + leg = lines[i]; + + if (leg.length === 2) { + // simple line + x4 = leg[0] * scalex + x4; // here last x4 was prior ending point + + y4 = leg[1] * scaley + y4; // here last y4 was prior ending point + + this.lineTo(x4, y4); + } else { + // bezier curve + x2 = leg[0] * scalex + x4; // here last x4 is prior ending point + + y2 = leg[1] * scaley + y4; // here last y4 is prior ending point + + x3 = leg[2] * scalex + x4; // here last x4 is prior ending point + + y3 = leg[3] * scaley + y4; // here last y4 is prior ending point + + x4 = leg[4] * scalex + x4; // here last x4 was prior ending point + + y4 = leg[5] * scaley + y4; // here last y4 was prior ending point + + this.curveTo(x2, y2, x3, y3, x4, y4); + } + } + + if (closed) { + this.close(); + } + + putStyle(style, patternKey, patternData); + return this; + }; + /** + * Similar to {@link API.lines} but all coordinates are interpreted as absolute coordinates instead of relative. + * @param {Array} lines An array of {op: operator, c: coordinates} object, where op is one of "m" (move to), "l" (line to) + * "c" (cubic bezier curve) and "h" (close (sub)path)). c is an array of coordinates. "m" and "l" expect two, "c" + * six and "h" an empty array (or undefined). + * @param {String=} style The style. Deprecated! + * @param {String=} patternKey The pattern key for the pattern that should be used to fill the path. Deprecated! + * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that + * will modify the pattern on use. Deprecated! + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name path + */ + + + API.path = function (lines, style, patternKey, patternData) { + for (var i = 0; i < lines.length; i++) { + var leg = lines[i]; + var coords = leg.c; + + switch (leg.op) { + case "m": + this.moveTo(coords[0], coords[1]); + break; + + case "l": + this.lineTo(coords[0], coords[1]); + break; + + case "c": + this.curveTo.apply(this, coords); + break; + + case "h": + this.close(); + break; + } + } + + putStyle(style, patternKey, patternData); + return this; + }; + /** + * Adds a rectangle to PDF + * + * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} w Width (in units declared at inception of PDF document) + * @param {Number} h Height (in units declared at inception of PDF document) + * @param {String=} style A string specifying the painting style or null. Valid styles include: + * 'S' [default] - stroke, + * 'F' - fill, + * and 'DF' (or 'FD') - fill then stroke. + * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple + * method calls. The last drawing method call used to define the shape should not have a null style argument. + * + * In "advanced" API mode this parameter is deprecated. + * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated! + * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that + * will modify the pattern on use. Deprecated! + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name rect + */ + + + API.rect = function (x, y, w, h, style, patternKey, patternData) { + if (apiMode === ApiMode.COMPAT) { + h = -h; + } + + out([hpf(scaleByK(x)), hpf(transformScaleY(y)), hpf(scaleByK(w)), hpf(scaleByK(h)), "re"].join(" ")); + putStyle(style, patternKey, patternData); + return this; + }; + /** + * Adds a triangle to PDF + * + * @param {Number} x1 Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y1 Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} x2 Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y2 Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} x3 Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y3 Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {String=} style A string specifying the painting style or null. Valid styles include: + * 'S' [default] - stroke, + * 'F' - fill, + * and 'DF' (or 'FD') - fill then stroke. + * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple + * method calls. The last drawing method call used to define the shape should not have a null style argument. + * + * In "advanced" API mode this parameter is deprecated. + * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated! + * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that + * will modify the pattern on use. Deprecated! + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name triangle + */ + + + API.triangle = function (x1, y1, x2, y2, x3, y3, style, patternKey, patternData) { + this.lines([[x2 - x1, y2 - y1], // vector to point 2 + [x3 - x2, y3 - y2], // vector to point 3 + [x1 - x3, y1 - y3] // closing vector back to point 1 + ], x1, y1, // start of path + [1, 1], style, true, patternKey, patternData); + return this; + }; + /** + * Adds a rectangle with rounded corners to PDF + * + * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} w Width (in units declared at inception of PDF document) + * @param {Number} h Height (in units declared at inception of PDF document) + * @param {Number} rx Radius along x axis (in units declared at inception of PDF document) + * @param {Number} ry Radius along y axis (in units declared at inception of PDF document) + * @param {String=} style A string specifying the painting style or null. Valid styles include: + * 'S' [default] - stroke, + * 'F' - fill, + * and 'DF' (or 'FD') - fill then stroke. + * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple + * method calls. The last drawing method call used to define the shape should not have a null style argument. + * + * In "advanced" API mode this parameter is deprecated. + * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated! + * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that + * will modify the pattern on use. Deprecated! + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name roundedRect + */ + + + API.roundedRect = function (x, y, w, h, rx, ry, style, patternKey, patternData) { + var MyArc = 4 / 3 * (Math.SQRT2 - 1); + rx = Math.min(rx, w * 0.5); + ry = Math.min(ry, h * 0.5); + this.lines([[w - 2 * rx, 0], [rx * MyArc, 0, rx, ry - ry * MyArc, rx, ry], [0, h - 2 * ry], [0, ry * MyArc, -(rx * MyArc), ry, -rx, ry], [-w + 2 * rx, 0], [-(rx * MyArc), 0, -rx, -(ry * MyArc), -rx, -ry], [0, -h + 2 * ry], [0, -(ry * MyArc), rx * MyArc, -ry, rx, -ry]], x + rx, y, // start of path + [1, 1], style, true, patternKey, patternData); + return this; + }; + /** + * Adds an ellipse to PDF + * + * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} rx Radius along x axis (in units declared at inception of PDF document) + * @param {Number} ry Radius along y axis (in units declared at inception of PDF document) + * @param {String=} style A string specifying the painting style or null. Valid styles include: + * 'S' [default] - stroke, + * 'F' - fill, + * and 'DF' (or 'FD') - fill then stroke. + * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple + * method calls. The last drawing method call used to define the shape should not have a null style argument. + * + * In "advanced" API mode this parameter is deprecated. + * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated! + * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that + * will modify the pattern on use. Deprecated! + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name ellipse + */ + + + API.ellipse = function (x, y, rx, ry, style, patternKey, patternData) { + var lx = 4 / 3 * (Math.SQRT2 - 1) * rx, + ly = 4 / 3 * (Math.SQRT2 - 1) * ry; + this.moveTo(x + rx, y); + this.curveTo(x + rx, y - ly, x + lx, y - ry, x, y - ry); + this.curveTo(x - lx, y - ry, x - rx, y - ly, x - rx, y); + this.curveTo(x - rx, y + ly, x - lx, y + ry, x, y + ry); + this.curveTo(x + lx, y + ry, x + rx, y + ly, x + rx, y); + putStyle(style, patternKey, patternData); + return this; + }; + /** + * Adds an circle to PDF + * + * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} r Radius (in units declared at inception of PDF document) + * @param {String=} style A string specifying the painting style or null. Valid styles include: + * 'S' [default] - stroke, + * 'F' - fill, + * and 'DF' (or 'FD') - fill then stroke. + * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple + * method calls. The last drawing method call used to define the shape should not have a null style argument. + * + * In "advanced" API mode this parameter is deprecated. + * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated! + * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that + * will modify the pattern on use. Deprecated! + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name circle + */ + + + API.circle = function (x, y, r, style, patternKey, patternData) { + return this.ellipse(x, y, r, r, style, patternKey, patternData); + }; + /** + * Adds a properties to the PDF document + * + * @param {Object} properties A property_name-to-property_value object structure. + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setProperties + */ + + + API.setProperties = function (properties) { + // copying only those properties we can render. + for (var property in documentProperties) { + if (documentProperties.hasOwnProperty(property) && properties[property]) { + documentProperties[property] = properties[property]; + } + } + + return this; + }; + /** + * Sets font size for upcoming text elements. + * + * @param {number} size Font size in points. + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setFontSize + */ + + + API.setFontSize = function (size) { + // convert font size into current unit system + if (apiMode === ApiMode.ADVANCED) { + activeFontSize = size / k; + } else { + activeFontSize = size; + } + + out("/" + activeFontKey + " " + activeFontSize + " Tf"); + return this; + }; + /** + * @return {number} + * @methodOf jsPDF# + * @name getFontSize + */ + + + API.getFontSize = function () { + if (apiMode === ApiMode.COMPAT) { + return activeFontSize; + } else { + return activeFontSize * k; + } + }; + /** + * Sets text font face, variant for upcoming text elements. + * See output of jsPDF.getFontList() for possible font names, styles. + * + * @param {string} fontName Font name or family. Example: "times" + * @param {string} fontStyle Font style or variant. Example: "italic" + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setFont + */ + + + API.setFont = function (fontName, fontStyle) { + activeFontKey = _getFont(fontName, fontStyle); // if font is not found, the above line blows up and we never go further + + out("/" + activeFontKey + " " + activeFontSize + " Tf"); + return this; + }; + /** + * Switches font style or variant for upcoming text elements, + * while keeping the font face or family same. + * See output of jsPDF.getFontList() for possible font names, styles. + * + * @param {string} style Font style or variant. Example: "italic" + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setFontStyle + */ + + + API.setFontStyle = API.setFontType = function (style) { + activeFontKey = _getFont(undefined, style); // if font is not found, the above line blows up and we never go further + + out("/" + activeFontKey + " " + activeFontSize + " Tf"); + return this; + }; + /** + * Returns an object - a tree of fontName to fontStyle relationships available to + * active PDF document. + * + * @public + * @function + * @instance + * @returns {Object} Like {'times':['normal', 'italic', ... ], 'arial':['normal', 'bold', ... ], ... } + * @methodOf jsPDF# + * @name getFontList + */ + + + API.getFontList = function () { + // TODO: iterate over fonts array or return copy of fontmap instead in case more are ever added. + var list = {}, + fontName, + fontStyle, + tmp; + + for (fontName in fontmap) { + if (fontmap.hasOwnProperty(fontName)) { + list[fontName] = tmp = []; + + for (fontStyle in fontmap[fontName]) { + if (fontmap[fontName].hasOwnProperty(fontStyle)) { + tmp.push(fontStyle); + } + } + } + } + + return list; + }; + /** + * Add a custom font to the current instance. + * + * @param {String} postScriptName name of the Font. Example: "Menlo-Regular" + * @param {String} fontName of font-family from @font-face definition. Example: "Menlo Regular" + * @param {String} fontStyle style. Example: "normal" + * @function + * @instance + * @methodOf jsPDF + * @name addFont + */ + + + API.addFont = function (postScriptName, fontName, fontStyle, encoding) { + encoding = encoding || "Identity-H"; + addFont.call(this, postScriptName, fontName, fontStyle, encoding); + }; + /** + * Sets line width for upcoming lines. + * + * @param {number} width Line width (in units declared at inception of PDF document) + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setLineWidth + */ + + + API.setLineWidth = function (width) { + out(scaleByK(width).toFixed(2) + " w"); + return this; + }; + /** + * Sets the stroke color for upcoming elements. + * + * Depending on the number of arguments given, Gray, RGB, or CMYK + * color space is implied. + * + * When only ch1 is given, "Gray" color space is implied and it + * must be a value in the range from 0.00 (solid black) to to 1.00 (white) + * if values are communicated as String types, or in range from 0 (black) + * to 255 (white) if communicated as Number type. + * The RGB-like 0-255 range is provided for backward compatibility. + * + * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each + * value must be in the range from 0.00 (minimum intensity) to to 1.00 + * (max intensity) if values are communicated as String types, or + * from 0 (min intensity) to to 255 (max intensity) if values are communicated + * as Number types. + * The RGB-like 0-255 range is provided for backward compatibility. + * + * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each + * value must be a in the range from 0.00 (0% concentration) to to + * 1.00 (100% concentration) + * + * Because JavaScript treats fixed point numbers badly (rounds to + * floating point nearest to binary representation) it is highly advised to + * communicate the fractional numbers as String types, not JavaScript Number type. + * + * @param {Number|String} ch1 Color channel value or {string} ch1 color value in hexadecimal, example: '#FFFFFF' + * @param {Number|String} ch2 Color channel value + * @param {Number|String} ch3 Color channel value + * @param {Number|String} ch4 Color channel value + * + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setDrawColor + */ + + + API.setDrawColor = function (ch1, ch2, ch3, ch4) { + var options = { + ch1: ch1, + ch2: ch2, + ch3: ch3, + ch4: ch4, + pdfColorType: "draw", + precision: 2 + }; + out(generateColorString(options)); + return this; + }; + /** + * Sets the fill color for upcoming elements. + * + * Depending on the number of arguments given, Gray, RGB, or CMYK + * color space is implied. + * + * When only ch1 is given, "Gray" color space is implied and it + * must be a value in the range from 0.00 (solid black) to to 1.00 (white) + * if values are communicated as String types, or in range from 0 (black) + * to 255 (white) if communicated as Number type. + * The RGB-like 0-255 range is provided for backward compatibility. + * + * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each + * value must be in the range from 0.00 (minimum intensity) to to 1.00 + * (max intensity) if values are communicated as String types, or + * from 0 (min intensity) to to 255 (max intensity) if values are communicated + * as Number types. + * The RGB-like 0-255 range is provided for backward compatibility. + * + * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each + * value must be a in the range from 0.00 (0% concentration) to to + * 1.00 (100% concentration) + * + * Because JavaScript treats fixed point numbers badly (rounds to + * floating point nearest to binary representation) it is highly advised to + * communicate the fractional numbers as String types, not JavaScript Number type. + * + * @param {Number|String} ch1 Color channel value or {string} ch1 color value in hexadecimal, example: '#FFFFFF' + * @param {Number|String} ch2 Color channel value + * @param {Number|String} ch3 Color channel value + * @param {Number|String} ch4 Color channel value + * + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setFillColor + */ + + + API.setFillColor = function (ch1, ch2, ch3, ch4) { + var options = { + ch1: ch1, + ch2: ch2, + ch3: ch3, + ch4: ch4, + pdfColorType: "fill", + precision: 2 + }; + out(generateColorString(options)); + return this; + }; + /** + * Sets the text color for upcoming elements. + * + * Depending on the number of arguments given, Gray, RGB, or CMYK + * color space is implied. + * + * When only ch1 is given, "Gray" color space is implied and it + * must be a value in the range from 0.00 (solid black) to to 1.00 (white) + * if values are communicated as String types, or in range from 0 (black) + * to 255 (white) if communicated as Number type. + * The RGB-like 0-255 range is provided for backward compatibility. + * + * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each + * value must be in the range from 0.00 (minimum intensity) to to 1.00 + * (max intensity) if values are communicated as String types, or + * from 0 (min intensity) to to 255 (max intensity) if values are communicated + * as Number types. + * The RGB-like 0-255 range is provided for backward compatibility. + * + * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each + * value must be a in the range from 0.00 (0% concentration) to to + * 1.00 (100% concentration) + * + * Because JavaScript treats fixed point numbers badly (rounds to + * floating point nearest to binary representation) it is highly advised to + * communicate the fractional numbers as String types, not JavaScript Number type. + * + * @param {Number|String} ch1 Color channel value or {string} ch1 color value in hexadecimal, example: '#FFFFFF' + * @param {Number|String} ch2 Color channel value + * @param {Number|String} ch3 Color channel value + * @param {Number|String} ch4 Color channel value + * + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setTextColor + */ + + + API.setTextColor = function (ch1, ch2, ch3, ch4) { + var options = { + ch1: ch1, + ch2: ch2, + ch3: ch3, + ch4: ch4, + pdfColorType: "text", + precision: 3 + }; + textColor = generateColorString(options); + return this; + }; + /** + * Initializes the default character set that the user wants to be global.. + * + * @param {number} charSpace + * @function + * @instance + * @returns {jsPDF} jsPDF-instance + * @methodOf jsPDF + * @name setCharSpace + */ + + + API.setCharSpace = function (charSpace) { + if (apiMode === ApiMode.COMPAT) { + activeCharSpace = charSpace; + } else if (apiMode === ApiMode.ADVANCED) { + activeCharSpace = charSpace / k; + } + + return this; + }; + /** + * Initializes the default character set that the user wants to be global.. + * + * @param {boolean} boolean + * @function + * @instance + * @returns {jsPDF} jsPDF-instance + * @methodOf jsPDF + * @name setR2L + */ + + + API.setR2L = function (boolean) { + R2L = boolean; + return this; + }; + /** + * Sets a either previously added {@link GState} (via {@link addGState}) or a new {@link GState}. + * @param {String|GState} gState If type is string, a previously added GState is used, if type is GState + * it will be added before use. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setGState + */ + + + API.setGState = function (gState) { + if (typeof gState === "string") { + gState = gStates[gStatesMap[gState]]; + } else { + gState = addGState(null, gState); + } + + if (!gState.equals(activeGState)) { + out("/" + gState.id + " gs"); + activeGState = gState; + } + }; + /** + * Is an Object providing a mapping from human-readable to + * integer flag values designating the varieties of line cap + * and join styles. + * + * @fieldOf jsPDF# + * @name CapJoinStyles + */ + + + API.CapJoinStyles = { + 0: 0, + butt: 0, + but: 0, + miter: 0, + 1: 1, + round: 1, + rounded: 1, + circle: 1, + 2: 2, + projecting: 2, + project: 2, + square: 2, + bevel: 2 + }; + /** + * Sets the line cap styles + * See {jsPDF.CapJoinStyles} for variants + * + * @param {String|Number} style A string or number identifying the type of line cap + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setLineCap + */ + + API.setLineCap = function (style) { + var id = this.CapJoinStyles[style]; + + if (id === undefined) { + throw new Error("Line cap style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles"); + } + + lineCapID = id; + out(id + " J"); + return this; + }; + /** + * Sets the line join styles + * See {jsPDF.CapJoinStyles} for variants + * + * @param {String|Number} style A string or number identifying the type of line join + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setLineJoin + */ + + + API.setLineJoin = function (style) { + var id = this.CapJoinStyles[style]; + + if (id === undefined) { + throw new Error("Line join style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles"); + } + + lineJoinID = id; + out(id + " j"); + return this; + }; + /** + * Sets the miter limit. + * @param {number} miterLimit + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setMiterLimit + */ + + + API.setLineMiterLimit = function (miterLimit) { + out(hpf(miterLimit) + " M"); + return this; + }; + /** + * Sets the line dash pattern. + * @param {Array} array An array containing 0-2 numbers. The first number sets the length of the + * dashes, the second number the length of the gaps. If the second number is missing, the gaps are considered + * to be as long as the dashes. An empty array means solid, unbroken lines. + * @param phase The phase lines start with. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setLineDashPattern + */ + + + API.setLineDashPattern = function (array, phase) { + out(["[" + (array[0] !== undefined ? array[0] : ""), (array[1] !== undefined ? array[1] : "") + "]", phase, "d"].join(" ")); + return this; + }; + /** + * Generates the PDF document. + * + * If `type` argument is undefined, output is raw body of resulting PDF returned as a string. + * + * @param {string} type A string identifying one of the possible output types. + * @param {Object} options An object providing some additional signalling to PDF generator. + * + * @function + * @instance + * @returns {jsPDF} + * @memberOf jsPDF + * @name output + */ + + + API.output = _output; + /** + * Saves as PDF document. An alias of jsPDF.output('save', 'filename.pdf') + * + * @memberOf jsPDF + * @name save + * @function + * @instance + * @param {string} filename The filename including extension. + * @returns {jsPDF} jsPDF-instance + */ + + API.save = function (filename) { + API.output("save", filename); + }; // applying plugins (more methods) ON TOP of built-in API. + // this is intentional as we allow plugins to override + // built-ins + + + for (var plugin in jsPDF.API) { + if (jsPDF.API.hasOwnProperty(plugin)) { + if (plugin === "events" && jsPDF.API.events.length) { + (function (events, newEvents) { + // jsPDF.API.events is a JS Array of Arrays + // where each Array is a pair of event name, handler + // Events were added by plugins to the jsPDF instantiator. + // These are always added to the new instance and some ran + // during instantiation. + var eventname, handler_and_args, i; + + for (i = newEvents.length - 1; i !== -1; i--) { + // subscribe takes 3 args: 'topic', function, runonce_flag + // if undefined, runonce is false. + // users can attach callback directly, + // or they can attach an array with [callback, runonce_flag] + // that's what the "apply" magic is for below. + eventname = newEvents[i][0]; + handler_and_args = newEvents[i][1]; + events.subscribe.apply(events, [eventname].concat(typeof handler_and_args === "function" ? [handler_and_args] : handler_and_args)); + } + })(events, jsPDF.API.events); + } else { + API[plugin] = jsPDF.API[plugin]; + } + } + } ////////////////////////////////////////////////////// + // continuing initialization of jsPDF Document object + ////////////////////////////////////////////////////// + // Add the first page automatically + + + addFonts(); + activeFontKey = "F1"; + + _addPage(format, orientation); + + events.publish("initialized"); + return API; + } + /** + * jsPDF.API is a STATIC property of jsPDF class. + * jsPDF.API is an object you can add methods and properties to. + * The methods / properties you add will show up in new jsPDF objects. + * + * One property is prepopulated. It is the 'events' Object. Plugin authors can add topics, + * callbacks to this object. These will be reassigned to all new instances of jsPDF. + * + * @static + * @public + * @memberOf jsPDF + * @name API + * + * @example + * jsPDF.API.mymethod = function(){ + * // 'this' will be ref to internal API object. see jsPDF source + * // , so you can refer to built-in methods like so: + * // this.line(....) + * // this.text(....) + * } + * var pdfdoc = new jsPDF() + * pdfdoc.mymethod() // <- !!!!!! + */ + + + jsPDF.API = { + events: [] + }; + /** + * The version of jsPDF + * @name version + * @type {string} + * @memberOf jsPDF + */ + + jsPDF.version = "0.0.0"; + + if (typeof define === "function" && define.amd) { + define(function () { + return jsPDF; + }); + } else if (typeof module !== "undefined" && module.exports) { + module.exports = jsPDF; + module.exports.jsPDF = jsPDF; + } else { + global.jsPDF = jsPDF; + } + + return jsPDF; + }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")()); // `self` is undefined in Firefox for Android content script context + // while `this` is nsIContentFrameMessageManager + // with an attribute `content` that corresponds to the window + + /** + * @license + * Copyright (c) 2016 Alexander Weidt, + * https://github.com/BiggA94 + * + * Licensed under the MIT License. http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF AcroForm Plugin + * + * @name AcroForm + * @module + */ + (function (jsPDFAPI, globalObj) { + + var scope; + var pageHeight; + var scaleFactor = 1; + + var inherit = function inherit(child, parent) { + + child.prototype = Object.create(parent.prototype); + child.prototype.constructor = child; + }; + + var scale = function scale(x) { + return x * (scaleFactor / 1); // 1 = (96 / 72) + }; + + var createFormXObject = function createFormXObject(formObject) { + var xobj = new AcroFormXObject(); + var height = AcroFormAppearance.internal.getHeight(formObject) || 0; + var width = AcroFormAppearance.internal.getWidth(formObject) || 0; + xobj.BBox = [0, 0, width.toFixed(2), height.toFixed(2)]; + return xobj; + }; + + var setBitPosition = function setBitPosition(variable, position, value) { + variable = variable || 0; + value = value || 1; + var bitMask = 1; + bitMask = bitMask << position - 1; + + if (value == 1) { + // Set the Bit to 1 + var variable = variable | bitMask; + } else { + // Set the Bit to 0 + var variable = variable & ~bitMask; + } + + return variable; + }; + /** + * Calculating the Ff entry: + * + * The Ff entry contains flags, that have to be set bitwise In the Following + * the number in the Comment is the BitPosition + */ + + + var calculateFlagsOnOptions = function calculateFlagsOnOptions(flags, opts, PDFVersion) { + var PDFVersion = PDFVersion || 1.3; + var flags = flags || 0; // 1, readOnly + + if (opts.readOnly == true) { + flags = setBitPosition(flags, 1); + } // 2, required + + + if (opts.required == true) { + flags = setBitPosition(flags, 2); + } // 4, noExport + + + if (opts.noExport == true) { + flags = setBitPosition(flags, 3); + } // 13, multiline + + + if (opts.multiline == true) { + flags = setBitPosition(flags, 13); + } // 14, Password + + + if (opts.password) { + flags = setBitPosition(flags, 14); + } // 15, NoToggleToOff (Radio buttons only + + + if (opts.noToggleToOff) { + flags = setBitPosition(flags, 15); + } // 16, Radio + + + if (opts.radio) { + flags = setBitPosition(flags, 16); + } // 17, Pushbutton + + + if (opts.pushbutton) { + flags = setBitPosition(flags, 17); + } // 18, Combo (If not set, the choiceField is a listBox!!) + + + if (opts.combo) { + flags = setBitPosition(flags, 18); + } // 19, Edit + + + if (opts.edit) { + flags = setBitPosition(flags, 19); + } // 20, Sort + + + if (opts.sort) { + flags = setBitPosition(flags, 20); + } // 21, FileSelect, PDF 1.4... + + + if (opts.fileSelect && PDFVersion >= 1.4) { + flags = setBitPosition(flags, 21); + } // 22, MultiSelect (PDF 1.4) + + + if (opts.multiSelect && PDFVersion >= 1.4) { + flags = setBitPosition(flags, 22); + } // 23, DoNotSpellCheck (PDF 1.4) + + + if (opts.doNotSpellCheck && PDFVersion >= 1.4) { + flags = setBitPosition(flags, 23); + } // 24, DoNotScroll (PDF 1.4) + + + if (opts.doNotScroll == true && PDFVersion >= 1.4) { + flags = setBitPosition(flags, 24); + } // 25, RichText (PDF 1.4) + + + if (opts.richText && PDFVersion >= 1.4) { + flags = setBitPosition(flags, 25); + } + + return flags; + }; + + var calculateCoordinates = function calculateCoordinates(args) { + var x = args[0]; + var y = args[1]; + var w = args[2]; + var h = args[3]; + var coordinates = {}; + + if (Array.isArray(x)) { + x[0] = scale(x[0]); + x[1] = scale(x[1]); + x[2] = scale(x[2]); + x[3] = scale(x[3]); + } else { + x = scale(x); + y = scale(y); + w = scale(w); + h = scale(h); + } + + coordinates.lowerLeft_X = x || 0; + coordinates.lowerLeft_Y = scale(pageHeight) - y - h || 0; + coordinates.upperRight_X = x + w || 0; + coordinates.upperRight_Y = scale(pageHeight) - y || 0; + return [coordinates.lowerLeft_X.toFixed(2), coordinates.lowerLeft_Y.toFixed(2), coordinates.upperRight_X.toFixed(2), coordinates.upperRight_Y.toFixed(2)]; + }; + + var calculateAppearanceStream = function calculateAppearanceStream(formObject) { + if (formObject.appearanceStreamContent) { + // If appearanceStream is already set, use it + return formObject.appearanceStreamContent; + } + + if (!formObject.V && !formObject.DV) { + return; + } // else calculate it + + + var stream = []; + var text = formObject.V || formObject.DV; + var calcRes = calculateX(formObject, text); + stream.push("/Tx BMC"); + stream.push("q"); + stream.push("/F1 " + calcRes.fontSize.toFixed(2) + " Tf"); + stream.push("1 0 0 1 0 0 Tm"); // Text Matrix + + stream.push("BT"); // Begin Text + + stream.push(calcRes.text); + stream.push("ET"); // End Text + + stream.push("Q"); + stream.push("EMC"); + var appearanceStreamContent = new createFormXObject(formObject); + appearanceStreamContent.stream = stream.join("\n"); + return appearanceStreamContent; + }; + + var calculateX = function calculateX(formObject, text, font, maxFontSize) { + var maxFontSize = maxFontSize || 12; + var font = font || "helvetica"; + var returnValue = { + text: "", + fontSize: "" + }; // Remove Brackets + + text = text.substr(0, 1) == "(" ? text.substr(1) : text; + text = text.substr(text.length - 1) == ")" ? text.substr(0, text.length - 1) : text; // split into array of words + + var textSplit = text.split(" "); + var fontSize = maxFontSize; // The Starting fontSize (The Maximum) + + var lineSpacing = 2; + var borderPadding = 2; + var height = AcroFormAppearance.internal.getHeight(formObject) || 0; + height = height < 0 ? -height : height; + var width = AcroFormAppearance.internal.getWidth(formObject) || 0; + width = width < 0 ? -width : width; + + var isSmallerThanWidth = function isSmallerThanWidth(i, lastLine, fontSize) { + if (i + 1 < textSplit.length) { + var tmp = lastLine + " " + textSplit[i + 1]; + var TextWidth = calculateFontSpace(tmp, fontSize + "px", font).width; + var FieldWidth = width - 2 * borderPadding; + return TextWidth <= FieldWidth; + } else { + return false; + } + }; + + fontSize++; + + FontSize: while (true) { + var text = ""; + fontSize--; + var textHeight = calculateFontSpace("3", fontSize + "px", font).height; + var startY = formObject.multiline ? height - fontSize : (height - textHeight) / 2; + startY += lineSpacing; + var startX = -borderPadding; + var lastY = startY; + var firstWordInLine = 0, + lastWordInLine = 0; + var lastLength = 0; + + if (fontSize <= 0) { + // In case, the Text doesn't fit at all + fontSize = 12; + text = "(...) Tj\n"; + text += "% Width of Text: " + calculateFontSpace(text, "1px").width + ", FieldWidth:" + width + "\n"; + break; + } + + lastLength = calculateFontSpace(textSplit[0] + " ", fontSize + "px", font).width; + var lastLine = ""; + var lineCount = 0; + + Line: for (var i in textSplit) { + if (textSplit.hasOwnProperty(i)) { + lastLine += textSplit[i] + " "; // Remove last blank + + lastLine = lastLine.substr(lastLine.length - 1) == " " ? lastLine.substr(0, lastLine.length - 1) : lastLine; + var key = parseInt(i); + lastLength = calculateFontSpace(lastLine + " ", fontSize + "px", font).width; + var nextLineIsSmaller = isSmallerThanWidth(key, lastLine, fontSize); + var isLastWord = i >= textSplit.length - 1; + + if (nextLineIsSmaller && !isLastWord) { + lastLine += " "; + continue; // Line + } else if (!nextLineIsSmaller && !isLastWord) { + if (!formObject.multiline) { + continue FontSize; + } else { + if ((textHeight + lineSpacing) * (lineCount + 2) + lineSpacing > height) { + // If the Text is higher than the + // FieldObject + continue FontSize; + } + + lastWordInLine = key; // go on + } + } else if (isLastWord) { + lastWordInLine = key; + } else { + if (formObject.multiline && (textHeight + lineSpacing) * (lineCount + 2) + lineSpacing > height) { + // If the Text is higher than the FieldObject + continue FontSize; + } + } + + var line = ""; + + for (var x = firstWordInLine; x <= lastWordInLine; x++) { + line += textSplit[x] + " "; + } // Remove last blank + + + line = line.substr(line.length - 1) == " " ? line.substr(0, line.length - 1) : line; // lastLength -= blankSpace.width; + + lastLength = calculateFontSpace(line, fontSize + "px", font).width; // Calculate startX + + switch (formObject.Q) { + case 2: + // Right justified + startX = width - lastLength - borderPadding; + break; + + case 1: + // Q = 1 := Text-Alignment: Center + startX = (width - lastLength) / 2; + break; + + case 0: + default: + startX = borderPadding; + break; + } + + text += startX.toFixed(2) + " " + lastY.toFixed(2) + " Td\n"; + text += "(" + line + ") Tj\n"; // reset X in PDF + + text += -startX.toFixed(2) + " 0 Td\n"; // After a Line, adjust y position + + lastY = -(fontSize + lineSpacing); + + lastLength = 0; + firstWordInLine = lastWordInLine + 1; + lineCount++; + lastLine = ""; + continue Line; + } + } + + break; + } + + returnValue.text = text; + returnValue.fontSize = fontSize; + return returnValue; + }; + /** + * Small workaround for calculating the TextMetric approximately. + * + * @param text + * @param fontsize + * @returns {TextMetrics} (Has Height and Width) + */ + + + var calculateFontSpace = function calculateFontSpace(text, fontSize, fontType) { + fontType = fontType || "helvetica"; + var font = scope.internal.getFont(fontType); + var width = scope.getStringUnitWidth(text, { + font: font, + fontSize: parseFloat(fontSize), + charSpace: 0 + }) * parseFloat(fontSize); + var height = scope.getStringUnitWidth("3", { + font: font, + fontSize: parseFloat(fontSize), + charSpace: 0 + }) * parseFloat(fontSize) * 1.5; + var result = { + height: height, + width: width + }; + return result; + }; + + var acroformPluginTemplate = { + fields: [], + xForms: [], + + /** + * acroFormDictionaryRoot contains information about the AcroForm + * Dictionary 0: The Event-Token, the AcroFormDictionaryCallback has + * 1: The Object ID of the Root + */ + acroFormDictionaryRoot: null, + + /** + * After the PDF gets evaluated, the reference to the root has to be + * reset, this indicates, whether the root has already been printed + * out + */ + printedOut: false, + internal: null, + isInitialized: false + }; + + var annotReferenceCallback = function annotReferenceCallback() { + var fields = scope.internal.acroformPlugin.acroFormDictionaryRoot.Fields; + + for (var i in fields) { + if (fields.hasOwnProperty(i)) { + var formObject = fields[i]; // add Annot Reference! + + if (formObject.hasAnnotation) { + // If theres an Annotation Widget in the Form Object, put the + // Reference in the /Annot array + createAnnotationReference.call(scope, formObject); + } + } + } + }; + + var putForm = function putForm(formObject) { + if (scope.internal.acroformPlugin.printedOut) { + scope.internal.acroformPlugin.printedOut = false; + scope.internal.acroformPlugin.acroFormDictionaryRoot = null; + } + + if (!scope.internal.acroformPlugin.acroFormDictionaryRoot) { + initializeAcroForm.call(scope); + } + + scope.internal.acroformPlugin.acroFormDictionaryRoot.Fields.push(formObject); + }; + /** + * Create the Reference to the widgetAnnotation, so that it gets referenced + * in the Annot[] int the+ (Requires the Annotation Plugin) + */ + + + var createAnnotationReference = function createAnnotationReference(object) { + var options = { + type: "reference", + object: object + }; + scope.annotationPlugin.annotations[scope.internal.getPageInfo(object.page).pageNumber].push(options); + }; // Callbacks + + + var putCatalogCallback = function putCatalogCallback() { + // Put reference to AcroForm to DocumentCatalog + if (typeof scope.internal.acroformPlugin.acroFormDictionaryRoot != "undefined") { + // for safety, shouldn't normally be the case + scope.internal.write("/AcroForm " + scope.internal.acroformPlugin.acroFormDictionaryRoot.objId + " " + 0 + " R"); + } else { + console.log("Root missing..."); + } + }; + /** + * Adds /Acroform X 0 R to Document Catalog, and creates the AcroForm + * Dictionary + */ + + + var AcroFormDictionaryCallback = function AcroFormDictionaryCallback() { + // Remove event + scope.internal.events.unsubscribe(scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID); + delete scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID; + scope.internal.acroformPlugin.printedOut = true; + }; + /** + * Creates the single Fields and writes them into the Document + * + * If fieldArray is set, use the fields that are inside it instead of the + * fields from the AcroRoot (for the FormXObjects...) + */ + + + var createFieldCallback = function createFieldCallback(fieldArray) { + var standardFields = !fieldArray; + + if (!fieldArray) { + // in case there is no fieldArray specified, we want to print out + // the Fields of the AcroForm + // Print out Root + scope.internal.newObjectDeferredBegin(scope.internal.acroformPlugin.acroFormDictionaryRoot.objId); + scope.internal.out(scope.internal.acroformPlugin.acroFormDictionaryRoot.getString()); + } + + var fieldArray = fieldArray || scope.internal.acroformPlugin.acroFormDictionaryRoot.Kids; + + for (var i in fieldArray) { + if (fieldArray.hasOwnProperty(i)) { + var form = fieldArray[i]; + var oldRect = form.Rect; + + if (form.Rect) { + form.Rect = calculateCoordinates.call(this, form.Rect); + } // Start Writing the Object + + + scope.internal.newObjectDeferredBegin(form.objId); + var content = form.objId + " 0 obj\n<<\n"; + + if (_typeof(form) === "object" && typeof form.getContent === "function") { + content += form.getContent(); + } + + form.Rect = oldRect; + + if (form.hasAppearanceStream && !form.appearanceStreamContent) { + // Calculate Appearance + var appearance = calculateAppearanceStream.call(this, form); + content += "/AP << /N " + appearance + " >>\n"; + scope.internal.acroformPlugin.xForms.push(appearance); + } // Assume AppearanceStreamContent is a Array with N,R,D (at least + // one of them!) + + + if (form.appearanceStreamContent) { + content += "/AP << "; // Iterate over N,R and D + + for (var k in form.appearanceStreamContent) { + if (form.appearanceStreamContent.hasOwnProperty(k)) { + var value = form.appearanceStreamContent[k]; + content += "/" + k + " "; + content += "<< "; + + if (Object.keys(value).length >= 1 || Array.isArray(value)) { + // appearanceStream is an Array or Object! + for (var i in value) { + if (value.hasOwnProperty(i)) { + var obj = value[i]; + + if (typeof obj === "function") { + // if Function is referenced, call it in order + // to get the FormXObject + obj = obj.call(this, form); + } + + content += "/" + i + " " + obj + " "; // In case the XForm is already used, e.g. OffState + // of CheckBoxes, don't add it + + if (!(scope.internal.acroformPlugin.xForms.indexOf(obj) >= 0)) scope.internal.acroformPlugin.xForms.push(obj); + } + } + } else { + var obj = value; + + if (typeof obj === "function") { + // if Function is referenced, call it in order to + // get the FormXObject + obj = obj.call(this, form); + } + + content += "/" + i + " " + obj + " \n"; + if (!(scope.internal.acroformPlugin.xForms.indexOf(obj) >= 0)) scope.internal.acroformPlugin.xForms.push(obj); + } + + content += " >>\n"; + } + } // appearance stream is a normal Object.. + + + content += ">>\n"; + } + + content += ">>\nendobj\n"; + scope.internal.out(content); + } + } + + if (standardFields) { + createXFormObjectCallback.call(this, scope.internal.acroformPlugin.xForms); + } + }; + + var createXFormObjectCallback = function createXFormObjectCallback(fieldArray) { + for (var i in fieldArray) { + if (fieldArray.hasOwnProperty(i)) { + var key = i; + var form = fieldArray[i]; // Start Writing the Object + + scope.internal.newObjectDeferredBegin(form && form.objId); + var content = ""; + + if (_typeof(form) === "object" && typeof form.getString === "function") { + content = form.getString(); + } + + scope.internal.out(content); + delete fieldArray[key]; + } + } + }; + + var initializeAcroForm = function initializeAcroForm() { + if (this.internal !== undefined && (this.internal.acroformPlugin === undefined || this.internal.acroformPlugin.isInitialized === false)) { + scope = this; + AcroFormField.FieldNum = 0; + this.internal.acroformPlugin = JSON.parse(JSON.stringify(acroformPluginTemplate)); + + if (this.internal.acroformPlugin.acroFormDictionaryRoot) { + // return; + throw new Error("Exception while creating AcroformDictionary"); + } + + scaleFactor = scope.internal.scaleFactor; + pageHeight = scope.internal.pageSize.getHeight(); // The Object Number of the AcroForm Dictionary + + scope.internal.acroformPlugin.acroFormDictionaryRoot = new AcroFormDictionary(); // add Callback for creating the AcroForm Dictionary + + scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID = scope.internal.events.subscribe("postPutResources", AcroFormDictionaryCallback); + scope.internal.events.subscribe("buildDocument", annotReferenceCallback); // buildDocument + // Register event, that is triggered when the DocumentCatalog is + // written, in order to add /AcroForm + + scope.internal.events.subscribe("putCatalog", putCatalogCallback); // Register event, that creates all Fields + + scope.internal.events.subscribe("postPutPages", createFieldCallback); + scope.internal.acroformPlugin.isInitialized = true; + } + }; + + var arrayToPdfArray = function arrayToPdfArray(array) { + if (Array.isArray(array)) { + var content = " ["; + + for (var i in array) { + if (array.hasOwnProperty(i)) { + var element = array[i].toString(); + content += element; + content += i < array.length - 1 ? " " : ""; + } + } + + content += "]"; + return content; + } + }; + + var toPdfString = function toPdfString(string) { + string = string || ""; // put Bracket at the Beginning of the String + + if (string.indexOf("(") !== 0) { + string = "(" + string; + } + + if (string.substring(string.length - 1) != ")") { + string += ")"; + } + + return string; + }; // ########################## + // Classes + // ########################## + + + var AcroFormPDFObject = function AcroFormPDFObject() { + // The Object ID in the PDF Object Model + // todo + var _objId; + + Object.defineProperty(this, "objId", { + get: function get() { + if (!_objId) { + _objId = scope.internal.newObjectDeferred(); + } + + if (!_objId) { + console.log("Couldn't create Object ID"); + } + + return _objId; + }, + configurable: false + }); + }; + + AcroFormPDFObject.prototype.toString = function () { + return this.objId + " 0 R"; + }; + + AcroFormPDFObject.prototype.getString = function () { + var res = this.objId + " 0 obj\n<<"; + var content = this.getContent(); + res += content + ">>\n"; + + if (this.stream) { + res += "stream\n"; + res += this.stream; + res += "\nendstream\n"; + } + + res += "endobj\n"; + return res; + }; + + AcroFormPDFObject.prototype.getContent = function () { + /** + * Prints out all enumerable Variables from the Object + * + * @param fieldObject + * @returns {string} + */ + var createContentFromFieldObject = function createContentFromFieldObject(fieldObject) { + var content = ""; + var keys = Object.keys(fieldObject).filter(function (key) { + return key != "content" && key != "appearanceStreamContent" && key.substring(0, 1) != "_"; + }); + + for (var i in keys) { + if (keys.hasOwnProperty(i)) { + var key = keys[i]; + var value = fieldObject[key]; + /* + * if (key == 'Rect' && value) { value = + * AcroForm.internal.calculateCoordinates.call(jsPDF.API.acroformPlugin.internal, + * value); } + */ + + if (value) { + if (Array.isArray(value)) { + content += "/" + key + " " + arrayToPdfArray(value) + "\n"; + } else if (value instanceof AcroFormPDFObject) { + // In case it is a reference to another PDFObject, + // take the referennce number + content += "/" + key + " " + value.objId + " 0 R" + "\n"; + } else { + content += "/" + key + " " + value + "\n"; + } + } + } + } + + return content; + }; + + var object = ""; + object += createContentFromFieldObject(this); + return object; + }; + + var AcroFormXObject = function AcroFormXObject() { + AcroFormPDFObject.call(this); + this.Type = "/XObject"; + this.Subtype = "/Form"; + this.FormType = 1; + this.BBox; + this.Matrix; + this.Resources = "2 0 R"; + this.PieceInfo; + + var _stream; + + Object.defineProperty(this, "Length", { + enumerable: true, + get: function get() { + return _stream !== undefined ? _stream.length : 0; + } + }); + Object.defineProperty(this, "stream", { + enumerable: false, + set: function set(val) { + _stream = val.trim(); + }, + get: function get() { + if (_stream) { + return _stream; + } else { + return null; + } + } + }); + }; + + inherit(AcroFormXObject, AcroFormPDFObject); // ##### The Objects, the User can Create: + + var AcroFormDictionary = function AcroFormDictionary() { + AcroFormPDFObject.call(this); + var _Kids = []; + Object.defineProperty(this, "Kids", { + enumerable: false, + configurable: true, + get: function get() { + if (_Kids.length > 0) { + return _Kids; + } else { + return; + } + } + }); + Object.defineProperty(this, "Fields", { + enumerable: true, + configurable: true, + get: function get() { + return _Kids; + } + }); // Default Appearance + + this.DA; + }; + + inherit(AcroFormDictionary, AcroFormPDFObject); // The Field Object contains the Variables, that every Field needs + // Rectangle for Appearance: lower_left_X, lower_left_Y, width, height + + var AcroFormField = function AcroFormField() { + + AcroFormPDFObject.call(this); + var _Rect = null; + Object.defineProperty(this, "Rect", { + enumerable: true, + configurable: false, + get: function get() { + if (!_Rect) { + return; + } + + var tmp = _Rect; // var calculatedRes = + // AcroForm.internal.calculateCoordinates(_Rect); // do + // later! + + return tmp; + }, + set: function set(val) { + _Rect = val; + } + }); + var _FT = ""; + Object.defineProperty(this, "FT", { + enumerable: true, + set: function set(val) { + _FT = val; + }, + get: function get() { + return _FT; + } + }); + var _F = 4; + Object.defineProperty(this, "F", { + enumerable: true, + set: function set(val) { + _F = val; + }, + get: function get() { + return _F; + } + }); + /** + * The Partial name of the Field Object. It has to be unique. + */ + + var _T = null; + Object.defineProperty(this, "T", { + enumerable: true, + configurable: false, + set: function set(val) { + _T = val; + }, + get: function get() { + if (!_T || _T.length < 1) { + if (this instanceof AcroFormChildClass) { + // In case of a Child from a Radio´Group, you don't + // need a FieldName!!! + return; + } + + return "(FieldObject" + AcroFormField.FieldNum++ + ")"; + } + + if (_T.substring(0, 1) == "(" && _T.substring(_T.length - 1)) { + return _T; + } + + return "(" + _T + ")"; + } + }); + var _DA = null; // Defines the default appearance (Needed for variable Text) + + Object.defineProperty(this, "DA", { + enumerable: true, + get: function get() { + if (!_DA) { + return; + } + + return "(" + _DA + ")"; + }, + set: function set(val) { + _DA = val; + } + }); + var _DV = null; // Defines the default value + + Object.defineProperty(this, "DV", { + enumerable: true, + configurable: true, + get: function get() { + if (!_DV) { + return; + } + + return _DV; + }, + set: function set(val) { + _DV = val; + } + }); + var _V = null; // Defines the default value + + Object.defineProperty(this, "V", { + enumerable: true, + configurable: true, + get: function get() { + if (!_V) { + return; + } + + return _V; + }, + set: function set(val) { + _V = val; + } + }); // this.Type = "/Annot"; + // this.Subtype = "/Widget"; + + Object.defineProperty(this, "Type", { + enumerable: true, + get: function get() { + return this.hasAnnotation ? "/Annot" : null; + } + }); + Object.defineProperty(this, "Subtype", { + enumerable: true, + get: function get() { + return this.hasAnnotation ? "/Widget" : null; + } + }); + /** + * + * @type {Array} + */ + + this.BG; + Object.defineProperty(this, "hasAnnotation", { + enumerable: false, + get: function get() { + if (this.Rect || this.BC || this.BG) { + return true; + } + + return false; + } + }); + Object.defineProperty(this, "hasAppearanceStream", { + enumerable: false, + configurable: true, + writable: true + }); + Object.defineProperty(this, "page", { + enumerable: false, + configurable: true, + writable: true + }); + }; + + inherit(AcroFormField, AcroFormPDFObject); + + var AcroFormChoiceField = function AcroFormChoiceField() { + AcroFormField.call(this); // Field Type = Choice Field + + this.FT = "/Ch"; // options + + this.Opt = []; + this.V = "()"; // Top Index + + this.TI = 0; + /** + * Defines, whether the + * + * @type {boolean} + */ + + var _combo = false; + Object.defineProperty(this, "combo", { + enumerable: false, + get: function get() { + return _combo; + }, + set: function set(val) { + _combo = val; + } + }); + /** + * Defines, whether the Choice Field is an Edit Field. An Edit Field + * is automatically an Combo Field. + */ + + Object.defineProperty(this, "edit", { + enumerable: true, + set: function set(val) { + if (val == true) { + this._edit = true; // ComboBox has to be true + + this.combo = true; + } else { + this._edit = false; + } + }, + get: function get() { + if (!this._edit) { + return false; + } + + return this._edit; + }, + configurable: false + }); + this.hasAppearanceStream = true; + }; + + inherit(AcroFormChoiceField, AcroFormField); + + var AcroFormListBox = function AcroFormListBox() { + AcroFormChoiceField.call(this); + this.combo = false; + }; + + inherit(AcroFormListBox, AcroFormChoiceField); + + var AcroFormComboBox = function AcroFormComboBox() { + AcroFormListBox.call(this); + this.combo = true; + }; + + inherit(AcroFormComboBox, AcroFormListBox); + + var AcroFormEditBox = function AcroFormEditBox() { + AcroFormComboBox.call(this); + this.edit = true; + }; + + inherit(AcroFormEditBox, AcroFormComboBox); + + var AcroFormButton = function AcroFormButton() { + AcroFormField.call(this); + this.FT = "/Btn"; // this.hasAnnotation = true; + }; + + inherit(AcroFormButton, AcroFormField); + + var AcroFormPushButton = function AcroFormPushButton() { + AcroFormButton.call(this); + var _pushbutton = true; + Object.defineProperty(this, "pushbutton", { + enumerable: false, + get: function get() { + return _pushbutton; + }, + set: function set(val) { + _pushbutton = val; + } + }); + }; + + inherit(AcroFormPushButton, AcroFormButton); + + var AcroFormRadioButton = function AcroFormRadioButton() { + AcroFormButton.call(this); + var _radio = true; + Object.defineProperty(this, "radio", { + enumerable: false, + get: function get() { + return _radio; + }, + set: function set(val) { + _radio = val; + } + }); + var _Kids = []; + Object.defineProperty(this, "Kids", { + enumerable: true, + get: function get() { + if (_Kids.length > 0) { + return _Kids; + } + } + }); + Object.defineProperty(this, "__Kids", { + get: function get() { + return _Kids; + } + }); + + var _noToggleToOff; + + Object.defineProperty(this, "noToggleToOff", { + enumerable: false, + get: function get() { + return _noToggleToOff; + }, + set: function set(val) { + _noToggleToOff = val; + } + }); // this.hasAnnotation = false; + }; + + inherit(AcroFormRadioButton, AcroFormButton); + /* + * The Child classs of a RadioButton (the radioGroup) -> The single + * Buttons + */ + + var AcroFormChildClass = function AcroFormChildClass(parent, name) { + AcroFormField.call(this); + this.Parent = parent; // todo: set AppearanceType as variable that can be set from the + // outside... + + this._AppearanceType = AcroFormAppearance.RadioButton.Circle; // The Default appearanceType is the Circle + + this.appearanceStreamContent = this._AppearanceType.createAppearanceStream(name); // Set Print in the Annot Flag + + this.F = setBitPosition(this.F, 3, 1); // Set AppearanceCharacteristicsDictionary with default appearance + // if field is not interacting with user + + this.MK = this._AppearanceType.createMK(); // (8) -> Cross, (1)-> Circle, ()-> nothing + // Default Appearance is Off + + this.AS = "/Off"; // + name; + + this._Name = name; + }; + + inherit(AcroFormChildClass, AcroFormField); + + AcroFormRadioButton.prototype.setAppearance = function (appearance) { + if (!("createAppearanceStream" in appearance && "createMK" in appearance)) { + console.log("Couldn't assign Appearance to RadioButton. Appearance was Invalid!"); + return; + } + + for (var i in this.__Kids) { + if (this.__Kids.hasOwnProperty(i)) { + var child = this.__Kids[i]; + child.appearanceStreamContent = appearance.createAppearanceStream(child._Name); + child.MK = appearance.createMK(); + } + } + }; + + AcroFormRadioButton.prototype.createOption = function (name) { + var parent = this; + var kidCount = this.__Kids.length; // Create new Child for RadioGroup + + var child = new AcroFormChildClass(parent, name); // Add to Parent + + this.__Kids.push(child); + + jsPDFAPI.addField(child); + return child; + }; + /** + * @name AcroFormCheckBox + * + * @memberOf AcroForm + * @function + */ + + + var AcroFormCheckBox = function AcroFormCheckBox() { + AcroFormButton.call(this); + this.appearanceStreamContent = AcroFormAppearance.CheckBox.createAppearanceStream(); + this.MK = AcroFormAppearance.CheckBox.createMK(); + this.AS = "/On"; + this.V = "/On"; + }; + + inherit(AcroFormCheckBox, AcroFormButton); + + var AcroFormTextField = function AcroFormTextField() { + AcroFormField.call(this); + this.DA = AcroFormAppearance.createDefaultAppearanceStream(); + this.F = 4; + + var _V; + + Object.defineProperty(this, "V", { + get: function get() { + if (_V) { + return toPdfString(_V); + } else { + return _V; + } + }, + enumerable: true, + set: function set(val) { + _V = val; + } + }); + + var _DV; + + Object.defineProperty(this, "DV", { + get: function get() { + if (_DV) { + return toPdfString(_DV); + } else { + return _DV; + } + }, + enumerable: true, + set: function set(val) { + _DV = val; + } + }); + var _multiline = false; + Object.defineProperty(this, "multiline", { + enumerable: false, + get: function get() { + return _multiline; + }, + set: function set(val) { + _multiline = val; + } + }); + /** + * For PDF 1.4 + * + * @type {boolean} + */ + + var _fileSelect = false; + Object.defineProperty(this, "fileSelect", { + enumerable: false, + get: function get() { + return _fileSelect; + }, + set: function set(val) { + _fileSelect = val; + } + }); + /** + * For PDF 1.4 + * + * @type {boolean} + */ + + var _doNotSpellCheck = false; + Object.defineProperty(this, "doNotSpellCheck", { + enumerable: false, + get: function get() { + return _doNotSpellCheck; + }, + set: function set(val) { + _doNotSpellCheck = val; + } + }); + /** + * For PDF 1.4 + * + * @type {boolean} + */ + + var _doNotScroll = false; + Object.defineProperty(this, "doNotScroll", { + enumerable: false, + get: function get() { + return _doNotScroll; + }, + set: function set(val) { + _doNotScroll = val; + } + }); + var _MaxLen = false; + Object.defineProperty(this, "MaxLen", { + enumerable: true, + get: function get() { + return _MaxLen; + }, + set: function set(val) { + _MaxLen = val; + } + }); + Object.defineProperty(this, "hasAppearanceStream", { + enumerable: false, + get: function get() { + return this.V || this.DV; + } + }); + }; + + inherit(AcroFormTextField, AcroFormField); + + var AcroFormPasswordField = function AcroFormPasswordField() { + AcroFormTextField.call(this); + var _password = true; + Object.defineProperty(this, "password", { + enumerable: false, + get: function get() { + return _password; + }, + set: function set(val) { + _password = val; + } + }); + }; + + inherit(AcroFormPasswordField, AcroFormTextField); // Contains Methods for creating standard appearances + + var AcroFormAppearance = { + CheckBox: { + createAppearanceStream: function createAppearanceStream() { + var appearance = { + N: { + On: AcroFormAppearance.CheckBox.YesNormal + }, + D: { + On: AcroFormAppearance.CheckBox.YesPushDown, + Off: AcroFormAppearance.CheckBox.OffPushDown + } + }; + return appearance; + }, + + /** + * If any other icons are needed, the number between the + * brackets can be changed + * + * @returns {string} + */ + createMK: function createMK() { + return "<< /CA (3)>>"; + }, + + /** + * Returns the standard On Appearance for a CheckBox + * + * @returns {AcroFormXObject} + */ + YesPushDown: function YesPushDown(formObject) { + var xobj = createFormXObject(formObject); + var stream = []; + var zapfDingbatsId = scope.internal.getFont("zapfdingbats", "normal").id; + formObject.Q = 1; // set text-alignment as centered + + var calcRes = calculateX(formObject, "3", "ZapfDingbats", 50); + stream.push("0.749023 g"); + stream.push("0 0 " + AcroFormAppearance.internal.getWidth(formObject).toFixed(2) + " " + AcroFormAppearance.internal.getHeight(formObject).toFixed(2) + " re"); + stream.push("f"); + stream.push("BMC"); + stream.push("q"); + stream.push("0 0 1 rg"); + stream.push("/" + zapfDingbatsId + " " + calcRes.fontSize.toFixed(2) + " Tf 0 g"); + stream.push("BT"); + stream.push(calcRes.text); + stream.push("ET"); + stream.push("Q"); + stream.push("EMC"); + xobj.stream = stream.join("\n"); + return xobj; + }, + YesNormal: function YesNormal(formObject) { + var xobj = createFormXObject(formObject); + var zapfDingbatsId = scope.internal.getFont("zapfdingbats", "normal").id; + var stream = []; + formObject.Q = 1; // set text-alignment as centered + + var height = AcroFormAppearance.internal.getHeight(formObject); + var width = AcroFormAppearance.internal.getWidth(formObject); + var calcRes = calculateX(formObject, "3", "ZapfDingbats", height * 0.9); + stream.push("1 g"); + stream.push("0 0 " + width.toFixed(2) + " " + height.toFixed(2) + " re"); + stream.push("f"); + stream.push("q"); + stream.push("0 0 1 rg"); + stream.push("0 0 " + (width - 1).toFixed(2) + " " + (height - 1).toFixed(2) + " re"); + stream.push("W"); + stream.push("n"); + stream.push("0 g"); + stream.push("BT"); + stream.push("/" + zapfDingbatsId + " " + calcRes.fontSize.toFixed(2) + " Tf 0 g"); + stream.push(calcRes.text); + stream.push("ET"); + stream.push("Q"); + xobj.stream = stream.join("\n"); + return xobj; + }, + + /** + * Returns the standard Off Appearance for a CheckBox + * + * @returns {AcroFormXObject} + */ + OffPushDown: function OffPushDown(formObject) { + var xobj = createFormXObject(formObject); + var stream = []; + stream.push("0.749023 g"); + stream.push("0 0 " + AcroFormAppearance.internal.getWidth(formObject).toFixed(2) + " " + AcroFormAppearance.internal.getHeight(formObject).toFixed(2) + " re"); + stream.push("f"); + xobj.stream = stream.join("\n"); + return xobj; + } + }, + RadioButton: { + Circle: { + createAppearanceStream: function createAppearanceStream(name) { + var appearanceStreamContent = { + D: { + Off: AcroFormAppearance.RadioButton.Circle.OffPushDown + }, + N: {} + }; + appearanceStreamContent.N[name] = AcroFormAppearance.RadioButton.Circle.YesNormal; + appearanceStreamContent.D[name] = AcroFormAppearance.RadioButton.Circle.YesPushDown; + return appearanceStreamContent; + }, + createMK: function createMK() { + return "<< /CA (l)>>"; + }, + YesNormal: function YesNormal(formObject) { + var xobj = createFormXObject(formObject); + var stream = []; // Make the Radius of the Circle relative to min(height, + // width) of formObject + + var DotRadius = AcroFormAppearance.internal.getWidth(formObject) <= AcroFormAppearance.internal.getHeight(formObject) ? AcroFormAppearance.internal.getWidth(formObject) / 4 : AcroFormAppearance.internal.getHeight(formObject) / 4; // The Borderpadding... + + DotRadius *= 0.9; + var c = AcroFormAppearance.internal.Bezier_C; + /* + * The Following is a Circle created with Bezier-Curves. + */ + + stream.push("q"); + stream.push("1 0 0 1 " + AcroFormAppearance.internal.getWidth(formObject) / 2 + " " + AcroFormAppearance.internal.getHeight(formObject) / 2 + " cm"); + stream.push(DotRadius + " 0 m"); + stream.push(DotRadius + " " + DotRadius * c + " " + DotRadius * c + " " + DotRadius + " 0 " + DotRadius + " c"); + stream.push("-" + DotRadius * c + " " + DotRadius + " -" + DotRadius + " " + DotRadius * c + " -" + DotRadius + " 0 c"); + stream.push("-" + DotRadius + " -" + DotRadius * c + " -" + DotRadius * c + " -" + DotRadius + " 0 -" + DotRadius + " c"); + stream.push(DotRadius * c + " -" + DotRadius + " " + DotRadius + " -" + DotRadius * c + " " + DotRadius + " 0 c"); + stream.push("f"); + stream.push("Q"); + xobj.stream = stream.join("\n"); + return xobj; + }, + YesPushDown: function YesPushDown(formObject) { + var xobj = createFormXObject(formObject); + var stream = []; + var DotRadius = AcroFormAppearance.internal.getWidth(formObject) <= AcroFormAppearance.internal.getHeight(formObject) ? AcroFormAppearance.internal.getWidth(formObject) / 4 : AcroFormAppearance.internal.getHeight(formObject) / 4; // The Borderpadding... + + DotRadius *= 0.9; // Save results for later use; no need to waste + // processor ticks on doing math + + var k = DotRadius * 2; // var c = AcroFormAppearance.internal.Bezier_C; + + var kc = k * AcroFormAppearance.internal.Bezier_C; + var dc = DotRadius * AcroFormAppearance.internal.Bezier_C; + stream.push("0.749023 g"); + stream.push("q"); + stream.push("1 0 0 1 " + (AcroFormAppearance.internal.getWidth(formObject) / 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) / 2).toFixed(2) + " cm"); + stream.push(k + " 0 m"); + stream.push(k + " " + kc + " " + kc + " " + k + " 0 " + k + " c"); + stream.push("-" + kc + " " + k + " -" + k + " " + kc + " -" + k + " 0 c"); + stream.push("-" + k + " -" + kc + " -" + kc + " -" + k + " 0 -" + k + " c"); + stream.push(kc + " -" + k + " " + k + " -" + kc + " " + k + " 0 c"); + stream.push("f"); + stream.push("Q"); + stream.push("0 g"); + stream.push("q"); + stream.push("1 0 0 1 " + (AcroFormAppearance.internal.getWidth(formObject) / 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) / 2).toFixed(2) + " cm"); + stream.push(DotRadius + " 0 m"); + stream.push("" + DotRadius + " " + dc + " " + dc + " " + DotRadius + " 0 " + DotRadius + " c"); + stream.push("-" + dc + " " + DotRadius + " -" + DotRadius + " " + dc + " -" + DotRadius + " 0 c"); + stream.push("-" + DotRadius + " -" + dc + " -" + dc + " -" + DotRadius + " 0 -" + DotRadius + " c"); + stream.push(dc + " -" + DotRadius + " " + DotRadius + " -" + dc + " " + DotRadius + " 0 c"); + stream.push("f"); + stream.push("Q"); + xobj.stream = stream.join("\n"); + return xobj; + }, + OffPushDown: function OffPushDown(formObject) { + var xobj = createFormXObject(formObject); + var stream = []; + var DotRadius = AcroFormAppearance.internal.getWidth(formObject) <= AcroFormAppearance.internal.getHeight(formObject) ? AcroFormAppearance.internal.getWidth(formObject) / 4 : AcroFormAppearance.internal.getHeight(formObject) / 4; // The Borderpadding... + + DotRadius *= 0.9; // Save results for later use; no need to waste + // processor ticks on doing math + + var k = DotRadius * 2; // var c = AcroFormAppearance.internal.Bezier_C; + + var kc = k * AcroFormAppearance.internal.Bezier_C; + stream.push("0.749023 g"); + stream.push("q"); + stream.push("1 0 0 1 " + (AcroFormAppearance.internal.getWidth(formObject) / 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) / 2).toFixed(2) + " cm"); + stream.push(k + " 0 m"); + stream.push(k + " " + kc + " " + kc + " " + k + " 0 " + k + " c"); + stream.push("-" + kc + " " + k + " -" + k + " " + kc + " -" + k + " 0 c"); + stream.push("-" + k + " -" + kc + " -" + kc + " -" + k + " 0 -" + k + " c"); + stream.push(kc + " -" + k + " " + k + " -" + kc + " " + k + " 0 c"); + stream.push("f"); + stream.push("Q"); + xobj.stream = stream.join("\n"); + return xobj; + } + }, + Cross: { + /** + * Creates the Actual AppearanceDictionary-References + * + * @param {string} name + * @returns {Object} + * @ignore + */ + createAppearanceStream: function createAppearanceStream(name) { + var appearanceStreamContent = { + D: { + Off: AcroFormAppearance.RadioButton.Cross.OffPushDown + }, + N: {} + }; + appearanceStreamContent.N[name] = AcroFormAppearance.RadioButton.Cross.YesNormal; + appearanceStreamContent.D[name] = AcroFormAppearance.RadioButton.Cross.YesPushDown; + return appearanceStreamContent; + }, + createMK: function createMK() { + return "<< /CA (8)>>"; + }, + YesNormal: function YesNormal(formObject) { + var xobj = createFormXObject(formObject); + var stream = []; + var cross = AcroFormAppearance.internal.calculateCross(formObject); + stream.push("q"); + stream.push("1 1 " + (AcroFormAppearance.internal.getWidth(formObject) - 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) - 2).toFixed(2) + " re"); + stream.push("W"); + stream.push("n"); + stream.push(cross.x1.x.toFixed(2) + " " + cross.x1.y.toFixed(2) + " m"); + stream.push(cross.x2.x.toFixed(2) + " " + cross.x2.y.toFixed(2) + " l"); + stream.push(cross.x4.x.toFixed(2) + " " + cross.x4.y.toFixed(2) + " m"); + stream.push(cross.x3.x.toFixed(2) + " " + cross.x3.y.toFixed(2) + " l"); + stream.push("s"); + stream.push("Q"); + xobj.stream = stream.join("\n"); + return xobj; + }, + YesPushDown: function YesPushDown(formObject) { + var xobj = createFormXObject(formObject); + var cross = AcroFormAppearance.internal.calculateCross(formObject); + var stream = []; + stream.push("0.749023 g"); + stream.push("0 0 " + AcroFormAppearance.internal.getWidth(formObject).toFixed(2) + " " + AcroFormAppearance.internal.getHeight(formObject).toFixed(2) + " re"); + stream.push("f"); + stream.push("q"); + stream.push("1 1 " + (AcroFormAppearance.internal.getWidth(formObject) - 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) - 2).toFixed(2) + " re"); + stream.push("W"); + stream.push("n"); + stream.push(cross.x1.x.toFixed(2) + " " + cross.x1.y.toFixed(2) + " m"); + stream.push(cross.x2.x.toFixed(2) + " " + cross.x2.y.toFixed(2) + " l"); + stream.push(cross.x4.x.toFixed(2) + " " + cross.x4.y.toFixed(2) + " m"); + stream.push(cross.x3.x.toFixed(2) + " " + cross.x3.y.toFixed(2) + " l"); + stream.push("s"); + stream.push("Q"); + xobj.stream = stream.join("\n"); + return xobj; + }, + OffPushDown: function OffPushDown(formObject) { + var xobj = createFormXObject(formObject); + var stream = []; + stream.push("0.749023 g"); + stream.push("0 0 " + AcroFormAppearance.internal.getWidth(formObject).toFixed(2) + " " + AcroFormAppearance.internal.getHeight(formObject).toFixed(2) + " re"); + stream.push("f"); + xobj.stream = stream.join("\n"); + return xobj; + } + } + }, + + /** + * Returns the standard Appearance + * + * @returns {AcroFormXObject} + */ + createDefaultAppearanceStream: function createDefaultAppearanceStream(formObject) { + // Set Helvetica to Standard Font (size: auto) + // Color: Black + return "/F1 0 Tf 0 g"; + } + }; + AcroFormAppearance.internal = { + Bezier_C: 0.551915024494, + calculateCross: function calculateCross(formObject) { + var min = function min(x, y) { + return x > y ? y : x; + }; + + var width = AcroFormAppearance.internal.getWidth(formObject); + var height = AcroFormAppearance.internal.getHeight(formObject); + var a = min(width, height); + + var cross = { + x1: { + // upperLeft + x: (width - a) / 2, + y: (height - a) / 2 + a // height - borderPadding + + }, + x2: { + // lowerRight + x: (width - a) / 2 + a, + y: (height - a) / 2 // borderPadding + + }, + x3: { + // lowerLeft + x: (width - a) / 2, + y: (height - a) / 2 // borderPadding + + }, + x4: { + // upperRight + x: (width - a) / 2 + a, + y: (height - a) / 2 + a // height - borderPadding + + } + }; + return cross; + } + }; + + AcroFormAppearance.internal.getWidth = function (formObject) { + var result = 0; + + if (_typeof(formObject) === "object") { + result = scale(formObject.Rect[2]); // (formObject.Rect[2] - + // formObject.Rect[0]) || 0; + } + + return result; + }; + + AcroFormAppearance.internal.getHeight = function (formObject) { + var result = 0; + + if (_typeof(formObject) === "object") { + result = scale(formObject.Rect[3]); // (formObject.Rect[1] - + // formObject.Rect[3]) || 0; + } + + return result; + }; // Public: + + /** + * Add an AcroForm-Field to the {jsPDF}-instance + * + * @memberOf AcroForm + * @name addField + * @param {Object} fieldObject + * @returns {jsPDF} + */ + + + jsPDFAPI.addField = function (fieldObject) { + initializeAcroForm.call(this); // var opt = parseOptions(fieldObject); + + if (fieldObject instanceof AcroFormTextField) { + this.addTextField.call(this, fieldObject); + } else if (fieldObject instanceof AcroFormChoiceField) { + this.addChoiceField.call(this, fieldObject); + } else if (fieldObject instanceof AcroFormButton) { + this.addButton.call(this, fieldObject); + } else if (fieldObject instanceof AcroFormChildClass) { + putForm.call(this, fieldObject); + } else if (fieldObject) { + // try to put.. + putForm.call(this, fieldObject); + } + + fieldObject.page = scope.internal.getCurrentPageInfo().pageNumber; + return this; + }; + /** + * @name addButton + * @param {AcroFormButton} + * @memberOf AcroForm + */ + + + jsPDFAPI.addButton = function (opts) { + initializeAcroForm.call(this); + var options = opts || new AcroFormField(); + options.FT = "/Btn"; + options.Ff = calculateFlagsOnOptions(options.Ff, opts, scope.internal.getPDFVersion()); + putForm.call(this, options); + }; + + jsPDFAPI.addTextField = function (opts) { + initializeAcroForm.call(this); + var options = opts || new AcroFormField(); + options.FT = "/Tx"; + options.Ff = calculateFlagsOnOptions(options.Ff, opts, scope.internal.getPDFVersion()); // Add field + + putForm.call(this, options); + }; + + jsPDFAPI.addChoiceField = function (opts) { + initializeAcroForm.call(this); + var options = opts || new AcroFormField(); + options.FT = "/Ch"; + options.Ff = calculateFlagsOnOptions(options.Ff, opts, scope.internal.getPDFVersion()); // options.hasAnnotation = true; + // Add field + + putForm.call(this, options); + }; + + if (_typeof(globalObj) == "object") { + globalObj["ChoiceField"] = AcroFormChoiceField; + globalObj["ListBox"] = AcroFormListBox; + globalObj["ComboBox"] = AcroFormComboBox; + globalObj["EditBox"] = AcroFormEditBox; + globalObj["Button"] = AcroFormButton; + globalObj["PushButton"] = AcroFormPushButton; + globalObj["RadioButton"] = AcroFormRadioButton; + globalObj["CheckBox"] = AcroFormCheckBox; + globalObj["TextField"] = AcroFormTextField; + globalObj["PasswordField"] = AcroFormPasswordField; // backwardsCompatibility + + globalObj["AcroForm"] = { + Appearance: AcroFormAppearance + }; + } + + jsPDFAPI.AcroFormChoiceField = AcroFormChoiceField; + jsPDFAPI.AcroFormListBox = AcroFormListBox; + jsPDFAPI.AcroFormComboBox = AcroFormComboBox; + jsPDFAPI.AcroFormEditBox = AcroFormEditBox; + jsPDFAPI.AcroFormButton = AcroFormButton; + jsPDFAPI.AcroFormPushButton = AcroFormPushButton; + jsPDFAPI.AcroFormRadioButton = AcroFormRadioButton; + jsPDFAPI.AcroFormCheckBox = AcroFormCheckBox; + jsPDFAPI.AcroFormTextField = AcroFormTextField; + jsPDFAPI.AcroFormPasswordField = AcroFormPasswordField; + jsPDFAPI.AcroFormAppearance = AcroFormAppearance; + jsPDFAPI.AcroForm = { + ChoiceField: AcroFormChoiceField, + ListBox: AcroFormListBox, + ComboBox: AcroFormComboBox, + EditBox: AcroFormEditBox, + Button: AcroFormButton, + PushButton: AcroFormPushButton, + RadioButton: AcroFormRadioButton, + CheckBox: AcroFormCheckBox, + TextField: AcroFormTextField, + PasswordField: AcroFormPasswordField, + Appearance: AcroFormAppearance + }; + })(jsPDF.API, typeof window !== "undefined" && window || typeof global !== "undefined" && global); + + /** @license + * jsPDF addImage plugin + * Copyright (c) 2012 Jason Siefken, https://github.com/siefkenj/ + * 2013 Chris Dowling, https://github.com/gingerchris + * 2013 Trinh Ho, https://github.com/ineedfat + * 2013 Edwin Alejandro Perez, https://github.com/eaparango + * 2013 Norah Smith, https://github.com/burnburnrocket + * 2014 Diego Casorran, https://github.com/diegocr + * 2014 James Robb, https://github.com/jamesbrobb + * + * + */ + + /** + * @name addImage + * @module + */ + (function (jsPDFAPI) { + + var namespace = "addImage_"; + var imageFileTypeHeaders = { + PNG: [[0x89, 0x50, 0x4e, 0x47]], + TIFF: [[0x4d, 0x4d, 0x00, 0x2a], //Motorola + [0x49, 0x49, 0x2a, 0x00] //Intel + ], + JPEG: [[0xff, 0xd8, 0xff, 0xe0, undefined, undefined, 0x4a, 0x46, 0x49, 0x46, 0x00], //JFIF + [0xff, 0xd8, 0xff, 0xe1, undefined, undefined, 0x45, 0x78, 0x69, 0x66, 0x00, 0x00] //Exif + ], + JPEG2000: [[0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20]], + GIF87a: [[0x47, 0x49, 0x46, 0x38, 0x37, 0x61]], + GIF89a: [[0x47, 0x49, 0x46, 0x38, 0x39, 0x61]], + BMP: [[0x42, 0x4d], //BM - Windows 3.1x, 95, NT, ... etc. + [0x42, 0x41], //BA - OS/2 struct bitmap array + [0x43, 0x49], //CI - OS/2 struct color icon + [0x43, 0x50], //CP - OS/2 const color pointer + [0x49, 0x43], //IC - OS/2 struct icon + [0x50, 0x54] //PT - OS/2 pointer + ] + }; + /** + * Recognize filetype of Image by magic-bytes + * + * https://en.wikipedia.org/wiki/List_of_file_signatures + * + * @name getImageFileTypeByImageData + * @public + * @function + * @param {string|arraybuffer} imageData imageData as base64 encoded DataUrl or arraybuffer + * @param {string} format format of file if filetype-recognition fails, e.g. 'JPEG' + * + * @returns {string} filetype of Image + */ + + jsPDFAPI.getImageFileTypeByImageData = function (imageData, fallbackFormat) { + fallbackFormat = fallbackFormat || "UNKNOWN"; + var i; + var j; + var result = "UNKNOWN"; + var headerSchemata; + var compareResult; + var fileType; + + if (jsPDFAPI.isArrayBufferView(imageData)) { + imageData = jsPDFAPI.arrayBufferToBinaryString(imageData); + } + + for (fileType in imageFileTypeHeaders) { + headerSchemata = imageFileTypeHeaders[fileType]; + + for (i = 0; i < headerSchemata.length; i += 1) { + compareResult = true; + + for (j = 0; j < headerSchemata[i].length; j += 1) { + if (headerSchemata[i][j] === undefined) { + continue; + } + + if (headerSchemata[i][j] !== imageData.charCodeAt(j)) { + compareResult = false; + break; + } + } + + if (compareResult === true) { + result = fileType; + break; + } + } + } + + if (result === "UNKNOWN" && fallbackFormat !== "UNKNOWN") { + console.warn('FileType of Image not recognized. Processing image as "' + fallbackFormat + '".'); + result = fallbackFormat; + } + + return result; + }; // Image functionality ported from pdf.js + + + var putImage = function putImage(img) { + var objectNumber = this.internal.newObject(), + out = this.internal.write, + putStream = this.internal.putStream; + img["n"] = objectNumber; + out("<>"); + } + + if ("trns" in img && img["trns"].constructor == Array) { + var trns = "", + i = 0, + len = img["trns"].length; + + for (; i < len; i++) { + trns += img["trns"][i] + " " + img["trns"][i] + " "; + } + + out("/Mask [" + trns + "]"); + } + + if ("smask" in img) { + out("/SMask " + (objectNumber + 1) + " 0 R"); + } + + out("/Length " + img["data"].length + ">>"); + putStream(img["data"]); + out("endobj"); // Soft mask + + if ("smask" in img) { + var dp = "/Predictor " + img["p"] + " /Colors 1 /BitsPerComponent " + img["bpc"] + " /Columns " + img["w"]; + var smask = { + w: img["w"], + h: img["h"], + cs: "DeviceGray", + bpc: img["bpc"], + dp: dp, + data: img["smask"] + }; + if ("f" in img) smask.f = img["f"]; + putImage.call(this, smask); + } //Palette + + + if (img["cs"] === this.color_spaces.INDEXED) { + this.internal.newObject(); //out('<< /Filter / ' + img['f'] +' /Length ' + img['pal'].length + '>>'); + //putStream(zlib.compress(img['pal'])); + + out("<< /Length " + img["pal"].length + ">>"); + putStream(this.arrayBufferToBinaryString(new Uint8Array(img["pal"]))); + out("endobj"); + } + }, + putResourcesCallback = function putResourcesCallback() { + var images = this.internal.collections[namespace + "images"]; + + for (var i in images) { + putImage.call(this, images[i]); + } + }, + putXObjectsDictCallback = function putXObjectsDictCallback() { + var images = this.internal.collections[namespace + "images"], + out = this.internal.write, + image; + + for (var i in images) { + image = images[i]; + out("/I" + image["i"], image["n"], "0", "R"); + } + }, + checkCompressValue = function checkCompressValue(value) { + if (value && typeof value === "string") value = value.toUpperCase(); + return value in jsPDFAPI.image_compression ? value : jsPDFAPI.image_compression.NONE; + }, + getImages = function getImages() { + var images = this.internal.collections[namespace + "images"]; //first run, so initialise stuff + + if (!images) { + this.internal.collections[namespace + "images"] = images = {}; + this.internal.events.subscribe("putResources", putResourcesCallback); + this.internal.events.subscribe("putXobjectDict", putXObjectsDictCallback); + } + + return images; + }, + getImageIndex = function getImageIndex(images) { + var imageIndex = 0; + + if (images) { + // this is NOT the first time this method is ran on this instance of jsPDF object. + imageIndex = Object.keys ? Object.keys(images).length : function (o) { + var i = 0; + + for (var e in o) { + if (o.hasOwnProperty(e)) { + i++; + } + } + + return i; + }(images); + } + + return imageIndex; + }, + notDefined = function notDefined(value) { + return typeof value === "undefined" || value === null || value.length === 0; + }, + generateAliasFromData = function generateAliasFromData(data) { + return typeof data === "string" && jsPDFAPI.sHashCode(data); + }, + isImageTypeSupported = function isImageTypeSupported(type) { + return typeof jsPDFAPI["process" + type.toUpperCase()] === "function"; + }, + isDOMElement = function isDOMElement(object) { + return _typeof(object) === "object" && object.nodeType === 1; + }, + createDataURIFromElement = function createDataURIFromElement(element, format) { + //if element is an image which uses data url definition, just return the dataurl + if (element.nodeName === "IMG" && element.hasAttribute("src")) { + var src = "" + element.getAttribute("src"); + if (src.indexOf("data:image/") === 0) return unescape(src); // only if the user doesn't care about a format + + if (!format && /\.png(?:[?#].*)?$/i.test(src)) format = "png"; + } + + if (element.nodeName === "CANVAS") { + var canvas = element; + } else { + var canvas = document.createElement("canvas"); + canvas.width = element.clientWidth || element.width; + canvas.height = element.clientHeight || element.height; + var ctx = canvas.getContext("2d"); + + if (!ctx) { + throw "addImage requires canvas to be supported by browser."; + } + + ctx.drawImage(element, 0, 0, canvas.width, canvas.height); + } + + return canvas.toDataURL(("" + format).toLowerCase() == "png" ? "image/png" : "image/jpeg"); + }, + checkImagesForAlias = function checkImagesForAlias(alias, images) { + var cached_info; + + if (images) { + for (var e in images) { + if (alias === images[e].alias) { + cached_info = images[e]; + break; + } + } + } + + return cached_info; + }, + determineWidthAndHeight = function determineWidthAndHeight(w, h, info) { + if (!w && !h) { + w = -96; + h = -96; + } + + if (w < 0) { + w = -1 * info["w"] * 72 / w / this.internal.scaleFactor; + } + + if (h < 0) { + h = -1 * info["h"] * 72 / h / this.internal.scaleFactor; + } + + if (w === 0) { + w = h * info["w"] / info["h"]; + } + + if (h === 0) { + h = w * info["h"] / info["w"]; + } + + return [w, h]; + }, + writeImageToPDF = function writeImageToPDF(x, y, w, h, info, index, images, rotation) { + var dims = determineWidthAndHeight.call(this, w, h, info), + coord = this.internal.getCoordinateString, + vcoord = this.internal.getVerticalCoordinateString; + w = dims[0]; + h = dims[1]; + images[index] = info; + + if (rotation) { + rotation *= Math.PI / 180; + var c = Math.cos(rotation); + var s = Math.sin(rotation); //like in pdf Reference do it 4 digits instead of 2 + + var f4 = function f4(number) { + return number.toFixed(4); + }; + + var rotationTransformationMatrix = [f4(c), f4(s), f4(s * -1), f4(c), 0, 0, "cm"]; + } + + this.internal.write("q"); //Save graphics state + + if (rotation) { + this.internal.write([1, "0", "0", 1, coord(x), vcoord(y + h), "cm"].join(" ")); //Translate + + this.internal.write(rotationTransformationMatrix.join(" ")); //Rotate + + this.internal.write([coord(w), "0", "0", coord(h), "0", "0", "cm"].join(" ")); //Scale + } else { + this.internal.write([coord(w), "0", "0", coord(h), coord(x), vcoord(y + h), "cm"].join(" ")); //Translate and Scale + } + + if (this.isAdvancedAPI()) { + // draw image bottom up when in "advanced" API mode + this.internal.write([1, 0, 0, -1, 0, 0, "cm"].join(" ")); + } + + this.internal.write("/I" + info["i"] + " Do"); //Paint Image + + this.internal.write("Q"); //Restore graphics state + }; + /** + * COLOR SPACES + */ + + + jsPDFAPI.color_spaces = { + DEVICE_RGB: "DeviceRGB", + DEVICE_GRAY: "DeviceGray", + DEVICE_CMYK: "DeviceCMYK", + CAL_GREY: "CalGray", + CAL_RGB: "CalRGB", + LAB: "Lab", + ICC_BASED: "ICCBased", + INDEXED: "Indexed", + PATTERN: "Pattern", + SEPARATION: "Separation", + DEVICE_N: "DeviceN" + }; + /** + * DECODE METHODS + */ + + jsPDFAPI.decode = { + DCT_DECODE: "DCTDecode", + FLATE_DECODE: "FlateDecode", + LZW_DECODE: "LZWDecode", + JPX_DECODE: "JPXDecode", + JBIG2_DECODE: "JBIG2Decode", + ASCII85_DECODE: "ASCII85Decode", + ASCII_HEX_DECODE: "ASCIIHexDecode", + RUN_LENGTH_DECODE: "RunLengthDecode", + CCITT_FAX_DECODE: "CCITTFaxDecode" + }; + /** + * IMAGE COMPRESSION TYPES + */ + + jsPDFAPI.image_compression = { + NONE: "NONE", + FAST: "FAST", + MEDIUM: "MEDIUM", + SLOW: "SLOW" + }; + /** + * @name sHashCode + * @function + * @param {string} str + * @returns {string} + */ + + jsPDFAPI.sHashCode = function (str) { + str = str || ""; + return Array.prototype.reduce && str.split("").reduce(function (a, b) { + a = (a << 5) - a + b.charCodeAt(0); + return a & a; + }, 0); + }; + /** + * @name isString + * @function + * @param {any} object + * @returns {boolean} + */ + + + jsPDFAPI.isString = function (object) { + return typeof object === "string"; + }; + /** + * Validates if given String is a valid Base64-String + * + * @name validateStringAsBase64 + * @public + * @function + * @param {String} possible Base64-String + * + * @returns {boolean} + */ + + + jsPDFAPI.validateStringAsBase64 = function (possibleBase64String) { + possibleBase64String = possibleBase64String || ""; + var result = true; + + if (possibleBase64String.length % 4 !== 0) { + result = false; + } + + if (/[A-Za-z0-9\/]+/.test(possibleBase64String.substr(0, possibleBase64String.length - 2)) === false) { + result = false; + } + + if (/[A-Za-z0-9\/][A-Za-z0-9+\/]|[A-Za-z0-9+\/]=|==/.test(possibleBase64String.substr(-2)) === false) { + result = false; + } + + return result; + }; + /** + * Strips out and returns info from a valid base64 data URI + * + * @name extractInfoFromBase64DataURI + * @function + * @param {string} dataUrl a valid data URI of format 'data:[][;base64],' + * @returns {Array}an Array containing the following + * [0] the complete data URI + * [1] + * [2] format - the second part of the mime-type i.e 'png' in 'image/png' + * [4] + */ + + + jsPDFAPI.extractInfoFromBase64DataURI = function (dataURI) { + return /^data:([\w]+?\/([\w]+?));\S*;*base64,(.+)$/g.exec(dataURI); + }; + /** + * Check to see if ArrayBuffer is supported + * + * @name supportsArrayBuffer + * @function + * @returns {boolean} + */ + + + jsPDFAPI.supportsArrayBuffer = function () { + return typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined"; + }; + /** + * Tests supplied object to determine if ArrayBuffer + * + * @name isArrayBuffer + * @function + * @param {Object} object an Object + * + * @returns {boolean} + */ + + + jsPDFAPI.isArrayBuffer = function (object) { + if (!this.supportsArrayBuffer()) return false; + return object instanceof ArrayBuffer; + }; + /** + * Tests supplied object to determine if it implements the ArrayBufferView (TypedArray) interface + * + * @name isArrayBufferView + * @function + * @param {Object} object an Object + * @returns {boolean} + */ + + + jsPDFAPI.isArrayBufferView = function (object) { + if (!this.supportsArrayBuffer()) return false; + if (typeof Uint32Array === "undefined") return false; + return object instanceof Int8Array || object instanceof Uint8Array || typeof Uint8ClampedArray !== "undefined" && object instanceof Uint8ClampedArray || object instanceof Int16Array || object instanceof Uint16Array || object instanceof Int32Array || object instanceof Uint32Array || object instanceof Float32Array || object instanceof Float64Array; + }; + /** + * Convert the Buffer to a Binary String + * + * @name binaryStringToUint8Array + * @public + * @function + * @param {ArrayBuffer} BinaryString with ImageData + * + * @returns {Uint8Array} + */ + + + jsPDFAPI.binaryStringToUint8Array = function (binary_string) { + /* + * not sure how efficient this will be will bigger files. Is there a native method? + */ + var len = binary_string.length; + var bytes = new Uint8Array(len); + + for (var i = 0; i < len; i++) { + bytes[i] = binary_string.charCodeAt(i); + } + + return bytes; + }; + /** + * Convert the Buffer to a Binary String + * + * @name arrayBufferToBinaryString + * @public + * @function + * @param {ArrayBuffer} ArrayBuffer with ImageData + * + * @returns {String} + */ + + + jsPDFAPI.arrayBufferToBinaryString = function (buffer) { + if (typeof atob === "function") { + return atob(this.arrayBufferToBase64(buffer)); + } + + if (typeof TextDecoder === "function") { + var decoder = new TextDecoder("ascii"); // test if the encoding is supported + + if (decoder.encoding === "ascii") { + return decoder.decode(buffer); + } + } //Fallback-solution + + + var data = this.isArrayBuffer(buffer) ? buffer : new Uint8Array(buffer); + var chunkSizeForSlice = 0x5000; + var binary_string = ""; + var slicesCount = Math.ceil(data.byteLength / chunkSizeForSlice); + + for (var i = 0; i < slicesCount; i++) { + binary_string += String.fromCharCode.apply(null, data.slice(i * chunkSizeForSlice, i * chunkSizeForSlice + chunkSizeForSlice)); + } + + return binary_string; + }; + /** + * Converts an ArrayBuffer directly to base64 + * + * Taken from http://jsperf.com/encoding-xhr-image-data/31 + * + * Need to test if this is a better solution for larger files + * + * @name arrayBufferToBase64 + * @param {arraybuffer} arrayBuffer + * @public + * @function + * + * @returns {string} + */ + + + jsPDFAPI.arrayBufferToBase64 = function (arrayBuffer) { + var base64 = ""; + var encodings = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var bytes = new Uint8Array(arrayBuffer); + var byteLength = bytes.byteLength; + var byteRemainder = byteLength % 3; + var mainLength = byteLength - byteRemainder; + var a, b, c, d; + var chunk; // Main loop deals with bytes in chunks of 3 + + for (var i = 0; i < mainLength; i = i + 3) { + // Combine the three bytes into a single integer + chunk = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2]; // Use bitmasks to extract 6-bit segments from the triplet + + a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18 + + b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12 + + c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6 + + d = chunk & 63; // 63 = 2^6 - 1 + // Convert the raw binary segments to the appropriate ASCII encoding + + base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]; + } // Deal with the remaining bytes and padding + + + if (byteRemainder == 1) { + chunk = bytes[mainLength]; + a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2 + // Set the 4 least significant bits to zero + + b = (chunk & 3) << 4; // 3 = 2^2 - 1 + + base64 += encodings[a] + encodings[b] + "=="; + } else if (byteRemainder == 2) { + chunk = bytes[mainLength] << 8 | bytes[mainLength + 1]; + a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10 + + b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4 + // Set the 2 least significant bits to zero + + c = (chunk & 15) << 2; // 15 = 2^4 - 1 + + base64 += encodings[a] + encodings[b] + encodings[c] + "="; + } + + return base64; + }; + /** + * + * @name createImageInfo + * @param {Object} data + * @param {number} wd width + * @param {number} ht height + * @param {Object} cs colorSpace + * @param {number} bpc bits per channel + * @param {any} f + * @param {number} imageIndex + * @param {string} alias + * @param {any} dp + * @param {any} trns + * @param {any} pal + * @param {any} smask + * @param {any} p + * @public + * @function + * + * @returns {Object} + */ + + + jsPDFAPI.createImageInfo = function (data, wd, ht, cs, bpc, f, imageIndex, alias, dp, trns, pal, smask, p) { + var info = { + alias: alias, + w: wd, + h: ht, + cs: cs, + bpc: bpc, + i: imageIndex, + data: data // n: objectNumber will be added by putImage code + + }; + if (f) info.f = f; + if (dp) info.dp = dp; + if (trns) info.trns = trns; + if (pal) info.pal = pal; + if (smask) info.smask = smask; + if (p) info.p = p; // predictor parameter for PNG compression + + return info; + }; + /** + * Adds an Image to the PDF. + * + * @name addImage + * @public + * @function + * @param {string/Image-Element/Canvas-Element/Uint8Array} imageData imageData as base64 encoded DataUrl or Image-HTMLElement or Canvas-HTMLElement + * @param {string} format format of file if filetype-recognition fails, e.g. 'JPEG' + * @param {number} x x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {number} y y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {number} width width of the image (in units declared at inception of PDF document) + * @param {number} height height of the Image (in units declared at inception of PDF document) + * @param {string} alias alias of the image (if used multiple times) + * @param {string} compression compression of the generated JPEG, can have the values 'NONE', 'FAST', 'MEDIUM' and 'SLOW' + * @param {number} rotation rotation of the image in degrees (0-359) + * + * @returns jsPDF + */ + + + jsPDFAPI.addImage = function (imageData, format, x, y, w, h, alias, compression, rotation) { + + var tmpImageData = ""; + + if (typeof format !== "string") { + var tmp = h; + h = w; + w = y; + y = x; + x = format; + format = tmp; + } + + if (_typeof(imageData) === "object" && !isDOMElement(imageData) && "imageData" in imageData) { + var options = imageData; + imageData = options.imageData; + format = options.format || format; + x = options.x || x || 0; + y = options.y || y || 0; + w = options.w || w; + h = options.h || h; + alias = options.alias || alias; + compression = options.compression || compression; + rotation = options.rotation || options.angle || rotation; + } + + if (typeof imageData === "string") { + imageData = unescape(imageData); + } + + if (isNaN(x) || isNaN(y)) { + console.error("jsPDF.addImage: Invalid coordinates", arguments); + throw new Error("Invalid coordinates passed to jsPDF.addImage"); + } + + var images = getImages.call(this), + info; + + if (!(info = checkImagesForAlias(imageData, images))) { + var dataAsBinaryString; + if (isDOMElement(imageData)) imageData = createDataURIFromElement(imageData, format); + if (notDefined(alias)) alias = generateAliasFromData(imageData); + + if (!(info = checkImagesForAlias(alias, images))) { + if (this.isString(imageData)) { + tmpImageData = this.convertStringToImageData(imageData); + + if (tmpImageData !== "") { + imageData = tmpImageData; + } else { + tmpImageData = this.loadImageFile(imageData); + + if (tmpImageData !== undefined) { + imageData = tmpImageData; + } + } + } + + format = this.getImageFileTypeByImageData(imageData, format); + if (!isImageTypeSupported(format)) throw new Error("addImage does not support files of type '" + format + "', please ensure that a plugin for '" + format + "' support is added."); + /** + * need to test if it's more efficient to convert all binary strings + * to TypedArray - or should we just leave and process as string? + */ + + if (this.supportsArrayBuffer()) { + // no need to convert if imageData is already uint8array + if (!(imageData instanceof Uint8Array)) { + dataAsBinaryString = imageData; + imageData = this.binaryStringToUint8Array(imageData); + } + } + + info = this["process" + format.toUpperCase()](imageData, getImageIndex(images), alias, checkCompressValue(compression), dataAsBinaryString); + if (!info) throw new Error("An unkwown error occurred whilst processing the image"); + } + } + + writeImageToPDF.call(this, x, y, w, h, info, info.i, images, rotation); + return this; + }; + /** + * @name convertStringToImageData + * @function + * @param {string} stringData + * @returns {string} binary data + */ + + + jsPDFAPI.convertStringToImageData = function (stringData) { + var base64Info; + var imageData = ""; + + if (this.isString(stringData)) { + var base64Info = this.extractInfoFromBase64DataURI(stringData); + + if (base64Info !== null) { + if (jsPDFAPI.validateStringAsBase64(base64Info[3])) { + imageData = atob(base64Info[3]); //convert to binary string + } + } else if (jsPDFAPI.validateStringAsBase64(stringData)) { + imageData = atob(stringData); + } + } + + return imageData; + }; + /** + * JPEG SUPPORT + **/ + //takes a string imgData containing the raw bytes of + //a jpeg image and returns [width, height] + //Algorithm from: http://www.64lines.com/jpeg-width-height + + + var getJpegSize = function getJpegSize(imgData) { + + var width, height, numcomponents; // Verify we have a valid jpeg header 0xff,0xd8,0xff,0xe0,?,?,'J','F','I','F',0x00 + + if (!imgData.charCodeAt(0) === 0xff || !imgData.charCodeAt(1) === 0xd8 || !imgData.charCodeAt(2) === 0xff || !imgData.charCodeAt(3) === 0xe0 || !imgData.charCodeAt(6) === "J".charCodeAt(0) || !imgData.charCodeAt(7) === "F".charCodeAt(0) || !imgData.charCodeAt(8) === "I".charCodeAt(0) || !imgData.charCodeAt(9) === "F".charCodeAt(0) || !imgData.charCodeAt(10) === 0x00) { + throw new Error("getJpegSize requires a binary string jpeg file"); + } + + var blockLength = imgData.charCodeAt(4) * 256 + imgData.charCodeAt(5); + var i = 4, + len = imgData.length; + + while (i < len) { + i += blockLength; + + if (imgData.charCodeAt(i) !== 0xff) { + throw new Error("getJpegSize could not find the size of the image"); + } + + if (imgData.charCodeAt(i + 1) === 0xc0 || //(SOF) Huffman - Baseline DCT + imgData.charCodeAt(i + 1) === 0xc1 || //(SOF) Huffman - Extended sequential DCT + imgData.charCodeAt(i + 1) === 0xc2 || // Progressive DCT (SOF2) + imgData.charCodeAt(i + 1) === 0xc3 || // Spatial (sequential) lossless (SOF3) + imgData.charCodeAt(i + 1) === 0xc4 || // Differential sequential DCT (SOF5) + imgData.charCodeAt(i + 1) === 0xc5 || // Differential progressive DCT (SOF6) + imgData.charCodeAt(i + 1) === 0xc6 || // Differential spatial (SOF7) + imgData.charCodeAt(i + 1) === 0xc7) { + height = imgData.charCodeAt(i + 5) * 256 + imgData.charCodeAt(i + 6); + width = imgData.charCodeAt(i + 7) * 256 + imgData.charCodeAt(i + 8); + numcomponents = imgData.charCodeAt(i + 9); + return [width, height, numcomponents]; + } else { + i += 2; + blockLength = imgData.charCodeAt(i) * 256 + imgData.charCodeAt(i + 1); + } + } + }, + getJpegSizeFromBytes = function getJpegSizeFromBytes(data) { + var hdr = data[0] << 8 | data[1]; + if (hdr !== 0xffd8) throw new Error("Supplied data is not a JPEG"); + var len = data.length, + block = (data[4] << 8) + data[5], + pos = 4, + bytes, + width, + height, + numcomponents; + + while (pos < len) { + pos += block; + bytes = readBytes(data, pos); + block = (bytes[2] << 8) + bytes[3]; + + if ((bytes[1] === 0xc0 || bytes[1] === 0xc2) && bytes[0] === 0xff && block > 7) { + bytes = readBytes(data, pos + 5); + width = (bytes[2] << 8) + bytes[3]; + height = (bytes[0] << 8) + bytes[1]; + numcomponents = bytes[4]; + return { + width: width, + height: height, + numcomponents: numcomponents + }; + } + + pos += 2; + } + + throw new Error("getJpegSizeFromBytes could not find the size of the image"); + }, + readBytes = function readBytes(data, offset) { + return data.subarray(offset, offset + 5); + }; + /** + * @ignore + */ + + + jsPDFAPI.processJPEG = function (data, index, alias, compression, dataAsBinaryString, colorSpace) { + + var filter = this.decode.DCT_DECODE, + bpc = 8, + dims; + + if (!this.isString(data) && !this.isArrayBuffer(data) && !this.isArrayBufferView(data)) { + return null; + } + + if (this.isString(data)) { + dims = getJpegSize(data); + } + + if (this.isArrayBuffer(data)) { + data = new Uint8Array(data); + } + + if (this.isArrayBufferView(data)) { + dims = getJpegSizeFromBytes(data); // if we already have a stored binary string rep use that + + data = dataAsBinaryString || this.arrayBufferToBinaryString(data); + } + + if (colorSpace === undefined) { + switch (dims.numcomponents) { + case 1: + colorSpace = this.color_spaces.DEVICE_GRAY; + break; + + case 4: + colorSpace = this.color_spaces.DEVICE_CMYK; + break; + + default: + case 3: + colorSpace = this.color_spaces.DEVICE_RGB; + break; + } + } + + return this.createImageInfo(data, dims.width, dims.height, colorSpace, bpc, filter, index, alias); + }; + /** + * @ignore + */ + + + jsPDFAPI.processJPG = function () + /*data, index, alias, compression, dataAsBinaryString*/ + { + return this.processJPEG.apply(this, arguments); + }; + /** + * @name loadImageFile + * @function + * @param {string} path + * @param {boolean} sync + * @param {function} callback + */ + + + jsPDFAPI.loadImageFile = function (path, sync, callback) { + sync = sync || true; + + callback = callback || function () {}; + + var isNode = Object.prototype.toString.call(typeof process !== "undefined" ? process : 0) === "[object process]"; + + var xhrMethod = function xhrMethod(url, sync, callback) { + var req = new XMLHttpRequest(); + var byteArray = []; + var i = 0; + + var sanitizeUnicode = function sanitizeUnicode(data) { + var dataLength = data.length; + var StringFromCharCode = String.fromCharCode; //Transform Unicode to ASCII + + for (i = 0; i < dataLength; i += 1) { + byteArray.push(StringFromCharCode(data.charCodeAt(i) & 0xff)); + } + + return byteArray.join(""); + }; + + req.open("GET", url, !sync); // XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com] + + req.overrideMimeType("text/plain; charset=x-user-defined"); + + if (sync === false) { + req.onload = function () { + return sanitizeUnicode(this.responseText); + }; + } + + req.send(null); + + if (req.status !== 200) { + console.warn('Unable to load file "' + url + '"'); + return; + } + + if (sync) { + return sanitizeUnicode(req.responseText); + } + }; //we have a browser and probably no CORS-Problem + + + if ((typeof window === "undefined" ? "undefined" : _typeof(window)) !== undefined && (typeof location === "undefined" ? "undefined" : _typeof(location)) === "object" && location.protocol.substr(0, 4) === "http") { + return xhrMethod(path, sync, callback); + } + }; + /** + * @name getImageProperties + * @function + * @param {Object} imageData + * @returns {Object} + */ + + + jsPDFAPI.getImageProperties = function (imageData) { + var info; + var tmpImageData = ""; + var format; + + if (isDOMElement(imageData)) { + imageData = createDataURIFromElement(imageData); + } + + if (this.isString(imageData)) { + tmpImageData = this.convertStringToImageData(imageData); + + if (tmpImageData !== "") { + imageData = tmpImageData; + } else { + tmpImageData = this.loadImageFile(imageData); + + if (tmpImageData !== undefined) { + imageData = tmpImageData; + } + } + } + + format = this.getImageFileTypeByImageData(imageData); + if (!isImageTypeSupported(format)) throw new Error("addImage does not support files of type '" + format + "', please ensure that a plugin for '" + format + "' support is added."); + /** + * need to test if it's more efficient to convert all binary strings + * to TypedArray - or should we just leave and process as string? + */ + + if (this.supportsArrayBuffer()) { + // no need to convert if imageData is already uint8array + if (!(imageData instanceof Uint8Array)) { + imageData = this.binaryStringToUint8Array(imageData); + } + } + + info = this["process" + format.toUpperCase()](imageData); + + if (!info) { + throw new Error("An unkwown error occurred whilst processing the image"); + } + + return { + fileType: format, + width: info.w, + height: info.h, + colorSpace: info.cs, + compressionMode: info.f, + bitsPerComponent: info.bpc + }; + }; + })(jsPDF.API); + + /** + * @license + * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF Annotations PlugIn + * + * There are many types of annotations in a PDF document. Annotations are placed + * on a page at a particular location. They are not 'attached' to an object. + *
+ * This plugin current supports
+ *
  • Goto Page (set pageNumber and top in options) + *
  • Goto Name (set name and top in options) + *
  • Goto URL (set url in options) + *

    + * The destination magnification factor can also be specified when goto is a page number or a named destination. (see documentation below) + * (set magFactor in options). XYZ is the default. + *

    + *

    + * Links, Text, Popup, and FreeText are supported. + *

    + *

    + * Options In PDF spec Not Implemented Yet + *

  • link border + *
  • named target + *
  • page coordinates + *
  • destination page scaling and layout + *
  • actions other than URL and GotoPage + *
  • background / hover actions + *

    + * @name annotations + * @module + */ + + /* + Destination Magnification Factors + See PDF 1.3 Page 386 for meanings and options + + [supported] + XYZ (options; left top zoom) + Fit (no options) + FitH (options: top) + FitV (options: left) + + [not supported] + FitR + FitB + FitBH + FitBV + */ + (function (jsPDFAPI) { + + var annotationPlugin = { + /** + * An array of arrays, indexed by pageNumber. + */ + annotations: [], + f2: function f2(number) { + return number.toFixed(2); + }, + notEmpty: function notEmpty(obj) { + if (typeof obj != "undefined") { + if (obj != "") { + return true; + } + } + } + }; + jsPDF.API.annotationPlugin = annotationPlugin; + jsPDF.API.events.push(["addPage", function (info) { + this.annotationPlugin.annotations[info.pageNumber] = []; + }]); + jsPDFAPI.events.push(["putPage", function (info) { + //TODO store annotations in pageContext so reorder/remove will not affect them. + var pageAnnos = this.annotationPlugin.annotations[info.pageNumber]; + var found = false; + + for (var a = 0; a < pageAnnos.length && !found; a++) { + var anno = pageAnnos[a]; + + switch (anno.type) { + case "link": + if (annotationPlugin.notEmpty(anno.options.url) || annotationPlugin.notEmpty(anno.options.pageNumber)) { + found = true; + break; + } + + case "reference": + case "text": + case "freetext": + found = true; + break; + } + } + + if (found == false) { + return; + } + + this.internal.write("/Annots ["); + var f2 = this.annotationPlugin.f2; + var k = this.internal.scaleFactor; + var pageHeight = this.internal.pageSize.getHeight(); + var pageInfo = this.internal.getPageInfo(info.pageNumber); + + for (var a = 0; a < pageAnnos.length; a++) { + var anno = pageAnnos[a]; + + switch (anno.type) { + case "reference": + // References to Widget Anotations (for AcroForm Fields) + this.internal.write(" " + anno.object.objId + " 0 R "); + break; + + case "text": + // Create a an object for both the text and the popup + var objText = this.internal.newAdditionalObject(); + var objPopup = this.internal.newAdditionalObject(); + var title = anno.title || "Note"; + var rect = "/Rect [" + f2(anno.bounds.x * k) + " " + f2(pageHeight - (anno.bounds.y + anno.bounds.h) * k) + " " + f2((anno.bounds.x + anno.bounds.w) * k) + " " + f2((pageHeight - anno.bounds.y) * k) + "] "; + line = "<>"; + objText.content = line; + var parent = objText.objId + " 0 R"; + var popoff = 30; + var rect = "/Rect [" + f2((anno.bounds.x + popoff) * k) + " " + f2(pageHeight - (anno.bounds.y + anno.bounds.h) * k) + " " + f2((anno.bounds.x + anno.bounds.w + popoff) * k) + " " + f2((pageHeight - anno.bounds.y) * k) + "] "; //var rect2 = "/Rect [" + f2(anno.bounds.x * k) + " " + f2((pageHeight - anno.bounds.y) * k) + " " + f2(anno.bounds.x + anno.bounds.w * k) + " " + f2(pageHeight - (anno.bounds.y + anno.bounds.h) * k) + "] "; + + line = "<>"; + } else if (anno.options.pageNumber) { + // first page is 0 + var info = this.internal.getPageInfo(anno.options.pageNumber); + line = "< pageNumber or url [required] + *

    If pageNumber is specified, top and zoom may also be specified

    + * @name link + * @function + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @param {Object} options + */ + + + jsPDFAPI.link = function (x, y, w, h, options) { + + this.annotationPlugin.annotations[this.internal.getCurrentPageInfo().pageNumber].push({ + x: x, + y: y, + w: w, + h: h, + options: options, + type: "link" + }); + }; + /** + * Currently only supports single line text. + * Returns the width of the text/link + * + * @name textWithLink + * @function + * @param {string} text + * @param {number} x + * @param {number} y + * @param {Object} options + * @returns {number} width the width of the text/link + */ + + + jsPDFAPI.textWithLink = function (text, x, y, options) { + + var width = this.getTextWidth(text); + var height = this.internal.getLineHeight() / this.internal.scaleFactor; + this.text(text, x, y); //TODO We really need the text baseline height to do this correctly. + // Or ability to draw text on top, bottom, center, or baseline. + + y += height * 0.2; + this.link(x, y - height, width, height, options); + return width; + }; //TODO move into external library + + /** + * @name getTextWidth + * @function + * @param {string} text + * @returns {number} txtWidth + */ + + + jsPDFAPI.getTextWidth = function (text) { + + var fontSize = this.internal.getFontSize(); + var txtWidth = this.getStringUnitWidth(text) * fontSize / this.internal.scaleFactor; + return txtWidth; + }; //TODO move into external library + + /** + * @name getLineHeight + * @function + * @returns {number} lineHeight + */ + + + jsPDFAPI.getLineHeight = function () { + return this.internal.getLineHeight(); + }; + + return this; + })(jsPDF.API); + + /** + * @license + * Copyright (c) 2017 Aras Abbasi + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF arabic parser PlugIn + * + * @name arabic + * @module + */ + (function (jsPDFAPI) { + + var arLangCodes = { + ar: "Arabic (Standard)", + "ar-DZ": "Arabic (Algeria)", + "ar-BH": "Arabic (Bahrain)", + "ar-EG": "Arabic (Egypt)", + "ar-IQ": "Arabic (Iraq)", + "ar-JO": "Arabic (Jordan)", + "ar-KW": "Arabic (Kuwait)", + "ar-LB": "Arabic (Lebanon)", + "ar-LY": "Arabic (Libya)", + "ar-MA": "Arabic (Morocco)", + "ar-OM": "Arabic (Oman)", + "ar-QA": "Arabic (Qatar)", + "ar-SA": "Arabic (Saudi Arabia)", + "ar-SY": "Arabic (Syria)", + "ar-TN": "Arabic (Tunisia)", + "ar-AE": "Arabic (U.A.E.)", + "ar-YE": "Arabic (Yemen)", + fa: "Persian", + "fa-IR": "Persian/Iran", + ur: "Urdu" + }; + var arLangCodesKeys = Object.keys(arLangCodes); + /** + * Arabic shape substitutions: char code => (isolated, final, initial, medial). + */ + + var arabicSubst = { + 1569: [65152], + 1570: [65153, 65154, 65153, 65154], + 1571: [65155, 65156, 65155, 65156], + 1572: [65157, 65158], + 1573: [65159, 65160, 65159, 65160], + 1574: [65161, 65162, 65163, 65164], + 1575: [65165, 65166, 65165, 65166], + 1576: [65167, 65168, 65169, 65170], + 1577: [65171, 65172], + 1578: [65173, 65174, 65175, 65176], + 1579: [65177, 65178, 65179, 65180], + 1580: [65181, 65182, 65183, 65184], + 1581: [65185, 65186, 65187, 65188], + 1582: [65189, 65190, 65191, 65192], + 1583: [65193, 65194, 65193], + 1584: [65195, 65196, 65195], + 1585: [65197, 65198, 65197], + 1586: [65199, 65200, 65199], + 1587: [65201, 65202, 65203, 65204], + 1588: [65205, 65206, 65207, 65208], + 1589: [65209, 65210, 65211, 65212], + 1590: [65213, 65214, 65215, 65216], + 1591: [65217, 65218, 65219, 65220], + 1592: [65221, 65222, 65223, 65224], + 1593: [65225, 65226, 65227, 65228], + 1594: [65229, 65230, 65231, 65232], + 1601: [65233, 65234, 65235, 65236], + 1602: [65237, 65238, 65239, 65240], + 1603: [65241, 65242, 65243, 65244], + 1604: [65245, 65246, 65247, 65248], + 1605: [65249, 65250, 65251, 65252], + 1606: [65253, 65254, 65255, 65256], + 1607: [65257, 65258, 65259, 65260], + 1608: [65261, 65262, 65261], + 1609: [65263, 65264, 64488, 64489], + 1610: [65265, 65266, 65267, 65268], + 1649: [64336, 64337], + 1655: [64477], + 1657: [64358, 64359, 64360, 64361], + 1658: [64350, 64351, 64352, 64353], + 1659: [64338, 64339, 64340, 64341], + 1662: [64342, 64343, 64344, 64345], + 1663: [64354, 64355, 64356, 64357], + 1664: [64346, 64347, 64348, 64349], + 1667: [64374, 64375, 64376, 64377], + 1668: [64370, 64371, 64372, 64373], + 1670: [64378, 64379, 64380, 64381], + 1671: [64382, 64383, 64384, 64385], + 1672: [64392, 64393], + 1676: [64388, 64389], + 1677: [64386, 64387], + 1678: [64390, 64391], + 1681: [64396, 64397], + 1688: [64394, 64395, 64394], + 1700: [64362, 64363, 64364, 64365], + 1702: [64366, 64367, 64368, 64369], + 1705: [64398, 64399, 64400, 64401], + 1709: [64467, 64468, 64469, 64470], + 1711: [64402, 64403, 64404, 64405], + 1713: [64410, 64411, 64412, 64413], + 1715: [64406, 64407, 64408, 64409], + 1722: [64414, 64415], + 1723: [64416, 64417, 64418, 64419], + 1726: [64426, 64427, 64428, 64429], + 1728: [64420, 64421], + 1729: [64422, 64423, 64424, 64425], + 1733: [64480, 64481], + 1734: [64473, 64474], + 1735: [64471, 64472], + 1736: [64475, 64476], + 1737: [64482, 64483], + 1739: [64478, 64479], + 1740: [64508, 64509, 64510, 64511], + 1744: [64484, 64485, 64486, 64487], + 1746: [64430, 64431], + 1747: [64432, 64433] + }; + var arabiclaasubst = { + 1570: [65269, 65270, 65269, 65270], + 1571: [65271, 65272, 65271, 65272], + 1573: [65273, 65274, 65273, 65274], + 1575: [65275, 65276, 65275, 65276] + }; + var arabicorigsubst = { + 1570: [65153, 65154, 65153, 65154], + 1571: [65155, 65156, 65155, 65156], + 1573: [65159, 65160, 65159, 65160], + 1575: [65165, 65166, 65165, 65166] + }; + var arabic_diacritics = { + 1612: 64606, + // Shadda + Dammatan + 1613: 64607, + // Shadda + Kasratan + 1614: 64608, + // Shadda + Fatha + 1615: 64609, + // Shadda + Damma + 1616: 64610 // Shadda + Kasra + + }; + var alfletter = [1570, 1571, 1573, 1575]; + var endedletter = [1569, 1570, 1571, 1572, 1573, 1575, 1577, 1583, 1584, 1585, 1586, 1608, 1688]; + var isolatedForm = 0; + var finalForm = 1; + var initialForm = 2; + var medialForm = 3; //private + + function isArabicLetter(letter) { + return letter !== undefined && arabicSubst[letter.charCodeAt(0)] !== undefined; + } + + function isArabicEndLetter(letter) { + return letter !== undefined && endedletter.indexOf(letter.charCodeAt(0)) >= 0; + } + + function isArabicAlfLetter(letter) { + return letter !== undefined && alfletter.indexOf(letter.charCodeAt(0)) >= 0; + } + + function arabicLetterHasFinalForm(letter) { + return isArabicLetter(letter) && arabicSubst[letter.charCodeAt(0)].length >= 2; + } + + function arabicLetterHasMedialForm(letter) { + return isArabicLetter(letter) && arabicSubst[letter.charCodeAt(0)].length == 4; + } + + function isArabicDiacritic(letter) { + return letter !== undefined && arabic_diacritics[letter.charCodeAt(0)] !== undefined; + } + + function getCorrectForm(currentChar, beforeChar, nextChar, arabicSubstition) { + + if (!isArabicLetter(currentChar)) { + return -1; + } + + arabicSubstition = arabicSubstition || {}; + arabicSubst = Object.assign(arabicSubst, arabicSubstition); + + if (!arabicLetterHasFinalForm(currentChar) || !isArabicLetter(beforeChar) && !isArabicLetter(nextChar) || !isArabicLetter(nextChar) && isArabicEndLetter(beforeChar) || isArabicEndLetter(currentChar) && !isArabicLetter(beforeChar) || isArabicEndLetter(currentChar) && isArabicAlfLetter(beforeChar) || isArabicEndLetter(currentChar) && isArabicEndLetter(beforeChar)) { + arabicSubst = Object.assign(arabicSubst, arabicorigsubst); + return isolatedForm; + } + + if (arabicLetterHasMedialForm(currentChar) && isArabicLetter(beforeChar) && !isArabicEndLetter(beforeChar) && isArabicLetter(nextChar) && arabicLetterHasFinalForm(nextChar)) { + arabicSubst = Object.assign(arabicSubst, arabicorigsubst); + return medialForm; + } + + if (isArabicEndLetter(currentChar) || !isArabicLetter(nextChar)) { + arabicSubst = Object.assign(arabicSubst, arabicorigsubst); + return finalForm; + } + + arabicSubst = Object.assign(arabicSubst, arabicorigsubst); + return initialForm; + } + + var commonSubstition = function commonSubstition(character) { + var replacementTable = { + "(": ")", + ")": "(" + }; + return replacementTable[character] || character; + }; + /** + * @name processArabic + * @function + * @param {string} text + * @param {boolean} reverse + * @returns {string} + */ + + + var processArabic = jsPDFAPI.processArabic = function (text, reverse) { + text = text || ""; + reverse = reverse || false; + var result = ""; + var i = 0; + var position = 0; + var currentLetter = ""; + var prevLetter = ""; + var nextLetter = ""; + var resultingLetter; + var localPrevLetter; + var localCurrentLetter; + var localNextLetter; + + for (i = 0; i < text.length; i += 1) { + currentLetter = text[i]; + prevLetter = text[i - 1]; + nextLetter = text[i + 1]; + + if (!isArabicLetter(currentLetter)) { + result += reverse ? commonSubstition(currentLetter) : currentLetter; + } else { + if (prevLetter !== undefined && prevLetter.charCodeAt(0) === 1604 && isArabicAlfLetter(currentLetter)) { + localPrevLetter = text[i - 2]; + localCurrentLetter = currentLetter; + localNextLetter = text[i + 1]; + position = getCorrectForm(localCurrentLetter, localPrevLetter, localNextLetter, arabiclaasubst); + resultingLetter = String.fromCharCode(arabiclaasubst[currentLetter.charCodeAt(0)][position]); + result = result.substr(0, result.length - 1) + resultingLetter; + } else if (prevLetter !== undefined && prevLetter.charCodeAt(0) === 1617 && isArabicDiacritic(currentLetter)) { + localPrevLetter = text[i - 2]; + localCurrentLetter = currentLetter; + localNextLetter = text[i + 1]; + position = getCorrectForm(localCurrentLetter, localPrevLetter, localNextLetter, arabicorigsubst); + resultingLetter = String.fromCharCode(arabic_diacritics[currentLetter.charCodeAt(0)][position]); + result = result.substr(0, result.length - 1) + resultingLetter; + } else { + position = getCorrectForm(currentLetter, prevLetter, nextLetter, arabicorigsubst); + result += String.fromCharCode(arabicSubst[currentLetter.charCodeAt(0)][position]); + } + } + } + + return reverse ? result.split("").reverse().join("") : result; + }; + + var arabicParserFunction = function arabicParserFunction(args) { + var text = args.text; + var x = args.x; + var y = args.y; + var options = args.options || {}; + var mutex = args.mutex || {}; + var lang = options.lang; + var tmpText = []; + + if (arLangCodesKeys.indexOf(lang) >= 0) { + if (Object.prototype.toString.call(text) === "[object Array]") { + var i = 0; + tmpText = []; + + for (i = 0; i < text.length; i += 1) { + if (Object.prototype.toString.call(text[i]) === "[object Array]") { + tmpText.push([processArabic(text[i][0], true), text[i][1], text[i][2]]); + } else { + tmpText.push([processArabic(text[i], true)]); + } + } + + args.text = tmpText; + } else { + args.text = processArabic(text, true); + } //force charSpace if not given. + + + if (options.charSpace === undefined) { + args.options.charSpace = 0; + } //if R2L is true, set it false. + + + if (options.R2L === true) { + args.options.R2L = false; + } + } + }; + + jsPDFAPI.events.push(["preProcessText", arabicParserFunction]); + })(jsPDF.API); + + /** @license + * jsPDF Autoprint Plugin + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * @name autoprint + * @module + */ + (function (jsPDFAPI) { + /** + * Makes the PDF automatically print. This works in Chrome, Firefox, Acrobat + * Reader. + * + * @name autoPrint + * @function + * @param {Object} options (optional) Set the attribute variant to 'non-conform' (default) or 'javascript' to activate different methods of automatic printing when opening in a PDF-viewer . + * @returns {jsPDF} + * @example + * var doc = new jsPDF(); + * doc.text(10, 10, 'This is a test'); + * doc.autoPrint({variant: 'non-conform'}); + * doc.save('autoprint.pdf'); + */ + + jsPDFAPI.autoPrint = function (options) { + + var refAutoPrintTag; + options = options || {}; + options.variant = options.variant || "non-conform"; + + switch (options.variant) { + case "javascript": + //https://github.com/Rob--W/pdf.js/commit/c676ecb5a0f54677b9f3340c3ef2cf42225453bb + this.addJS("print({});"); + break; + + case "non-conform": + default: + this.internal.events.subscribe("postPutResources", function () { + refAutoPrintTag = this.internal.newObject(); + this.internal.out("<<"); + this.internal.out("/S /Named"); + this.internal.out("/Type /Action"); + this.internal.out("/N /Print"); + this.internal.out(">>"); + this.internal.out("endobj"); + }); + this.internal.events.subscribe("putCatalog", function () { + this.internal.out("/OpenAction " + refAutoPrintTag + " 0 R"); + }); + break; + } + + return this; + }; + })(jsPDF.API); + + /** + * @license + * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF Canvas PlugIn + * This plugin mimics the HTML5 Canvas + * + * The goal is to provide a way for current canvas users to print directly to a PDF. + * @name canvas + * @module + */ + (function (jsPDFAPI) { + + jsPDFAPI.events.push(["initialized", function () { + this.canvas.pdf = this; + }]); + /** + * @name canvas + * @static + * @type {Object} + */ + + jsPDFAPI.canvas = { + /** + * @name getContext + * @function + * @param {string} the context type + */ + getContext: function getContext(name) { + this.pdf.context2d._canvas = this; + return this.pdf.context2d; + }, + childNodes: [], + style: {}, + autoContext2dResizeX: true, + autoContext2dResizeY: true + }; + /** + * Width of the canvas + * + * @name width + * @property {number} width + */ + + Object.defineProperty(jsPDFAPI.canvas, "width", { + get: function get() { + return this._width; + }, + set: function set(value) { + this._width = value; + + if (this.autoContext2dResizeX) { + this.getContext("2d").pageWrapX = value + 1; + } + } + }); + /** + * Height of the canvas + * + * @name height + * @property {number} height + */ + + Object.defineProperty(jsPDFAPI.canvas, "height", { + get: function get() { + return this._height; + }, + set: function set(value) { + this._height = value; + + if (this.autoContext2dResizeY) { + this.getContext("2d").pageWrapY = value + 1; + } + } + }); + return this; + })(jsPDF.API); + + /** + * @license + * ==================================================================== + * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com + * 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br + * 2013 Lee Driscoll, https://github.com/lsdriscoll + * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria + * 2014 James Hall, james@parall.ax + * 2014 Diego Casorran, https://github.com/diegocr + * + * + * ==================================================================== + */ + + /** + * @name cell + * @module + */ + (function (jsPDFAPI) { + /*jslint browser:true */ + + /*global document: false, jsPDF */ + + var padding = 3, + margin = 13, + headerFunction, + lastCellPos = { + x: undefined, + y: undefined, + w: undefined, + h: undefined, + ln: undefined + }, + pages = 1, + setLastCellPosition = function setLastCellPosition(x, y, w, h, ln) { + lastCellPos = { + x: x, + y: y, + w: w, + h: h, + ln: ln + }; + }, + getLastCellPosition = function getLastCellPosition() { + return lastCellPos; + }, + NO_MARGINS = { + left: 0, + top: 0, + bottom: 0 + }; + /** + * @name setHeaderFunction + * @function + * @param {function} func + */ + + + jsPDFAPI.setHeaderFunction = function (func) { + headerFunction = func; + }; + /** + * @name getTextDimensions + * @function + * @param {string} txt + * @returns {Object} dimensions + */ + + + jsPDFAPI.getTextDimensions = function (text, options) { + var fontSize = this.table_font_size || this.internal.getFontSize(); + var fontStyle = this.internal.getFont().fontStyle; + options = options || {}; + var scaleFactor = options.scaleFactor || this.internal.scaleFactor; + var width = 0; + var amountOfLines = 0; + var height = 0; + var tempWidth = 0; + + if (typeof text === "string") { + width = this.getStringUnitWidth(text) * fontSize; + + if (width !== 0) { + amountOfLines = 1; + } + } else if (Object.prototype.toString.call(text) === "[object Array]") { + for (var i = 0; i < text.length; i++) { + tempWidth = this.getStringUnitWidth(text[i]) * fontSize; + + if (width < tempWidth) { + width = tempWidth; + } + } + + if (width !== 0) { + amountOfLines = text.length; + } + } else { + console.error("getTextDimensions expects text-parameter to be of type String or an Array of Strings."); + } + + width = width / scaleFactor; + height = amountOfLines * fontSize * 1.15 / scaleFactor; + return { + w: width, + h: height + }; + }; + /** + * @name cellAddPage + * @function + */ + + + jsPDFAPI.cellAddPage = function () { + var margins = this.margins || NO_MARGINS; + this.addPage(); + setLastCellPosition(margins.left, margins.top, undefined, undefined); //setLastCellPosition(undefined, undefined, undefined, undefined, undefined); + + pages += 1; + }; + /** + * @name cellInitialize + * @function + */ + + + jsPDFAPI.cellInitialize = function () { + lastCellPos = { + x: undefined, + y: undefined, + w: undefined, + h: undefined, + ln: undefined + }; + pages = 1; + }; + /** + * @name cell + * @function + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @param {string} txt + * @param {number} ln lineNumber + * @param {string} align + * @return {jsPDF} jsPDF-instance + */ + + + jsPDFAPI.cell = function (x, y, w, h, txt, ln, align) { + var curCell = getLastCellPosition(); + var pgAdded = false; // If this is not the first cell, we must change its position + + if (curCell.ln !== undefined) { + if (curCell.ln === ln) { + //Same line + x = curCell.x + curCell.w; + y = curCell.y; + } else { + //New line + var margins = this.margins || NO_MARGINS; + + if (curCell.y + curCell.h + h + margin >= this.internal.pageSize.getHeight() - margins.bottom) { + this.cellAddPage(); + pgAdded = true; + + if (this.printHeaders && this.tableHeaderRow) { + this.printHeaderRow(ln, true); + } + } //We ignore the passed y: the lines may have different heights + + + y = getLastCellPosition().y + getLastCellPosition().h; + if (pgAdded) y = margin + 10; + } + } + + if (txt[0] !== undefined) { + if (this.printingHeaderRow) { + this.rect(x, y, w, h, "FD"); + } else { + this.rect(x, y, w, h); + } + + if (align === "right") { + if (!(txt instanceof Array)) { + txt = [txt]; + } + + for (var i = 0; i < txt.length; i++) { + var currentLine = txt[i]; + var textSize = this.getStringUnitWidth(currentLine) * this.internal.getFontSize(); + this.text(currentLine, x + w - textSize - padding, y + this.internal.getLineHeight() * (i + 1)); + } + } else { + this.text(txt, x + padding, y + this.internal.getLineHeight()); + } + } + + setLastCellPosition(x, y, w, h, ln); + return this; + }; + /** + * Return the maximum value from an array + * + * @name arrayMax + * @function + * @param {Array} array + * @param comparisonFn + * @returns {number} + */ + + + jsPDFAPI.arrayMax = function (array, comparisonFn) { + var max = array[0], + i, + ln, + item; + + for (i = 0, ln = array.length; i < ln; i += 1) { + item = array[i]; + + if (comparisonFn) { + if (comparisonFn(max, item) === -1) { + max = item; + } + } else { + if (item > max) { + max = item; + } + } + } + + return max; + }; + /** + * Create a table from a set of data. + * @name table + * @function + * @param {Integer} [x] : left-position for top-left corner of table + * @param {Integer} [y] top-position for top-left corner of table + * @param {Object[]} [data] As array of objects containing key-value pairs corresponding to a row of data. + * @param {String[]} [headers] Omit or null to auto-generate headers at a performance cost + * @param {Object} [config.printHeaders] True to print column headers at the top of every page + * @param {Object} [config.autoSize] True to dynamically set the column widths to match the widest cell value + * @param {Object} [config.margins] margin values for left, top, bottom, and width + * @param {Object} [config.fontSize] Integer fontSize to use (optional) + * @returns {jsPDF} jsPDF-instance + */ + + + jsPDFAPI.table = function (x, y, data, headers, config) { + if (!data) { + throw "No data for PDF table"; + } + + var headerNames = [], + headerPrompts = [], + header, + i, + ln, + cln, + columnMatrix = {}, + columnWidths = {}, + columnData, + column, + columnMinWidths = [], + j, + tableHeaderConfigs = [], + model, + jln, + func, + //set up defaults. If a value is provided in config, defaults will be overwritten: + autoSize = false, + printHeaders = true, + fontSize = 12, + margins = NO_MARGINS; + margins.width = this.internal.pageSize.getWidth(); + + if (config) { + //override config defaults if the user has specified non-default behavior: + if (config.autoSize === true) { + autoSize = true; + } + + if (config.printHeaders === false) { + printHeaders = false; + } + + if (config.fontSize) { + fontSize = config.fontSize; + } + + if (config.css && typeof config.css["font-size"] !== "undefined") { + fontSize = config.css["font-size"] * 16; + } + + if (config.margins) { + margins = config.margins; + } + } + /** + * @property {Number} lnMod + * Keep track of the current line number modifier used when creating cells + */ + + + this.lnMod = 0; + lastCellPos = { + x: undefined, + y: undefined, + w: undefined, + h: undefined, + ln: undefined + }, pages = 1; + this.printHeaders = printHeaders; + this.margins = margins; + this.setFontSize(fontSize); + this.table_font_size = fontSize; // Set header values + + if (headers === undefined || headers === null) { + // No headers defined so we derive from data + headerNames = Object.keys(data[0]); + } else if (headers[0] && typeof headers[0] !== "string") { + var px2pt = 0.264583 * 72 / 25.4; // Split header configs into names and prompts + + for (i = 0, ln = headers.length; i < ln; i += 1) { + header = headers[i]; + headerNames.push(header.name); + headerPrompts.push(header.prompt); + columnWidths[header.name] = header.width * px2pt; + } + } else { + headerNames = headers; + } + + if (autoSize) { + // Create a matrix of columns e.g., {column_title: [row1_Record, row2_Record]} + func = function func(rec) { + return rec[header]; + }; + + for (i = 0, ln = headerNames.length; i < ln; i += 1) { + header = headerNames[i]; + columnMatrix[header] = data.map(func); // get header width + + columnMinWidths.push(this.getTextDimensions(headerPrompts[i] || header, { + scaleFactor: 1 + }).w); + column = columnMatrix[header]; // get cell widths + + for (j = 0, cln = column.length; j < cln; j += 1) { + columnData = column[j]; + columnMinWidths.push(this.getTextDimensions(columnData, { + scaleFactor: 1 + }).w); + } // get final column width + + + columnWidths[header] = jsPDFAPI.arrayMax(columnMinWidths); //have to reset + + columnMinWidths = []; + } + } // -- Construct the table + + + if (printHeaders) { + var lineHeight = this.calculateLineHeight(headerNames, columnWidths, headerPrompts.length ? headerPrompts : headerNames); // Construct the header row + + for (i = 0, ln = headerNames.length; i < ln; i += 1) { + header = headerNames[i]; + tableHeaderConfigs.push([x, y, columnWidths[header], lineHeight, String(headerPrompts.length ? headerPrompts[i] : header)]); + } // Store the table header config + + + this.setTableHeaderRow(tableHeaderConfigs); // Print the header for the start of the table + + this.printHeaderRow(1, false); + } // Construct the data rows + + + for (i = 0, ln = data.length; i < ln; i += 1) { + var lineHeight; + model = data[i]; + lineHeight = this.calculateLineHeight(headerNames, columnWidths, model); + + for (j = 0, jln = headerNames.length; j < jln; j += 1) { + header = headerNames[j]; + this.cell(x, y, columnWidths[header], lineHeight, model[header], i + 2, header.align); + } + } + + this.lastCellPos = lastCellPos; + this.table_x = x; + this.table_y = y; + return this; + }; + /** + * Calculate the height for containing the highest column + * + * @name calculateLineHeight + * @function + * @param {String[]} headerNames is the header, used as keys to the data + * @param {Integer[]} columnWidths is size of each column + * @param {Object[]} model is the line of data we want to calculate the height of + * @returns {number} lineHeight + */ + + + jsPDFAPI.calculateLineHeight = function (headerNames, columnWidths, model) { + var header, + lineHeight = 0; + + for (var j = 0; j < headerNames.length; j++) { + header = headerNames[j]; + model[header] = this.splitTextToSize(String(model[header]), columnWidths[header] - padding); + var h = this.internal.getLineHeight() * model[header].length + padding; + if (h > lineHeight) lineHeight = h; + } + + return lineHeight; + }; + /** + * Store the config for outputting a table header + * + * @name setTableHeaderRow + * @function + * @param {Object[]} config + * An array of cell configs that would define a header row: Each config matches the config used by jsPDFAPI.cell + * except the ln parameter is excluded + */ + + + jsPDFAPI.setTableHeaderRow = function (config) { + this.tableHeaderRow = config; + }; + /** + * Output the store header row + * + * @name printHeaderRow + * @function + * @param {number} lineNumber The line number to output the header at + * @param {boolean} new_page + */ + + + jsPDFAPI.printHeaderRow = function (lineNumber, new_page) { + if (!this.tableHeaderRow) { + throw "Property tableHeaderRow does not exist."; + } + + var tableHeaderCell, tmpArray, i, ln; + this.printingHeaderRow = true; + + if (headerFunction !== undefined) { + var position = headerFunction(this, pages); + setLastCellPosition(position[0], position[1], position[2], position[3], -1); + } + + this.setFontStyle("bold"); + var tempHeaderConf = []; + + for (i = 0, ln = this.tableHeaderRow.length; i < ln; i += 1) { + this.setFillColor(200, 200, 200); + tableHeaderCell = this.tableHeaderRow[i]; + + if (new_page) { + this.margins.top = margin; + tableHeaderCell[1] = this.margins && this.margins.top || 0; + tempHeaderConf.push(tableHeaderCell); + } + + tmpArray = [].concat(tableHeaderCell); + this.cell.apply(this, tmpArray.concat(lineNumber)); + } + + if (tempHeaderConf.length > 0) { + this.setTableHeaderRow(tempHeaderConf); + } + + this.setFontStyle("normal"); + this.printingHeaderRow = false; + }; + })(jsPDF.API); + + /** + * jsPDF Context2D PlugIn Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv + * + * Licensed under the MIT License. http://opensource.org/licenses/mit-license + */ + + /** + * TODO implement stroke opacity (refactor from fill() method ) + * TODO transform angle and radii parameters + */ + + /** + * This plugin mimics the HTML5 Canvas's context2d. + * + * The goal is to provide a way for current canvas implementations to print directly to a PDF. + * + * @name context2d + * @module + */ + (function (jsPDFAPI, globalObj) { + + jsPDFAPI.events.push(["initialized", function () { + this.context2d.pdf = this; + this.context2d.internal.pdf = this; + this.context2d.ctx = new context(); + this.context2d.ctxStack = []; + this.context2d.path = []; + }]); + jsPDFAPI.context2d = { + /** + * @name pageWrapXEnabled + * @type {boolean} + * @default false + */ + pageWrapXEnabled: false, + + /** + * @name pageWrapYEnabled + * @type {boolean} + * @default false + */ + pageWrapYEnabled: false, + + /** + * @name pageWrapX + * @type {number} + * @default 9999999 + */ + pageWrapX: 9999999, + + /** + * @name pageWrapY + * @type {number} + * @default 9999999 + */ + pageWrapY: 9999999, + + /** + * @name ctx + * @type {Object} + */ + ctx: new context(), + + /** + * @name f2 + * @type {function} + * @ignore + */ + f2: function f2(number) { + return number.toFixed(2); + }, + + /** + * Fills the current drawing (path) + * + * @name fill + * @function + * @description The fill() method fills the current drawing (path). The default color is black. + */ + fill: function fill() { + //evenodd or nonzero (default) + var rule = "fill"; + + this._drawPaths(rule, false); + }, + + /** + * Actually draws the path you have defined + * + * @name stroke + * @function + * @description The stroke() method actually draws the path you have defined with all those moveTo() and lineTo() methods. The default color is black. + */ + stroke: function stroke() { + var rule = "stroke"; + + this._drawPaths(rule, false); + }, + + /** + * Begins a path, or resets the current + * + * @name beginPath + * @function + * @description The beginPath() method begins a path, or resets the current path. + */ + beginPath: function beginPath() { + this._resetPath(); + + this._beginPath(); + }, + + /** + * Moves the path to the specified point in the canvas, without creating a line + * + * @name moveTo + * @function + * @param x {Number} The x-coordinate of where to move the path to + * @param y {Number} The y-coordinate of where to move the path to + */ + moveTo: function moveTo(x, y) { + x = this._wrapX(x); + y = this._wrapY(y); + + var xpt = this._matrix_map_point(this.ctx._transform, [x, y]); + + x = xpt[0]; + y = xpt[1]; + var obj = { + type: "mt", + x: x, + y: y + }; + this.path.push(obj); + }, + + /** + * Creates a path from the current point back to the starting point + * + * @name closePath + * @function + * @description The closePath() method creates a path from the current point back to the starting point. + */ + closePath: function closePath() { + this._closePath(); + + var obj = { + type: "close" + }; + this.path.push(obj); + }, + + /** + * Adds a new point and creates a line to that point from the last specified point in the canvas + * + * @name lineTo + * @function + * @param x The x-coordinate of where to create the line to + * @param y The y-coordinate of where to create the line to + * @description The lineTo() method adds a new point and creates a line TO that point FROM the last specified point in the canvas (this method does not draw the line). + */ + lineTo: function lineTo(x, y) { + x = this._wrapX(x); + y = this._wrapY(y); + + var xpt = this._matrix_map_point(this.ctx._transform, [x, y]); + + x = xpt[0]; + y = xpt[1]; + var obj = { + type: "lt", + x: x, + y: y + }; + this.path.push(obj); + }, + + /** + * Clips a region of any shape and size from the original canvas + * + * @name clip + * @function + * @description The clip() method clips a region of any shape and size from the original canvas. + */ + clip: function clip() { + this._drawPaths(null, true); + }, + + /** + * Creates a cubic Bézier curve + * + * @name quadraticCurveTo + * @function + * @param cpx {Number} The x-coordinate of the Bézier control point + * @param cpy {Number} The y-coordinate of the Bézier control point + * @param x {Number} The x-coordinate of the ending point + * @param y {Number} The y-coordinate of the ending point + * @description The quadraticCurveTo() method adds a point to the current path by using the specified control points that represent a quadratic Bézier curve.

    A quadratic Bézier curve requires two points. The first point is a control point that is used in the quadratic Bézier calculation and the second point is the ending point for the curve. The starting point for the curve is the last point in the current path. If a path does not exist, use the beginPath() and moveTo() methods to define a starting point. + */ + quadraticCurveTo: function quadraticCurveTo(cpx, cpy, x, y) { + var x1 = this._wrapX(cpx); + + var y1 = this._wrapY(cpy); + + x = this._wrapX(x); + y = this._wrapY(y); + var xpt; + xpt = this._matrix_map_point(this.ctx._transform, [x, y]); + x = xpt[0]; + y = xpt[1]; + xpt = this._matrix_map_point(this.ctx._transform, [x1, y1]); + x1 = xpt[0]; + y1 = xpt[1]; + var obj = { + type: "qct", + x1: x1, + y1: y1, + x: x, + y: y + }; + this.path.push(obj); + }, + + /** + * Creates a cubic Bézier curve + * + * @name bezierCurveTo + * @function + * @param cp1x {Number} The x-coordinate of the first Bézier control point + * @param cp1y {Number} The y-coordinate of the first Bézier control point + * @param cp2x {Number} The x-coordinate of the second Bézier control point + * @param cp2y {Number} The y-coordinate of the second Bézier control point + * @param x {Number} The x-coordinate of the ending point + * @param y {Number} The y-coordinate of the ending point + * @description The bezierCurveTo() method adds a point to the current path by using the specified control points that represent a cubic Bézier curve.

    A cubic bezier curve requires three points. The first two points are control points that are used in the cubic Bézier calculation and the last point is the ending point for the curve. The starting point for the curve is the last point in the current path. If a path does not exist, use the beginPath() and moveTo() methods to define a starting point. + */ + bezierCurveTo: function bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) { + var x1 = this._wrapX(cp1x); + + var y1 = this._wrapY(cp1y); + + var x2 = this._wrapX(cp2x); + + var y2 = this._wrapY(cp2y); + + x = this._wrapX(x); + y = this._wrapY(y); + var xpt; + xpt = this._matrix_map_point(this.ctx._transform, [x, y]); + x = xpt[0]; + y = xpt[1]; + xpt = this._matrix_map_point(this.ctx._transform, [x1, y1]); + x1 = xpt[0]; + y1 = xpt[1]; + xpt = this._matrix_map_point(this.ctx._transform, [x2, y2]); + x2 = xpt[0]; + y2 = xpt[1]; + var obj = { + type: "bct", + x1: x1, + y1: y1, + x2: x2, + y2: y2, + x: x, + y: y + }; + this.path.push(obj); + }, + + /** + * Creates an arc/curve (used to create circles, or parts of circles) + * + * @name arc + * @function + * @param x {Number} The x-coordinate of the center of the circle + * @param y {Number} The y-coordinate of the center of the circle + * @param radius {Number} The radius of the circle + * @param startAngle {Number} The starting angle, in radians (0 is at the 3 o'clock position of the arc's circle) + * @param endAngle {Number} The ending angle, in radians + * @param counterclockwise {Boolean} Optional. Specifies whether the drawing should be counterclockwise or clockwise. False is default, and indicates clockwise, while true indicates counter-clockwise. + * @description The arc() method creates an arc/curve (used to create circles, or parts of circles). + */ + arc: function arc(x, y, radius, startAngle, endAngle, counterclockwise) { + x = this._wrapX(x); + y = this._wrapY(y); + counterclockwise = counterclockwise || false; + + if (!this._matrix_is_identity(this.ctx._transform)) { + var xpt = this._matrix_map_point(this.ctx._transform, [x, y]); + + x = xpt[0]; + y = xpt[1]; + + var x_radPt0 = this._matrix_map_point(this.ctx._transform, [0, 0]); + + var x_radPt = this._matrix_map_point(this.ctx._transform, [0, radius]); + + radius = Math.sqrt(Math.pow(x_radPt[0] - x_radPt0[0], 2) + Math.pow(x_radPt[1] - x_radPt0[1], 2)); + } + + var obj = { + type: "arc", + x: x, + y: y, + radius: radius, + startAngle: startAngle, + endAngle: endAngle, + counterclockwise: counterclockwise + }; + this.path.push(obj); + }, + + /** + * Creates an arc/curve between two tangents + * + * @name arcTo + * @function + * @param x1 {Number} The x-coordinate of the first tangent + * @param y1 {Number} The y-coordinate of the first tangent + * @param x2 {Number} The x-coordinate of the second tangent + * @param y2 {Number} The y-coordinate of the second tangent + * @param radius The radius of the + * @description The arcTo() method creates an arc/curve between two tangents on the canvas. + */ + arcTo: function arcTo(x1, y1, x2, y2, radius) {//TODO needs to be implemented + }, + //Rectangles + + /** + * Creates a rectangle + * + * @name rect + * @function + * @param x {Number} The x-coordinate of the upper-left corner of the rectangle + * @param y {Number} The y-coordinate of the upper-left corner of the rectangle + * @param w {Number} The width of the rectangle, in pixels + * @param h {Number} The height of the rectangle, in pixels + * @description The rect() method creates a rectangle. + */ + rect: function rect(x, y, w, h) { + this.moveTo(x, y); + this.lineTo(x + w, y); + this.lineTo(x + w, y + h); + this.lineTo(x, y + h); + this.lineTo(x, y); + this.lineTo(x + w, y); + this.lineTo(x, y); + }, + + /** + * Draws a "filled" rectangle + * + * @name fillRect + * @function + * @param x {Number} The x-coordinate of the upper-left corner of the rectangle + * @param y {Number} The y-coordinate of the upper-left corner of the rectangle + * @param w {Number} The width of the rectangle, in pixels + * @param h {Number} The height of the rectangle, in pixels + * @description The fillRect() method draws a "filled" rectangle. The default color of the fill is black. + */ + fillRect: function fillRect(x, y, w, h) { + if (this._isFillTransparent()) { + return; + } + + x = this._wrapX(x); + y = this._wrapY(y); + + var xpt1 = this._matrix_map_point(this.ctx._transform, [x, y]); + + var xpt2 = this._matrix_map_point(this.ctx._transform, [x + w, y]); + + var xpt3 = this._matrix_map_point(this.ctx._transform, [x + w, y + h]); + + var xpt4 = this._matrix_map_point(this.ctx._transform, [x, y + h]); + + this.pdf.internal.out("q"); + this.pdf.setLineCap("butt"); + this.pdf.setLineJoin("miter"); + var lines = []; + lines.push([xpt2[0] - xpt1[0], xpt2[1] - xpt1[1]]); + lines.push([xpt3[0] - xpt2[0], xpt3[1] - xpt2[1]]); + lines.push([xpt4[0] - xpt3[0], xpt4[1] - xpt3[1]]); + lines.push([xpt1[0] - xpt4[0], xpt1[1] - xpt4[1]]); + lines.push([xpt2[0] - xpt1[0], xpt2[1] - xpt1[1]]); + lines.push([xpt1[0] - xpt2[0], xpt1[1] - xpt2[1]]); + this.pdf.lines(lines, xpt1[0], xpt1[1], null, "F"); + this.pdf.internal.out("Q"); + }, + + /** + * Draws a rectangle (no fill) + * + * @name strokeRect + * @function + * @param x {Number} The x-coordinate of the upper-left corner of the rectangle + * @param y {Number} The y-coordinate of the upper-left corner of the rectangle + * @param w {Number} The width of the rectangle, in pixels + * @param h {Number} The height of the rectangle, in pixels + * @description The strokeRect() method draws a rectangle (no fill). The default color of the stroke is black. + */ + strokeRect: function strokeRect(x, y, w, h) { + if (this._isStrokeTransparent()) { + return; + } + + x = this._wrapX(x); + y = this._wrapY(y); + + var xpt1 = this._matrix_map_point(this.ctx._transform, [x, y]); + + var xpt2 = this._matrix_map_point(this.ctx._transform, [x + w, y]); + + var xpt3 = this._matrix_map_point(this.ctx._transform, [x + w, y + h]); + + var xpt4 = this._matrix_map_point(this.ctx._transform, [x, y + h]); + + var lines = []; + lines.push([xpt2[0] - xpt1[0], xpt2[1] - xpt1[1]]); + lines.push([xpt3[0] - xpt2[0], xpt3[1] - xpt2[1]]); + lines.push([xpt4[0] - xpt3[0], xpt4[1] - xpt3[1]]); + lines.push([xpt1[0] - xpt4[0], xpt1[1] - xpt4[1]]); + lines.push([xpt2[0] - xpt1[0], xpt2[1] - xpt1[1]]); + lines.push([xpt1[0] - xpt2[0], xpt1[1] - xpt2[1]]); + this.pdf.lines(lines, xpt1[0], xpt1[1], null, "S"); + }, + + /** + * Clears the specified pixels within a given rectangle + * + * @name clearRect + * @function + * @param x {Number} The x-coordinate of the upper-left corner of the rectangle + * @param y {Number} The y-coordinate of the upper-left corner of the rectangle + * @param w {Number} The width of the rectangle to clear, in pixels + * @param h {Number} The height of the rectangle to clear, in pixels + * @description We cannot clear PDF commands that were already written to PDF, so we use white instead.
    + * As a special case, read a special flag (ignoreClearRect) and do nothing if it is set. + * This results in all calls to clearRect() to do nothing, and keep the canvas transparent. + * This flag is stored in the save/restore context and is managed the same way as other drawing states. + * + */ + clearRect: function clearRect(x, y, w, h) { + if (this.ctx.ignoreClearRect) { + return; + } + + this.save(); + + this._setFillStyle("#ffffff"); + + this.fillRect(x, y, w, h); + this.restore(); + }, + //Other + + /** + * Saves the state of the current context + * + * @name save + * @function + */ + save: function save() { + this.pdf.internal.out("q"); + this.ctx._fontSize = this.pdf.internal.getFontSize(); + var ctx = new context(); + ctx.copy(this.ctx); + this.ctxStack.push(this.ctx); + this.ctx = ctx; + }, + + /** + * Returns previously saved path state and attributes + * + * @name restore + * @function + */ + restore: function restore() { + this.pdf.internal.out("Q"); + + if (this.ctxStack.length !== 0) { + this.ctx = this.ctxStack.pop(); + + this._setFillStyle(this.ctx.fillStyle); + + this._setStrokeStyle(this.ctx.strokeStyle); + + this._setFont(this.ctx.font); + + this.pdf.setFontSize(this.ctx._fontSize); + + this._setLineCap(this.ctx.lineCap); + + this._setLineWidth(this.ctx.lineWidth); + + this._setLineJoin(this.ctx.lineJoin); + } + }, + // some stubs + + /** + * @name createEvent + * @function + */ + createEvent: function createEvent() { + console.log("createEvent not implemented (yet)"); + }, + + /** + * @name toDataURL + * @function + */ + toDataURL: function toDataURL() { + console.log("toDataUrl not implemented (yet)"); + }, + //helper functions + _beginPath: function _beginPath() { + this.path.push({ + type: "begin" + }); + }, + _closePath: function _closePath() { + var pathBegin = { + x: 0, + y: 0 + }; + var i = 0; + var len = this.path.length; + + for (i = this.path.length - 1; i !== -1; i--) { + if (this.path[i].type === "begin") { + if (_typeof(this.path[i + 1]) === "object" && typeof this.path[i + 1].x === "number") { + pathBegin = { + x: this.path[i + 1].x, + y: this.path[i + 1].y + }; + var obj = { + type: "lt", + x: pathBegin.x, + y: pathBegin.y + }; + this.path.push(obj); + break; + } + } + } //TODO Repeat second move to get lineJoins correct, maybe only when lineJoin active in _drawPaths + + + if (_typeof(this.path[i + 2]) === "object" && typeof this.path[i + 2].x === "number") { + this.path.push(JSON.parse(JSON.stringify(this.path[i + 2]))); + } + }, + _resetPath: function _resetPath() { + this.path = []; + }, + + /** + * Get the decimal values of r, g, b and a + * + * @name _getRGBA + * @function + * @private + * @ignore + */ + _getRGBA: function _getRGBA(style) { + var r, g, b, a; + + if (style.isCanvasGradient === true) { + style = style.getColor(); + } + + var rgbColor = new RGBColor(style); + + if (!style) { + return { + r: 0, + g: 0, + b: 0, + a: 0, + style: style + }; + } + + if (this.internal.rxTransparent.test(style)) { + r = 0; + g = 0; + b = 0; + a = 0; + } else { + var m = this.internal.rxRgb.exec(style); + + if (m != null) { + r = parseInt(m[1]); + g = parseInt(m[2]); + b = parseInt(m[3]); + a = 1; + } else { + m = this.internal.rxRgba.exec(style); + + if (m != null) { + r = parseInt(m[1]); + g = parseInt(m[2]); + b = parseInt(m[3]); + a = parseFloat(m[4]); + } else { + a = 1; + + if (style.charAt(0) != "#") { + if (rgbColor.ok) { + style = rgbColor.toHex(); + } else { + style = "#000000"; + } + } + + if (style.length === 4) { + r = style.substring(1, 2); + r += r; + g = style.substring(2, 3); + g += g; + b = style.substring(3, 4); + b += b; + } else { + r = style.substring(1, 3); + g = style.substring(3, 5); + b = style.substring(5, 7); + } + + r = parseInt(r, 16); + g = parseInt(g, 16); + b = parseInt(b, 16); + } + } + } + + return { + r: r, + g: g, + b: b, + a: a, + style: style + }; + }, + + /** + * @name _isFilllTransparent + * @function + * @private + * @ignore + * @returns {Boolean} + */ + _isFillTransparent: function _isFillTransparent() { + return this.ctx._isFillTransparent || this.globalAlpha == 0; + }, + + /** + * @name _isStrokeTransparent + * @function + * @private + * @ignore + * @returns {Boolean} + */ + _isStrokeTransparent: function _isStrokeTransparent() { + return this.ctx._isStrokeTransparent || this.globalAlpha == 0; + }, + + /** + * Sets the color, gradient, or pattern used to fill the drawing + * + * @name _setFillStyle + * @function + * @private + * @ignore + */ + _setFillStyle: function _setFillStyle(style) { + var rgba; + rgba = this._getRGBA(style); + this.ctx.fillStyle = style; + this.ctx._isFillTransparent = rgba.a === 0; + this.ctx._fillOpacity = rgba.a; + this.pdf.setFillColor(rgba.r, rgba.g, rgba.b, { + a: rgba.a + }); + this.pdf.setTextColor(rgba.r, rgba.g, rgba.b, { + a: rgba.a + }); + }, + + /** + * Sets the color, gradient, or pattern used for strokes + * + * @name _setStrokeStyle + * @function + * @private + * @ignore + */ + _setStrokeStyle: function _setStrokeStyle(style) { + var rgba = this._getRGBA(style); + + this.ctx.strokeStyle = rgba.style; + this.ctx._isStrokeTransparent = rgba.a === 0; + this.ctx._strokeOpacity = rgba.a; //TODO jsPDF to handle rgba + + if (rgba.a === 0) { + this.pdf.setDrawColor(255, 255, 255); + } else if (rgba.a === 1) { + this.pdf.setDrawColor(rgba.r, rgba.g, rgba.b); + } else { + //this.pdf.setDrawColor(rgba.r, rgba.g, rgba.b, {a: rgba.a}); + this.pdf.setDrawColor(rgba.r, rgba.g, rgba.b); + } + }, + + /** + * Sets font properties for text content + * + * @name _setFont + * @function + * @param {String} The font property uses the same syntax as the CSS font property. + * @private + * @ignore + */ + _setFont: function _setFont(font) { + this.ctx.font = font; + var rx, m; //source: https://stackoverflow.com/a/10136041 + + rx = /^\s*(?=(?:(?:[-a-z]+\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\"\'\sa-z]+?)\s*$/i; + m = rx.exec(font); + + if (m != null) { + var fontStyle = m[1]; + var fontVariant = m[2]; + var fontWeight = m[3]; + var fontSize = m[4]; + var fontSizeUnit = m[5]; + var fontFamily = m[6]; + } else { + return; + } + + if ("px" === fontSizeUnit) { + fontSize = Math.floor(parseFloat(fontSize)); // fontSize = fontSize * 1.25; + } else if ("em" === fontSizeUnit) { + fontSize = Math.floor(parseFloat(fontSize) * this.pdf.getFontSize()); + } else { + fontSize = Math.floor(parseFloat(fontSize)); + } + + this.pdf.setFontSize(fontSize); + var style = ""; + + if (fontWeight === "bold" || parseInt(fontWeight, 10) >= 700 || fontStyle === "bold") { + style = "bold"; + } + + if (fontStyle === "italic") { + style += "italic"; + } + + if (style.length === 0) { + style = "normal"; + } + + var jsPdfFontName = ""; + var parts = fontFamily.toLowerCase().replace(/"|'/g, "").split(/\s*,\s*/); + var fallbackFonts = { + arial: "Helvetica", + verdana: "Helvetica", + helvetica: "Helvetica", + "sans-serif": "Helvetica", + fixed: "Courier", + monospace: "Courier", + terminal: "Courier", + courier: "Courier", + times: "Times", + cursive: "Times", + fantasy: "Times", + serif: "Times" + }; + + for (var i = 0; i < parts.length; i++) { + if (this.pdf.internal.getFont(parts[i], style, { + noFallback: true, + disableWarning: true + }) !== undefined) { + jsPdfFontName = parts[i]; + break; + } else if (style === "bolditalic" && this.pdf.internal.getFont(parts[i], "bold", { + noFallback: true, + disableWarning: true + }) !== undefined) { + jsPdfFontName = parts[i]; + style = "bold"; + } else if (this.pdf.internal.getFont(parts[i], "normal", { + noFallback: true, + disableWarning: true + }) !== undefined) { + jsPdfFontName = parts[i]; + style = "normal"; + break; + } + } + + if (jsPdfFontName === "") { + for (var i = 0; i < parts.length; i++) { + if (fallbackFonts[parts[i]]) { + jsPdfFontName = fallbackFonts[parts[i]]; + break; + } + } + } + + jsPdfFontName = jsPdfFontName === "" ? "Times" : jsPdfFontName; + this.pdf.setFont(jsPdfFontName, style); + }, + + /** + * @name _setTextBaseline + * @function + * @private + * @ignore + */ + _setTextBaseline: function _setTextBaseline(baseline) { + this.ctx.textBaseline = baseline; + }, + + /** + * @name _getTextBaseline + * @function + * @private + * @ignore + * @returns {Number} + */ + _getTextBaseline: function _getTextBaseline() { + return this.ctx.textBaseline; + }, + + /** + * @name _setTextAlign + * @function + * @private + * @ignore + */ + _setTextAlign: function _setTextAlign(canvasAlign) { + switch (canvasAlign) { + case "right": + case "end": + this.ctx.textAlign = "right"; + break; + + case "center": + this.ctx.textAlign = "center"; + break; + + case "left": + case "start": + default: + this.ctx.textAlign = "left"; + break; + } + }, + + /** + * @name _getTextAlign + * @function + * @private + * @ignore + * @returns {String} + */ + _getTextAlign: function _getTextAlign() { + return this.ctx.textAlign; + }, + + /** + * Draws "filled" text on the canvas + * + * @name fillText + * @function + * @param text {String} Specifies the text that will be written on the canvas + * @param x {Number} The x coordinate where to start painting the text (relative to the canvas) + * @param y {Number} The y coordinate where to start painting the text (relative to the canvas) + * @param maxWidth {Number} Optional. The maximum allowed width of the text, in pixels + * @description The fillText() method draws filled text on the canvas. The default color of the text is black. + */ + fillText: function fillText(text, x, y, maxWidth) { + if (this._isFillTransparent()) { + return; + } + + x = this._wrapX(x); + y = this._wrapY(y); + + var xpt = this._matrix_map_point(this.ctx._transform, [x, y]); + + x = xpt[0]; + y = xpt[1]; + + var rads = this._matrix_rotation(this.ctx._transform); + + var degs = rads * 57.2958; // We only use X axis as scale hint + + var scale = 1; + + try { + scale = this._matrix_decompose(this._getTransform()).scale[0]; + } catch (e) { + console.warn(e); + } // In some cases the transform was very small (5.715760606202283e-17). Most likely a canvg rounding error. + + + if (scale < 0.01) { + this.pdf.text(text, x, this._getBaseline(y), { + angle: degs, + align: this.textAlign + }); + } else { + var oldSize = this.pdf.internal.getFontSize(); + this.pdf.setFontSize(oldSize * scale); + this.pdf.text(text, x, this._getBaseline(y), { + angle: degs, + align: this.textAlign + }); + this.pdf.setFontSize(oldSize); + } + }, + + /** + * Draws text on the canvas (no fill) + * + * @name strokeText + * @function + * @param text {String} Specifies the text that will be written on the canvas + * @param x {Number} The x coordinate where to start painting the text (relative to the canvas) + * @param y {Number} The y coordinate where to start painting the text (relative to the canvas) + * @param maxWidth {Number} Optional. The maximum allowed width of the text, in pixels + * @description The strokeText() method draws text (with no fill) on the canvas. The default color of the text is black. + */ + strokeText: function strokeText(text, x, y, maxWidth) { + if (this._isStrokeTransparent()) { + return; + } + + x = this._wrapX(x); + y = this._wrapY(y); + + var xpt = this._matrix_map_point(this.ctx._transform, [x, y]); + + x = xpt[0]; + y = xpt[1]; + + var rads = this._matrix_rotation(this.ctx._transform); + + var degs = rads * 57.2958; + var scale = 1; // We only use the X axis as scale hint + + try { + scale = this._matrix_decompose(this._getTransform()).scale[0]; + } catch (e) { + console.warn(e); + } + + if (scale < 0.01) { + this.pdf.text(text, x, this._getBaseline(y), { + angle: degs, + align: this.textAlign, + renderingMode: "stroke" + }); + } else { + var oldSize = this.pdf.internal.getFontSize(); + this.pdf.setFontSize(oldSize * scale); + this.pdf.text(text, x, this._getBaseline(y), { + angle: degs, + align: this.textAlign, + renderingMode: "stroke" + }); + this.pdf.setFontSize(oldSize); + } + }, + + /** + * Returns an object that contains the width of the specified text + * + * @name measureText + * @function + * @param text {String} The text to be measured + * @description The measureText() method returns an object that contains the width of the specified text, in pixels. + * @returns {Number} + */ + measureText: function measureText(text) { + var pdf = this.pdf; + return { + getWidth: function getWidth() { + var fontSize = pdf.internal.getFontSize(); + var txtWidth = pdf.getStringUnitWidth(text) * fontSize / pdf.internal.scaleFactor; // Convert points to pixels + //TODO Use scaleFactor? + + txtWidth *= 1.3333; + return txtWidth; + }, + + get width() { + return this.getWidth(text); + } + + }; + }, + //Line Styles + + /** + * + * @name _setLineWidth + * @function + * @private + * @ignore + */ + _setLineWidth: function _setLineWidth(width) { + this.ctx.lineWidth = width; + this.pdf.setLineWidth(width); + }, + + /** + * @name _setLineCap + * @function + * @private + * @ignore + */ + _setLineCap: function _setLineCap(style) { + this.ctx.lineCap = style; + this.pdf.setLineCap(style); + }, + + /** + * + * @name _setLineJoin + * @function + * @private + * @ignore + */ + _setLineJoin: function _setLineJoin(style) { + this.ctx.lineJoin = style; + this.pdf.setLineJoin(style); + }, + + /** + * + * @name _getLineJoin + * @function + * @private + * @ignore + */ + _getLineJoin: function _getLineJoin() { + return this.ctx.lineJoin; + }, + + /** + * + * @name _wrapX + * @function + * @private + * @ignore + */ + _wrapX: function _wrapX(x) { + if (this.pageWrapXEnabled) { + return x % this.pageWrapX; + } else { + return x; + } + }, + + /** + * @name _wrapY + * @function + * @private + * @ignore + */ + _wrapY: function _wrapY(y) { + if (this.pageWrapYEnabled) { + this._gotoPage(this._page(y)); + + return (y - this.lastBreak) % this.pageWrapY; + } else { + return y; + } + }, + //Transformations + + /** + * Scales the current drawing bigger or smaller + * + * @name scale + * @function + * @param scalewidth {Number} Scales the width of the current drawing (1=100%, 0.5=50%, 2=200%, etc.) + * @param scaleheight {Number} Scales the height of the current drawing (1=100%, 0.5=50%, 2=200%, etc.) + * @description The scale() method scales the current drawing, bigger or smaller. + */ + scale: function scale(scalewidth, scaleheight) { + var matrix = [scalewidth, 0.0, 0.0, scaleheight, 0.0, 0.0]; + this.ctx._transform = this._matrix_multiply(this.ctx._transform, matrix); + }, + + /** + * Rotates the current drawing + * + * @name rotate + * @function + * @param angle {Number} The rotation angle, in radians. + * @description To calculate from degrees to radians: degrees*Math.PI/180.
    + * Example: to rotate 5 degrees, specify the following: 5*Math.PI/180 + */ + rotate: function rotate(angle) { + var matrix = [Math.cos(angle), Math.sin(angle), -Math.sin(angle), Math.cos(angle), 0.0, 0.0]; + this.ctx._transform = this._matrix_multiply(this.ctx._transform, matrix); + }, + + /** + * Remaps the (0,0) position on the canvas + * + * @name translate + * @function + * @param x {Number} The value to add to horizontal (x) coordinates + * @param y {Number} The value to add to vertical (y) coordinates + * @description The translate() method remaps the (0,0) position on the canvas. + */ + translate: function translate(x, y) { + var matrix = [1.0, 0.0, 0.0, 1.0, x, y]; + this.ctx._transform = this._matrix_multiply(this.ctx._transform, matrix); + }, + + /** + * Replaces the current transformation matrix for the drawing + * + * @name transform + * @function + * @param a {Number} Horizontal scaling + * @param b {Number} Horizontal skewing + * @param c {Number} Vertical skewing + * @param d {Number} Vertical scaling + * @param e {Number} Horizontal moving + * @param f {Number} Vertical moving + * @description Each object on the canvas has a current transformation matrix.

    The transform() method replaces the current transformation matrix. It multiplies the current transformation matrix with the matrix described by:



    a c e

    b d f

    0 0 1

    In other words, the transform() method lets you scale, rotate, move, and skew the current context. + */ + transform: function transform(a, b, c, d, e, f) { + this.ctx._transform = this._matrix_multiply(this.ctx._transform, [a, b, c, d, e, f]); + }, + + /** + * Resets the current transform to the identity matrix. Then runs transform() + * + * @name setTransform + * @function + * @param a {Number} Horizontal scaling + * @param b {Number} Horizontal skewing + * @param c {Number} Vertical skewing + * @param d {Number} Vertical scaling + * @param e {Number} Horizontal moving + * @param f {Number} Vertical moving + * @description Each object on the canvas has a current transformation matrix.

    The setTransform() method resets the current transform to the identity matrix, and then runs transform() with the same arguments.

    In other words, the setTransform() method lets you scale, rotate, move, and skew the current context. + */ + setTransform: function setTransform(a, b, c, d, e, f) { + this.ctx._transform = [a, b, c, d, e, f]; + }, + + /** + * @name _getTransform + * @function + * @private + * @ignore + */ + _getTransform: function _getTransform() { + return this.ctx._transform; + }, + lastBreak: 0, + // Y Position of page breaks. + pageBreaks: [], + + /** + * Should only be used if pageWrapYEnabled is true + * + * @name _page + * @function + * @private + * @ignore + * @returns One-based Page Number + */ + _page: function _page(y) { + if (this.pageWrapYEnabled) { + this.lastBreak = 0; + var manualBreaks = 0; + var autoBreaks = 0; + + for (var i = 0; i < this.pageBreaks.length; i++) { + if (y >= this.pageBreaks[i]) { + manualBreaks++; + + if (this.lastBreak === 0) { + autoBreaks++; + } + + var spaceBetweenLastBreak = this.pageBreaks[i] - this.lastBreak; + this.lastBreak = this.pageBreaks[i]; + var pagesSinceLastBreak = Math.floor(spaceBetweenLastBreak / this.pageWrapY); + autoBreaks += pagesSinceLastBreak; + } + } + + if (this.lastBreak === 0) { + var pagesSinceLastBreak = Math.floor(y / this.pageWrapY) + 1; + autoBreaks += pagesSinceLastBreak; + } + + return autoBreaks + manualBreaks; + } else { + return this.pdf.internal.getCurrentPageInfo().pageNumber; + } + }, + _gotoPage: function _gotoPage(pageOneBased) {// This is a stub to be overriden if needed + }, + + /** + * Draws an image, canvas, or video onto the canvas + * + * @function + * @param img {} Specifies the image, canvas, or video element to use + * @param sx {Number} Optional. The x coordinate where to start clipping + * @param sy {Number} Optional. The y coordinate where to start clipping + * @param swidth {Number} Optional. The width of the clipped image + * @param sheight {Number} Optional. The height of the clipped image + * @param x {Number} The x coordinate where to place the image on the canvas + * @param y {Number} The y coordinate where to place the image on the canvas + * @param width {Number} Optional. The width of the image to use (stretch or reduce the image) + * @param height {Number} Optional. The height of the image to use (stretch or reduce the image) + * + */ + drawImage: function drawImage(img, x, y, w, h, x2, y2, w2, h2) { + if (x2 !== undefined) { + x = x2; + y = y2; + w = w2; + h = h2; + } + + x = this._wrapX(x); + y = this._wrapY(y); + + var xRect = this._matrix_map_rect(this.ctx._transform, { + x: x, + y: y, + w: w, + h: h + }); + + var xRect2 = this._matrix_map_rect(this.ctx._transform, { + x: x2, + y: y2, + w: w2, + h: h2 + }); // TODO implement source clipping and image scaling + + + var format; + var rx = /data:image\/(\w+).*/i; + var m = rx.exec(img); + + if (m != null) { + format = m[1]; + } else { + // format = "jpeg"; + format = "png"; + } + + this.pdf.addImage(img, format, xRect.x, xRect.y, xRect.w, xRect.h); + }, + + /** + * Multiply the first matrix by the second + * + * @name matrix_multiply + * @function + * @param m1 + * @param m2 + * @returns {Array} + * @private + * @ignore + */ + _matrix_multiply: function _matrix_multiply(m2, m1) { + var sx = m1[0]; + var shy = m1[1]; + var shx = m1[2]; + var sy = m1[3]; + var tx = m1[4]; + var ty = m1[5]; + var t0 = sx * m2[0] + shy * m2[2]; + var t2 = shx * m2[0] + sy * m2[2]; + var t4 = tx * m2[0] + ty * m2[2] + m2[4]; + shy = sx * m2[1] + shy * m2[3]; + sy = shx * m2[1] + sy * m2[3]; + ty = tx * m2[1] + ty * m2[3] + m2[5]; + sx = t0; + shx = t2; + tx = t4; + return [sx, shy, shx, sy, tx, ty]; + }, + + /** + * @name _matrix_rotation + * @function + * @private + * @ignore + */ + _matrix_rotation: function _matrix_rotation(m) { + return Math.atan2(m[2], m[0]); + }, + + /** + * @name _matrix_decompose + * @function + * @private + * @ignore + */ + _matrix_decompose: function _matrix_decompose(matrix) { + var a = matrix[0]; + var b = matrix[1]; + var c = matrix[2]; + var d = matrix[3]; + var scaleX = Math.sqrt(a * a + b * b); + a /= scaleX; + b /= scaleX; + var shear = a * c + b * d; + c -= a * shear; + d -= b * shear; + var scaleY = Math.sqrt(c * c + d * d); + c /= scaleY; + d /= scaleY; + shear /= scaleY; + + if (a * d < b * c) { + a = -a; + b = -b; + shear = -shear; + scaleX = -scaleX; + } + + return { + scale: [scaleX, 0, 0, scaleY, 0, 0], + translate: [1, 0, 0, 1, matrix[4], matrix[5]], + rotate: [a, b, -b, a, 0, 0], + skew: [1, 0, shear, 1, 0, 0] + }; + }, + + /** + * @name _matrix_map_point + * @function + * @private + * @ignore + */ + _matrix_map_point: function _matrix_map_point(m1, pt) { + var sx = m1[0]; + var shy = m1[1]; + var shx = m1[2]; + var sy = m1[3]; + var tx = m1[4]; + var ty = m1[5]; + var px = pt[0]; + var py = pt[1]; + var x = px * sx + py * shx + tx; + var y = px * shy + py * sy + ty; + return [x, y]; + }, + + /** + * @name _matrix_map_point_obj + * @function + * @private + * @ignore + */ + _matrix_map_point_obj: function _matrix_map_point_obj(m1, pt) { + var xpt = this._matrix_map_point(m1, [pt.x, pt.y]); + + return { + x: xpt[0], + y: xpt[1] + }; + }, + + /** + * @name _matrix_map_rect + * @function + * @private + * @ignore + */ + _matrix_map_rect: function _matrix_map_rect(m1, rect) { + var p1 = this._matrix_map_point(m1, [rect.x, rect.y]); + + var p2 = this._matrix_map_point(m1, [rect.x + rect.w, rect.y + rect.h]); + + return { + x: p1[0], + y: p1[1], + w: p2[0] - p1[0], + h: p2[1] - p1[1] + }; + }, + + /** + * @name _matrix_is_identity + * @function + * @private + * @ignore + */ + _matrix_is_identity: function _matrix_is_identity(m1) { + if (m1[0] != 1) { + return false; + } + + if (m1[1] != 0) { + return false; + } + + if (m1[2] != 0) { + return false; + } + + if (m1[3] != 1) { + return false; + } + + if (m1[4] != 0) { + return false; + } + + if (m1[5] != 0) { + return false; + } + + return true; + }, + + /** + * Processes the paths + * + * @function + * @param rule {String} + * @param isClip {Boolean} + * @private + * @ignore + */ + _drawPaths: function _drawPaths(rule, isClip) { + var isStroke = rule === "stroke"; + var isFill = !isStroke; + + if (isStroke && !isClip && this._isStrokeTransparent()) { + return; + } + + if (isFill && !isClip && this._isFillTransparent()) { + return; + } + + var v2Support = typeof this.pdf.internal.newObject2 === "function"; + var lines; + + if (globalObj.outIntercept) { + lines = globalObj.outIntercept.type === "group" ? globalObj.outIntercept.stream : globalObj.outIntercept; + } else { + lines = this.internal.getCurrentPage(); + } + + var moves = []; + var outInterceptOld = globalObj.outIntercept; + /* + if (v2Support) { + // Blend and Mask + switch (this.ctx.globalCompositeOperation) { + case 'normal': + case 'source-over': + break; + case 'destination-in': + case 'destination-out': + //TODO this need to be added to the current group or page + // define a mask stream + var obj = this.pdf.internal.newStreamObject(); // define a mask state + var obj2 = this.pdf.internal.newObject2(); + obj2.push('<>'); // /S /Luminosity will need to define color space + obj2.push('>>'); // add mask to page resources + var gsName = 'MASK' + obj2.objId; + this.pdf.internal.addGraphicsState(gsName, obj2.objId); + var instruction = '/' + gsName + ' gs'; // add mask to page, group, or stream + lines.splice(0, 0, 'q'); + lines.splice(1, 0, instruction); + lines.push('Q'); + globalObj.outIntercept = obj; + break; + default: + var dictionaryEntry = '/' + this.pdf.internal.blendModeMap[this.ctx.globalCompositeOperation.toUpperCase()]; + if (dictionaryEntry) { + this.pdf.internal.out(dictionaryEntry + ' gs'); + } + break; + } + } + */ + + var alpha = this.ctx.globalAlpha; + + if (this.ctx._fillOpacity < 1) { + // TODO combine this with global opacity + alpha = this.ctx._fillOpacity; + } //TODO check for an opacity graphics state that was already created + //TODO do not set opacity if current value is already active + + /* + if (v2Support) { + var objOpac = this.pdf.internal.newObject2(); + objOpac.push('<>'); + var gsName = 'GS_O_' + objOpac.objId; + this.pdf.internal.addGraphicsState(gsName, objOpac.objId); + this.pdf.internal.out('/' + gsName + ' gs'); + } + */ + + + var xPath = this.path; + + for (var i = 0; i < xPath.length; i++) { + var pt = xPath[i]; + + switch (pt.type) { + case "begin": + moves.push({ + begin: true + }); + break; + + case "close": + moves.push({ + close: true + }); + break; + + case "mt": + moves.push({ + start: pt, + deltas: [], + abs: [] + }); + break; + + case "lt": + var delta = [pt.x - xPath[i - 1].x, pt.y - xPath[i - 1].y]; + var iii = moves.length; + + if (iii > 0) { + for (iii; iii > 0; iii--) { + if (moves[iii - 1].close !== true && moves[iii - 1].begin !== true) { + moves[iii - 1].deltas.push(delta); + moves[iii - 1].abs.push(pt); + break; + } + } + } + + break; + + case "bct": + var delta = [pt.x1 - xPath[i - 1].x, pt.y1 - xPath[i - 1].y, pt.x2 - xPath[i - 1].x, pt.y2 - xPath[i - 1].y, pt.x - xPath[i - 1].x, pt.y - xPath[i - 1].y]; + moves[moves.length - 1].deltas.push(delta); + break; + + case "qct": + // convert to bezier + var x1 = xPath[i - 1].x + 2.0 / 3.0 * (pt.x1 - xPath[i - 1].x); + var y1 = xPath[i - 1].y + 2.0 / 3.0 * (pt.y1 - xPath[i - 1].y); + var x2 = pt.x + 2.0 / 3.0 * (pt.x1 - pt.x); + var y2 = pt.y + 2.0 / 3.0 * (pt.y1 - pt.y); + var x3 = pt.x; + var y3 = pt.y; + var delta = [x1 - xPath[i - 1].x, y1 - xPath[i - 1].y, x2 - xPath[i - 1].x, y2 - xPath[i - 1].y, x3 - xPath[i - 1].x, y3 - xPath[i - 1].y]; + moves[moves.length - 1].deltas.push(delta); + break; + + case "arc": + moves.push({ + deltas: [], + abs: [] + }); + moves[moves.length - 1].arc = true; + + if (Array.isArray(moves[moves.length - 1].abs)) { + moves[moves.length - 1].abs.push(pt); + } + + break; + } + } + + var style; + + if (!isClip) { + if (isStroke) { + style = "S"; + } else { + style = "f"; + } + } else { + style = null; + } + + for (var i = 0; i < moves.length; i++) { + if (moves[i].begin) ; + + if (moves[i].arc) { + if (moves[i].start) { + this.internal.move2(this, moves[i].start.x, moves[i].start.y); + } + + var arcs = moves[i].abs; + + for (var ii = 0; ii < arcs.length; ii++) { + var arc = arcs[ii]; //TODO lines deltas were getting in here + + if (typeof arc.startAngle !== "undefined") { + var start = arc.startAngle * 360 / (2 * Math.PI); + var end = arc.endAngle * 360 / (2 * Math.PI); + var x = arc.x; + var y = arc.y; + this.internal.arc2(this, x, y, arc.radius, start, end, arc.counterclockwise, style, isClip); + } else { + this.internal.line2(c2d, arc.x, arc.y); + } + } + } + + if (!moves[i].arc) { + if (moves[i].close !== true && moves[i].begin !== true) { + var x = moves[i].start.x; + var y = moves[i].start.y; + this.pdf.lines(moves[i].deltas, x, y, null, null); + } + } + + if (moves[i].close) ; + } + + if (style) { + this.pdf.internal.out(style); + } + + if (isClip) { + this.pdf.clip(); + } + + globalObj.outIntercept = outInterceptOld; // if (this.ctx._clip_path.length > 0) { + // lines.push('Q'); + // } + }, + + /* + _pushMask: function () { + var v2Support = typeof this.pdf.internal.newObject2 === 'function'; + if (!v2Support) { + console.log('jsPDF v2 not enabled') + return; + } + // define a mask stream + var obj = this.pdf.internal.newStreamObject(); + // define a mask state + var obj2 = this.pdf.internal.newObject2(); + obj2.push('<>'); // /S /Luminosity will need to define color space + obj2.push('>>'); + // add mask to page resources + var gsName = 'MASK' + obj2.objId; + this.pdf.internal.addGraphicsState(gsName, obj2.objId); + var instruction = '/' + gsName + ' gs'; + this.pdf.internal.out(instruction); + }, + */ + _getBaseline: function _getBaseline(y) { + var height = parseInt(this.pdf.internal.getFontSize() / this.pdf.internal.scaleFactor); // TODO Get descent from font descriptor + + var descent = height * 0.25; + + switch (this.ctx.textBaseline) { + case "bottom": + return y - descent; + + case "top": + return y + height; + + case "hanging": + return y + height - descent; + + case "middle": + return y + height / 2 - descent; + + case "ideographic": + // TODO not implemented + return y; + + case "alphabetic": + default: + return y; + } + }, + createLinearGradient: function createLinearGradient() { + var canvasGradient = function canvasGradient() {}; + + canvasGradient.colorStops = []; + + canvasGradient.addColorStop = function (offset, color) { + this.colorStops.push([offset, color]); + }; + + canvasGradient.getColor = function () { + if (this.colorStops.length === 0) { + return "#000000"; + } + + return this.colorStops[0][1]; + }; + + canvasGradient.isCanvasGradient = true; + return canvasGradient; + }, + createPattern: function createPattern() { + return this.createLinearGradient(); + }, + createRadialGradient: function createRadialGradient() { + return this.createLinearGradient(); + } + }; + var c2d = jsPDFAPI.context2d; + /** + * Sets or returns the color, gradient, or pattern used to fill the drawing + * + * @name fillStyle + * @default #000000 + * @property {(color|gradient|pattern)} value The color of the drawing. Default value is #000000
    + * A gradient object (linear or radial) used to fill the drawing (not supported by context2d)
    + * A pattern object to use to fill the drawing (not supported by context2d) + */ + + Object.defineProperty(c2d, "fillStyle", { + set: function set(value) { + this._setFillStyle(value); + }, + get: function get() { + return this.ctx.fillStyle; + } + }); + /** + * Sets or returns the color, gradient, or pattern used for strokes + * + * @name strokeStyle + * @default #000000 + * @property {color} color A CSS color value that indicates the stroke color of the drawing. Default value is #000000 (not supported by context2d) + * @property {gradient} gradient A gradient object (linear or radial) used to create a gradient stroke (not supported by context2d) + * @property {pattern} pattern A pattern object used to create a pattern stroke (not supported by context2d) + */ + + Object.defineProperty(c2d, "strokeStyle", { + set: function set(value) { + this._setStrokeStyle(value); + }, + get: function get() { + return this.ctx.strokeStyle; + } + }); //Line Styles + + /** + * Sets or returns the style of the end caps for a line + * + * @name lineCap + * @default butt + * @property {(butt|round|square)} lineCap butt A flat edge is added to each end of the line
    + * round A rounded end cap is added to each end of the line
    + * square A square end cap is added to each end of the line
    + */ + + Object.defineProperty(c2d, "lineCap", { + set: function set(val) { + this._setLineCap(val); + }, + get: function get() { + return this.ctx.lineCap; + } + }); + /** + * Sets or returns the current line width + * + * @name lineWidth + * @default 1 + * @property {number} lineWidth The current line width, in pixels + */ + + Object.defineProperty(c2d, "lineWidth", { + set: function set(value) { + this._setLineWidth(value); + }, + get: function get() { + return this.ctx.lineWidth; + } + }); + /** + * Sets or returns the type of corner created, when two lines meet + */ + + Object.defineProperty(c2d, "lineJoin", { + set: function set(val) { + this._setLineJoin(val); + }, + get: function get() { + return this.ctx.lineJoin; + } + }); + /** + * Sets or returns the maximum miter length + */ + + Object.defineProperty(c2d, "miterLimit", { + set: function set(val) { + this.ctx.miterLimit = val; + }, + get: function get() { + return this.ctx.miterLimit; + } + }); + Object.defineProperty(c2d, "textBaseline", { + set: function set(value) { + this._setTextBaseline(value); + }, + get: function get() { + return this._getTextBaseline(); + } + }); + Object.defineProperty(c2d, "textAlign", { + set: function set(value) { + this._setTextAlign(value); + }, + get: function get() { + return this._getTextAlign(); + } + }); + Object.defineProperty(c2d, "font", { + set: function set(value) { + this._setFont(value); + }, + get: function get() { + return this.ctx.font; + } + }); + Object.defineProperty(c2d, "globalCompositeOperation", { + set: function set(value) { + this.ctx.globalCompositeOperation = value; + }, + get: function get() { + return this.ctx.globalCompositeOperation; + } + }); + Object.defineProperty(c2d, "globalAlpha", { + set: function set(value) { + this.ctx.globalAlpha = value; + }, + get: function get() { + return this.ctx.globalAlpha; + } + }); + Object.defineProperty(c2d, "canvas", { + get: function get() { + return { + parentNode: false, + style: false + }; + } + }); // Not HTML API + + Object.defineProperty(c2d, "ignoreClearRect", { + set: function set(value) { + this.ctx.ignoreClearRect = value; + }, + get: function get() { + return this.ctx.ignoreClearRect; + } + }); // End Not HTML API + + c2d.internal = {}; + c2d.internal.rxRgb = /rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/; + c2d.internal.rxRgba = /rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/; + c2d.internal.rxTransparent = /transparent|rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*0+\s*\)/; // http://hansmuller-flex.blogspot.com/2011/10/more-about-approximating-circular-arcs.html + + c2d.internal.arc = function (c2d, xc, yc, r, a1, a2, counterclockwise, style) { + var k = this.pdf.internal.scaleFactor; + var pageHeight = this.pdf.internal.pageSize.getHeight(); + var f2 = this.pdf.internal.f2; + var a1r = a1 * (Math.PI / 180); + var a2r = a2 * (Math.PI / 180); + var curves = this.createArc(r, a1r, a2r, counterclockwise); + + for (var i = 0; i < curves.length; i++) { + var curve = curves[i]; + + if (i === 0) { + this.pdf.internal.out([f2((curve.x1 + xc) * k), f2((pageHeight - (curve.y1 + yc)) * k), "m", f2((curve.x2 + xc) * k), f2((pageHeight - (curve.y2 + yc)) * k), f2((curve.x3 + xc) * k), f2((pageHeight - (curve.y3 + yc)) * k), f2((curve.x4 + xc) * k), f2((pageHeight - (curve.y4 + yc)) * k), "c"].join(" ")); + } else { + this.pdf.internal.out([f2((curve.x2 + xc) * k), f2((pageHeight - (curve.y2 + yc)) * k), f2((curve.x3 + xc) * k), f2((pageHeight - (curve.y3 + yc)) * k), f2((curve.x4 + xc) * k), f2((pageHeight - (curve.y4 + yc)) * k), "c"].join(" ")); + } //c2d._lastPoint = {x: curve.x1 + xc, y: curve.y1 + yc}; + + + c2d._lastPoint = { + x: xc, + y: yc + }; // f2((curve.x1 + xc) * k), f2((pageHeight - (curve.y1 + yc)) * k), 'm', f2((curve.x2 + xc) * k), f2((pageHeight - (curve.y2 + yc)) * k), f2((curve.x3 + xc) * k), f2((pageHeight - (curve.y3 + yc)) * k), f2((curve.x4 + xc) * k), f2((pageHeight - (curve.y4 + yc)) * k), 'c' + } + + if (style !== null) { + this.pdf.internal.out(this.pdf.internal.getStyle(style)); + } + }; + /** + * + * @param x Edge point X + * @param y Edge point Y + * @param r Radius + * @param a1 start angle + * @param a2 end angle + * @param counterclockwise + * @param style + * @param isClip + */ + + + c2d.internal.arc2 = function (c2d, x, y, r, a1, a2, counterclockwise, style, isClip) { + // we need to convert from cartesian to polar here methinks. + var centerX = x; // + r; + + var centerY = y; + + if (!isClip) { + this.arc(c2d, centerX, centerY, r, a1, a2, counterclockwise, style); + } else { + this.arc(c2d, centerX, centerY, r, a1, a2, counterclockwise, null); + this.pdf.clip(); + } + }; + + c2d.internal.move2 = function (c2d, x, y) { + var k = this.pdf.internal.scaleFactor; + var pageHeight = this.pdf.internal.pageSize.getHeight(); + var f2 = this.pdf.internal.f2; + this.pdf.internal.out([f2(x * k), f2((pageHeight - y) * k), "m"].join(" ")); + c2d._lastPoint = { + x: x, + y: y + }; + }; + + c2d.internal.line2 = function (c2d, dx, dy) { + var k = this.pdf.internal.scaleFactor; + var pageHeight = this.pdf.internal.pageSize.getHeight(); + var f2 = this.pdf.internal.f2; //var pt = {x: c2d._lastPoint.x + dx, y: c2d._lastPoint.y + dy}; + + var pt = { + x: dx, + y: dy + }; + this.pdf.internal.out([f2(pt.x * k), f2((pageHeight - pt.y) * k), "l"].join(" ")); //this.pdf.internal.out('f'); + + c2d._lastPoint = pt; + }; + /** + * Return a array of objects that represent bezier curves which approximate the circular arc centered at the origin, from startAngle to endAngle (radians) with the specified radius. + * + * Each bezier curve is an object with four points, where x1,y1 and x4,y4 are the arc's end points and x2,y2 and x3,y3 are the cubic bezier's control points. + */ + + + c2d.internal.createArc = function (radius, startAngle, endAngle, anticlockwise) { + var EPSILON = 0.00001; // Roughly 1/1000th of a degree, see below + // normalize startAngle, endAngle to [-2PI, 2PI] + + var twoPI = Math.PI * 2; + var startAngleN = startAngle; + + if (startAngleN < twoPI || startAngleN > twoPI) { + startAngleN = startAngleN % twoPI; + } + + var endAngleN = endAngle; + + if (endAngleN < twoPI || endAngleN > twoPI) { + endAngleN = endAngleN % twoPI; + } // Compute the sequence of arc curves, up to PI/2 at a time. + // Total arc angle is less than 2PI. + + + var curves = []; + var piOverTwo = Math.PI / 2.0; //var sgn = (startAngle < endAngle) ? +1 : -1; // clockwise or counterclockwise + + var sgn = anticlockwise ? -1 : +1; + var a1 = startAngle; + + for (var totalAngle = Math.min(twoPI, Math.abs(endAngleN - startAngleN)); totalAngle > EPSILON;) { + var a2 = a1 + sgn * Math.min(totalAngle, piOverTwo); + curves.push(this.createSmallArc(radius, a1, a2)); + totalAngle -= Math.abs(a2 - a1); + a1 = a2; + } + + return curves; + }; + + c2d.internal.getCurrentPage = function () { + return this.pdf.internal.pages[this.pdf.internal.getCurrentPageInfo().pageNumber]; + }; + /** + * Cubic bezier approximation of a circular arc centered at the origin, from (radians) a1 to a2, where a2-a1 < pi/2. The arc's radius is r. + * + * Returns an object with four points, where x1,y1 and x4,y4 are the arc's end points and x2,y2 and x3,y3 are the cubic bezier's control points. + * + * This algorithm is based on the approach described in: A. Riškus, "Approximation of a Cubic Bezier Curve by Circular Arcs and Vice Versa," Information Technology and Control, 35(4), 2006 pp. 371-378. + */ + + + c2d.internal.createSmallArc = function (r, a1, a2) { + // Compute all four points for an arc that subtends the same total angle + // but is centered on the X-axis + var a = (a2 - a1) / 2.0; + var x4 = r * Math.cos(a); + var y4 = r * Math.sin(a); + var x1 = x4; + var y1 = -y4; + var q1 = x1 * x1 + y1 * y1; + var q2 = q1 + x1 * x4 + y1 * y4; + var k2 = 4 / 3 * (Math.sqrt(2 * q1 * q2) - q2) / (x1 * y4 - y1 * x4); + var x2 = x1 - k2 * y1; + var y2 = y1 + k2 * x1; + var x3 = x2; + var y3 = -y2; // Find the arc points' actual locations by computing x1,y1 and x4,y4 + // and rotating the control points by a + a1 + + var ar = a + a1; + var cos_ar = Math.cos(ar); + var sin_ar = Math.sin(ar); + return { + x1: r * Math.cos(a1), + y1: r * Math.sin(a1), + x2: x2 * cos_ar - y2 * sin_ar, + y2: x2 * sin_ar + y2 * cos_ar, + x3: x3 * cos_ar - y3 * sin_ar, + y3: x3 * sin_ar + y3 * cos_ar, + x4: r * Math.cos(a2), + y4: r * Math.sin(a2) + }; + }; + /** + * + * @function + * @constructor + */ + + + function context() { + this._isStrokeTransparent = false; + this._strokeOpacity = 1; + this.strokeStyle = "#000000"; + this.fillStyle = "#000000"; + this._isFillTransparent = false; + this._fillOpacity = 1; + this.font = "12pt times"; + this.textBaseline = "alphabetic"; // top,bottom,middle,ideographic,alphabetic,hanging + + this.textAlign = "left"; + this.lineWidth = 1; + this.lineJoin = "miter"; // round, bevel, miter + + this.lineCap = "butt"; // butt, round, square + + this._transform = [1, 0, 0, 1, 0, 0]; // sx, shy, shx, sy, tx, ty + + this.globalCompositeOperation = "normal"; + this.globalAlpha = 1.0; + this._clip_path = []; + this.currentPoint = { + x: 0, + y: 0 + }; // TODO miter limit //default 10 + // Not HTML API + + this.ignoreClearRect = false; + + this.copy = function (ctx) { + this._isStrokeTransparent = ctx._isStrokeTransparent; + this._strokeOpacity = ctx._strokeOpacity; + this.strokeStyle = ctx.strokeStyle; + this._isFillTransparent = ctx._isFillTransparent; + this._fillOpacity = ctx._fillOpacity; + this.fillStyle = ctx.fillStyle; + this.font = ctx.font; + this.lineWidth = ctx.lineWidth; + this.lineJoin = ctx.lineJoin; + this.lineCap = ctx.lineCap; + this.textBaseline = ctx.textBaseline; + this.textAlign = ctx.textAlign; + this._fontSize = ctx._fontSize; + this._transform = ctx._transform.slice(0); + this.globalCompositeOperation = ctx.globalCompositeOperation; + this.globalAlpha = ctx.globalAlpha; + this._clip_path = ctx._clip_path.slice(0); //TODO deep copy? + + this.currentPoint = ctx.currentPoint; // Not HTML API + + this.ignoreClearRect = ctx.ignoreClearRect; + }; + } + + return this; + })(jsPDF.API, typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")()); + + /** + * Copyright (c) 2018 Erik Koopmans + * Released under the MIT License. + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF html PlugIn + * + * @name html + * @module + */ + (function (jsPDFAPI, global) { + /** + * Determine the type of a variable/object. + * + * @private + * @ignore + */ + + var objType = function objType(obj) { + var type = _typeof(obj); + + if (type === "undefined") return "undefined";else if (type === "string" || obj instanceof String) return "string";else if (type === "number" || obj instanceof Number) return "number";else if (type === "function" || obj instanceof Function) return "function";else if (!!obj && obj.constructor === Array) return "array";else if (obj && obj.nodeType === 1) return "element";else if (type === "object") return "object";else return "unknown"; + }; + /** + * Create an HTML element with optional className, innerHTML, and style. + * + * @private + * @ignore + */ + + + var createElement = function createElement(tagName, opt) { + var el = document.createElement(tagName); + if (opt.className) el.className = opt.className; + + if (opt.innerHTML) { + el.innerHTML = opt.innerHTML; + var scripts = el.getElementsByTagName("script"); + + for (var i = scripts.length; i-- > 0; null) { + scripts[i].parentNode.removeChild(scripts[i]); + } + } + + for (var key in opt.style) { + el.style[key] = opt.style[key]; + } + + return el; + }; + /** + * Deep-clone a node and preserve contents/properties. + * + * @private + * @ignore + */ + + + var cloneNode = function cloneNode(node, javascriptEnabled) { + // Recursively clone the node. + var clone = node.nodeType === 3 ? document.createTextNode(node.nodeValue) : node.cloneNode(false); + + for (var child = node.firstChild; child; child = child.nextSibling) { + if (javascriptEnabled === true || child.nodeType !== 1 || child.nodeName !== "SCRIPT") { + clone.appendChild(cloneNode(child, javascriptEnabled)); + } + } + + if (node.nodeType === 1) { + // Preserve contents/properties of special nodes. + if (node.nodeName === "CANVAS") { + clone.width = node.width; + clone.height = node.height; + clone.getContext("2d").drawImage(node, 0, 0); + } else if (node.nodeName === "TEXTAREA" || node.nodeName === "SELECT") { + clone.value = node.value; + } // Preserve the node's scroll position when it loads. + + + clone.addEventListener("load", function () { + clone.scrollTop = node.scrollTop; + clone.scrollLeft = node.scrollLeft; + }, true); + } // Return the cloned node. + + + return clone; + }; + /* ----- CONSTRUCTOR ----- */ + + + var Worker = function Worker(opt) { + // Create the root parent for the proto chain, and the starting Worker. + var root = Object.assign(Worker.convert(Promise.resolve()), JSON.parse(JSON.stringify(Worker.template))); + var self = Worker.convert(Promise.resolve(), root); // Set progress, optional settings, and return. + + self = self.setProgress(1, Worker, 1, [Worker]); + self = self.set(opt); + return self; + }; // Boilerplate for subclassing Promise. + + + Worker.prototype = Object.create(Promise.prototype); + Worker.prototype.constructor = Worker; // Converts/casts promises into Workers. + + Worker.convert = function convert(promise, inherit) { + // Uses prototypal inheritance to receive changes made to ancestors' properties. + promise.__proto__ = inherit || Worker.prototype; + return promise; + }; + + Worker.template = { + prop: { + src: null, + container: null, + overlay: null, + canvas: null, + img: null, + pdf: null, + pageSize: null, + callback: function callback() {} + }, + progress: { + val: 0, + state: null, + n: 0, + stack: [] + }, + opt: { + filename: "file.pdf", + margin: [0, 0, 0, 0], + enableLinks: true, + html2canvas: {}, + jsPDF: {} + } + }; + /* ----- FROM / TO ----- */ + + Worker.prototype.from = function from(src, type) { + function getType(src) { + switch (objType(src)) { + case "string": + return "string"; + + case "element": + return src.nodeName.toLowerCase === "canvas" ? "canvas" : "element"; + + default: + return "unknown"; + } + } + + return this.then(function from_main() { + type = type || getType(src); + + switch (type) { + case "string": + return this.set({ + src: createElement("div", { + innerHTML: src + }) + }); + + case "element": + return this.set({ + src: src + }); + + case "canvas": + return this.set({ + canvas: src + }); + + case "img": + return this.set({ + img: src + }); + + default: + return this.error("Unknown source type."); + } + }); + }; + + Worker.prototype.to = function to(target) { + // Route the 'to' request to the appropriate method. + switch (target) { + case "container": + return this.toContainer(); + + case "canvas": + return this.toCanvas(); + + case "img": + return this.toImg(); + + case "pdf": + return this.toPdf(); + + default: + return this.error("Invalid target."); + } + }; + + Worker.prototype.toContainer = function toContainer() { + // Set up function prerequisites. + var prereqs = [function checkSrc() { + return this.prop.src || this.error("Cannot duplicate - no source HTML."); + }, function checkPageSize() { + return this.prop.pageSize || this.setPageSize(); + }]; + return this.thenList(prereqs).then(function toContainer_main() { + // Define the CSS styles for the container and its overlay parent. + var overlayCSS = { + position: "fixed", + overflow: "hidden", + zIndex: 1000, + left: "-100000px", + right: 0, + bottom: 0, + top: 0 + }; + var containerCSS = { + position: "relative", + display: "inline-block", + width: Math.max(this.prop.src.clientWidth, this.prop.src.scrollWidth, this.prop.src.offsetWidth) + "px", + left: 0, + right: 0, + top: 0, + margin: "auto", + backgroundColor: "white" + }; // Set the overlay to hidden (could be changed in the future to provide a print preview). + + var source = cloneNode(this.prop.src, this.opt.html2canvas.javascriptEnabled); + + if (source.tagName === "BODY") { + containerCSS.height = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight) + "px"; + } + + this.prop.overlay = createElement("div", { + className: "html2pdf__overlay", + style: overlayCSS + }); + this.prop.container = createElement("div", { + className: "html2pdf__container", + style: containerCSS + }); + this.prop.container.appendChild(source); + this.prop.container.firstChild.appendChild(createElement("div", { + style: { + clear: "both", + border: "0 none transparent", + margin: 0, + padding: 0, + height: 0 + } + })); + this.prop.container.style.float = "none"; + this.prop.overlay.appendChild(this.prop.container); + document.body.appendChild(this.prop.overlay); + this.prop.container.firstChild.style.position = "relative"; + this.prop.container.height = Math.max(this.prop.container.firstChild.clientHeight, this.prop.container.firstChild.scrollHeight, this.prop.container.firstChild.offsetHeight) + "px"; + }); + }; + + Worker.prototype.toCanvas = function toCanvas() { + // Set up function prerequisites. + var prereqs = [function checkContainer() { + return document.body.contains(this.prop.container) || this.toContainer(); + }]; // Fulfill prereqs then create the canvas. + + return this.thenList(prereqs).then(function toCanvas_main() { + // Handle old-fashioned 'onrendered' argument. + var options = Object.assign({}, this.opt.html2canvas); + delete options.onrendered; + + if (!this.isHtml2CanvasLoaded()) { + return; + } + + return html2canvas(this.prop.container, options); + }).then(function toCanvas_post(canvas) { + // Handle old-fashioned 'onrendered' argument. + var onRendered = this.opt.html2canvas.onrendered || function () {}; + + onRendered(canvas); + this.prop.canvas = canvas; + document.body.removeChild(this.prop.overlay); + }); + }; + + Worker.prototype.toContext2d = function toContext2d() { + // Set up function prerequisites. + var prereqs = [function checkContainer() { + return document.body.contains(this.prop.container) || this.toContainer(); + }]; // Fulfill prereqs then create the canvas. + + return this.thenList(prereqs).then(function toContext2d_main() { + // Handle old-fashioned 'onrendered' argument. + var pdf = this.opt.jsPDF; + var options = Object.assign({ + async: true, + allowTaint: true, + backgroundColor: "#ffffff", + imageTimeout: 15000, + logging: true, + proxy: null, + removeContainer: true, + foreignObjectRendering: false, + useCORS: false + }, this.opt.html2canvas); + delete options.onrendered; + options.windowHeight = options.windowHeight || 0; + options.windowHeight = options.windowHeight == 0 ? Math.max(this.prop.container.clientHeight, this.prop.container.scrollHeight, this.prop.container.offsetHeight) : options.windowHeight; + + if (!this.isHtml2CanvasLoaded()) { + return; + } + + return html2canvas(this.prop.container, options); + }).then(function toContext2d_post(canvas) { + // Handle old-fashioned 'onrendered' argument. + var onRendered = this.opt.html2canvas.onrendered || function () {}; + + onRendered(canvas); + this.prop.canvas = canvas; + document.body.removeChild(this.prop.overlay); + }); + }; + + Worker.prototype.toImg = function toImg() { + // Set up function prerequisites. + var prereqs = [function checkCanvas() { + return this.prop.canvas || this.toCanvas(); + }]; // Fulfill prereqs then create the image. + + return this.thenList(prereqs).then(function toImg_main() { + var imgData = this.prop.canvas.toDataURL("image/" + this.opt.image.type, this.opt.image.quality); + this.prop.img = document.createElement("img"); + this.prop.img.src = imgData; + }); + }; + + Worker.prototype.toPdf = function toPdf() { + // Set up function prerequisites. + var prereqs = [function checkContext2d() { + return this.toContext2d(); + } //function checkCanvas() { return this.prop.canvas || this.toCanvas(); } + ]; // Fulfill prereqs then create the image. + + return this.thenList(prereqs).then(function toPdf_main() { + // Create local copies of frequently used properties. + this.prop.pdf = this.prop.pdf || this.opt.jsPDF; + }); + }; + /* ----- OUTPUT / SAVE ----- */ + + + Worker.prototype.output = function output(type, options, src) { + // Redirect requests to the correct function (outputPdf / outputImg). + src = src || "pdf"; + + if (src.toLowerCase() === "img" || src.toLowerCase() === "image") { + return this.outputImg(type, options); + } else { + return this.outputPdf(type, options); + } + }; + + Worker.prototype.outputPdf = function outputPdf(type, options) { + // Set up function prerequisites. + var prereqs = [function checkPdf() { + return this.prop.pdf || this.toPdf(); + }]; // Fulfill prereqs then perform the appropriate output. + + return this.thenList(prereqs).then(function outputPdf_main() { + /* Currently implemented output types: + * https://rawgit.com/MrRio/jsPDF/master/docs/jspdf.js.html#line992 + * save(options), arraybuffer, blob, bloburi/bloburl, + * datauristring/dataurlstring, dataurlnewwindow, datauri/dataurl + */ + return this.prop.pdf.output(type, options); + }); + }; + + Worker.prototype.outputImg = function outputImg(type, options) { + // Set up function prerequisites. + var prereqs = [function checkImg() { + return this.prop.img || this.toImg(); + }]; // Fulfill prereqs then perform the appropriate output. + + return this.thenList(prereqs).then(function outputImg_main() { + switch (type) { + case undefined: + case "img": + return this.prop.img; + + case "datauristring": + case "dataurlstring": + return this.prop.img.src; + + case "datauri": + case "dataurl": + return document.location.href = this.prop.img.src; + + default: + throw 'Image output type "' + type + '" is not supported.'; + } + }); + }; + + Worker.prototype.isHtml2CanvasLoaded = function () { + var result = typeof global.html2canvas !== "undefined"; + + if (!result) { + console.error("html2canvas not loaded."); + } + + return result; + }; + + Worker.prototype.save = function save(filename) { + // Set up function prerequisites. + var prereqs = [function checkPdf() { + return this.prop.pdf || this.toPdf(); + }]; + + if (!this.isHtml2CanvasLoaded()) { + return; + } // Fulfill prereqs, update the filename (if provided), and save the PDF. + + + return this.thenList(prereqs).set(filename ? { + filename: filename + } : null).then(function save_main() { + this.prop.pdf.save(this.opt.filename); + }); + }; + + Worker.prototype.doCallback = function doCallback(filename) { + // Set up function prerequisites. + var prereqs = [function checkPdf() { + return this.prop.pdf || this.toPdf(); + }]; + + if (!this.isHtml2CanvasLoaded()) { + return; + } // Fulfill prereqs, update the filename (if provided), and save the PDF. + + + return this.thenList(prereqs).then(function doCallback_main() { + this.prop.callback(this.prop.pdf); + }); + }; + /* ----- SET / GET ----- */ + + + Worker.prototype.set = function set(opt) { + // TODO: Implement ordered pairs? + // Silently ignore invalid or empty input. + if (objType(opt) !== "object") { + return this; + } // Build an array of setter functions to queue. + + + var fns = Object.keys(opt || {}).map(function (key) { + if (key in Worker.template.prop) { + // Set pre-defined properties. + return function set_prop() { + this.prop[key] = opt[key]; + }; + } else { + switch (key) { + case "margin": + return this.setMargin.bind(this, opt.margin); + + case "jsPDF": + return function set_jsPDF() { + this.opt.jsPDF = opt.jsPDF; + return this.setPageSize(); + }; + + case "pageSize": + return this.setPageSize.bind(this, opt.pageSize); + + default: + // Set any other properties in opt. + return function set_opt() { + this.opt[key] = opt[key]; + }; + } + } + }, this); // Set properties within the promise chain. + + return this.then(function set_main() { + return this.thenList(fns); + }); + }; + + Worker.prototype.get = function get(key, cbk) { + return this.then(function get_main() { + // Fetch the requested property, either as a predefined prop or in opt. + var val = key in Worker.template.prop ? this.prop[key] : this.opt[key]; + return cbk ? cbk(val) : val; + }); + }; + + Worker.prototype.setMargin = function setMargin(margin) { + return this.then(function setMargin_main() { + // Parse the margin property. + switch (objType(margin)) { + case "number": + margin = [margin, margin, margin, margin]; + + case "array": + if (margin.length === 2) { + margin = [margin[0], margin[1], margin[0], margin[1]]; + } + + if (margin.length === 4) { + break; + } + + default: + return this.error("Invalid margin array."); + } // Set the margin property, then update pageSize. + + + this.opt.margin = margin; + }).then(this.setPageSize); + }; + + Worker.prototype.setPageSize = function setPageSize(pageSize) { + function toPx(val, k) { + return Math.floor(val * k / 72 * 96); + } + + return this.then(function setPageSize_main() { + // Retrieve page-size based on jsPDF settings, if not explicitly provided. + pageSize = pageSize || jsPDF.getPageSize(this.opt.jsPDF); // Add 'inner' field if not present. + + if (!pageSize.hasOwnProperty("inner")) { + pageSize.inner = { + width: pageSize.width - this.opt.margin[1] - this.opt.margin[3], + height: pageSize.height - this.opt.margin[0] - this.opt.margin[2] + }; + pageSize.inner.px = { + width: toPx(pageSize.inner.width, pageSize.k), + height: toPx(pageSize.inner.height, pageSize.k) + }; + pageSize.inner.ratio = pageSize.inner.height / pageSize.inner.width; + } // Attach pageSize to this. + + + this.prop.pageSize = pageSize; + }); + }; + + Worker.prototype.setProgress = function setProgress(val, state, n, stack) { + // Immediately update all progress values. + if (val != null) this.progress.val = val; + if (state != null) this.progress.state = state; + if (n != null) this.progress.n = n; + if (stack != null) this.progress.stack = stack; + this.progress.ratio = this.progress.val / this.progress.state; // Return this for command chaining. + + return this; + }; + + Worker.prototype.updateProgress = function updateProgress(val, state, n, stack) { + // Immediately update all progress values, using setProgress. + return this.setProgress(val ? this.progress.val + val : null, state ? state : null, n ? this.progress.n + n : null, stack ? this.progress.stack.concat(stack) : null); + }; + /* ----- PROMISE MAPPING ----- */ + + + Worker.prototype.then = function then(onFulfilled, onRejected) { + // Wrap `this` for encapsulation. + var self = this; + return this.thenCore(onFulfilled, onRejected, function then_main(onFulfilled, onRejected) { + // Update progress while queuing, calling, and resolving `then`. + self.updateProgress(null, null, 1, [onFulfilled]); + return Promise.prototype.then.call(this, function then_pre(val) { + self.updateProgress(null, onFulfilled); + return val; + }).then(onFulfilled, onRejected).then(function then_post(val) { + self.updateProgress(1); + return val; + }); + }); + }; + + Worker.prototype.thenCore = function thenCore(onFulfilled, onRejected, thenBase) { + // Handle optional thenBase parameter. + thenBase = thenBase || Promise.prototype.then; // Wrap `this` for encapsulation and bind it to the promise handlers. + + var self = this; + + if (onFulfilled) { + onFulfilled = onFulfilled.bind(self); + } + + if (onRejected) { + onRejected = onRejected.bind(self); + } // Cast self into a Promise to avoid polyfills recursively defining `then`. + + + var isNative = Promise.toString().indexOf("[native code]") !== -1 && Promise.name === "Promise"; + var selfPromise = isNative ? self : Worker.convert(Object.assign({}, self), Promise.prototype); // Return the promise, after casting it into a Worker and preserving props. + + var returnVal = thenBase.call(selfPromise, onFulfilled, onRejected); + return Worker.convert(returnVal, self.__proto__); + }; + + Worker.prototype.thenExternal = function thenExternal(onFulfilled, onRejected) { + // Call `then` and return a standard promise (exits the Worker chain). + return Promise.prototype.then.call(this, onFulfilled, onRejected); + }; + + Worker.prototype.thenList = function thenList(fns) { + // Queue a series of promise 'factories' into the promise chain. + var self = this; + fns.forEach(function thenList_forEach(fn) { + self = self.thenCore(fn); + }); + return self; + }; + + Worker.prototype["catch"] = function (onRejected) { + // Bind `this` to the promise handler, call `catch`, and return a Worker. + if (onRejected) { + onRejected = onRejected.bind(this); + } + + var returnVal = Promise.prototype["catch"].call(this, onRejected); + return Worker.convert(returnVal, this); + }; + + Worker.prototype.catchExternal = function catchExternal(onRejected) { + // Call `catch` and return a standard promise (exits the Worker chain). + return Promise.prototype["catch"].call(this, onRejected); + }; + + Worker.prototype.error = function error(msg) { + // Throw the error in the Promise chain. + return this.then(function error_main() { + throw new Error(msg); + }); + }; + /* ----- ALIASES ----- */ + + + Worker.prototype.using = Worker.prototype.set; + Worker.prototype.saveAs = Worker.prototype.save; + Worker.prototype.export = Worker.prototype.output; + Worker.prototype.run = Worker.prototype.then; // Get dimensions of a PDF page, as determined by jsPDF. + + jsPDF.getPageSize = function (orientation, unit, format) { + // Decode options object + if (_typeof(orientation) === "object") { + var options = orientation; + orientation = options.orientation; + unit = options.unit || unit; + format = options.format || format; + } // Default options + + + unit = unit || "mm"; + format = format || "a4"; + orientation = ("" + (orientation || "P")).toLowerCase(); + var format_as_string = ("" + format).toLowerCase(); // Size in pt of various paper formats + + var pageFormats = { + a0: [2383.94, 3370.39], + a1: [1683.78, 2383.94], + a2: [1190.55, 1683.78], + a3: [841.89, 1190.55], + a4: [595.28, 841.89], + a5: [419.53, 595.28], + a6: [297.64, 419.53], + a7: [209.76, 297.64], + a8: [147.4, 209.76], + a9: [104.88, 147.4], + a10: [73.7, 104.88], + b0: [2834.65, 4008.19], + b1: [2004.09, 2834.65], + b2: [1417.32, 2004.09], + b3: [1000.63, 1417.32], + b4: [708.66, 1000.63], + b5: [498.9, 708.66], + b6: [354.33, 498.9], + b7: [249.45, 354.33], + b8: [175.75, 249.45], + b9: [124.72, 175.75], + b10: [87.87, 124.72], + c0: [2599.37, 3676.54], + c1: [1836.85, 2599.37], + c2: [1298.27, 1836.85], + c3: [918.43, 1298.27], + c4: [649.13, 918.43], + c5: [459.21, 649.13], + c6: [323.15, 459.21], + c7: [229.61, 323.15], + c8: [161.57, 229.61], + c9: [113.39, 161.57], + c10: [79.37, 113.39], + dl: [311.81, 623.62], + letter: [612, 792], + "government-letter": [576, 756], + legal: [612, 1008], + "junior-legal": [576, 360], + ledger: [1224, 792], + tabloid: [792, 1224], + "credit-card": [153, 243] + }; // Unit conversion + + switch (unit) { + case "pt": + var k = 1; + break; + + case "mm": + var k = 72 / 25.4; + break; + + case "cm": + var k = 72 / 2.54; + break; + + case "in": + var k = 72; + break; + + case "px": + var k = 72 / 96; + break; + + case "pc": + var k = 12; + break; + + case "em": + var k = 12; + break; + + case "ex": + var k = 6; + break; + + default: + throw "Invalid unit: " + unit; + } // Dimensions are stored as user units and converted to points on output + + + if (pageFormats.hasOwnProperty(format_as_string)) { + var pageHeight = pageFormats[format_as_string][1] / k; + var pageWidth = pageFormats[format_as_string][0] / k; + } else { + try { + var pageHeight = format[1]; + var pageWidth = format[0]; + } catch (err) { + throw new Error("Invalid format: " + format); + } + } // Handle page orientation + + + if (orientation === "p" || orientation === "portrait") { + orientation = "p"; + + if (pageWidth > pageHeight) { + var tmp = pageWidth; + pageWidth = pageHeight; + pageHeight = tmp; + } + } else if (orientation === "l" || orientation === "landscape") { + orientation = "l"; + + if (pageHeight > pageWidth) { + var tmp = pageWidth; + pageWidth = pageHeight; + pageHeight = tmp; + } + } else { + throw "Invalid orientation: " + orientation; + } // Return information (k is the unit conversion ratio from pts) + + + var info = { + width: pageWidth, + height: pageHeight, + unit: unit, + k: k + }; + return info; + }; + /** + * Generate a PDF from an HTML element or string using. + * + * @name html + * @function + * @param {Element|string} source The source element or HTML string. + * @param {Object=} options An object of optional settings. + * @description The Plugin needs html2canvas from niklasvh + */ + + + jsPDFAPI.html = function (src, options) { + + options = options || {}; + + options.callback = options.callback || function () {}; + + options.html2canvas = options.html2canvas || {}; + options.html2canvas.canvas = options.html2canvas.canvas || this.canvas; + options.jsPDF = options.jsPDF || this; // Create a new worker with the given options. + + var pdf = options.jsPDF; + pdf.annotations = { + _nameMap: [], + createAnnotation: function createAnnotation(href, bounds) { + var x = pdf.context2d._wrapX(bounds.left); + + var y = pdf.context2d._wrapY(bounds.top); + + var page = pdf.context2d._page(bounds.top); + + var options; + var index = href.indexOf("#"); + + if (index >= 0) { + options = { + name: href.substring(index + 1) + }; + } else { + options = { + url: href + }; + } + + pdf.link(x, y, bounds.right - bounds.left, bounds.bottom - bounds.top, options); + }, + setName: function setName(name, bounds) { + var x = pdf.context2d._wrapX(bounds.left); + + var y = pdf.context2d._wrapY(bounds.top); + + var page = pdf.context2d._page(bounds.top); + + this._nameMap[name] = { + page: page, + x: x, + y: y + }; + } + }; + + pdf.context2d._pageBreakAt = function (y) { + this.pageBreaks.push(y); + }; + + pdf.context2d._gotoPage = function (pageOneBased) { + while (pdf.internal.getNumberOfPages() < pageOneBased) { + pdf.addPage(); + } + + pdf.setPage(pageOneBased); + }; + + pdf.context2d.pageWrapYEnabled = true; + pdf.context2d.pageWrapY = pdf.internal.pageSize.getHeight() / pdf.internal.scaleFactor + 1; + pdf.canvas.autoContext2dResizeY = false; + var worker = new Worker(options); + + if (!options.worker) { + // If worker is not set to true, perform the traditional 'simple' operation. + return worker.from(src).doCallback(); + } else { + // Otherwise, return the worker for new Promise-based operation. + return worker; + } + + return this; + }; + })(jsPDF.API, typeof window !== "undefined" && window || typeof global !== "undefined" && global); + + /** + * @license + * ==================================================================== + * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com + * + * + * ==================================================================== + */ + + /*global jsPDF */ + + /** + * jsPDF JavaScript plugin + * + * @name javascript + * @module + */ + (function (jsPDFAPI) { + + var jsNamesObj, jsJsObj, text; + /** + * @name addJS + * @function + * @param {string} javascript The javascript to be embedded into the PDF-file. + * @returns {jsPDF} + */ + + jsPDFAPI.addJS = function (javascript) { + text = javascript; + this.internal.events.subscribe("postPutResources", function (javascript) { + jsNamesObj = this.internal.newObject(); + this.internal.out("<<"); + this.internal.out("/Names [(EmbeddedJS) " + (jsNamesObj + 1) + " 0 R]"); + this.internal.out(">>"); + this.internal.out("endobj"); + jsJsObj = this.internal.newObject(); + this.internal.out("<<"); + this.internal.out("/S /JavaScript"); + this.internal.out("/JS (" + text + ")"); + this.internal.out(">>"); + this.internal.out("endobj"); + }); + this.internal.events.subscribe("putCatalog", function () { + if (jsNamesObj !== undefined && jsJsObj !== undefined) { + this.internal.out("/Names <>"); + } + }); + return this; + }; + })(jsPDF.API); + + /** + * @license + * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF Outline PlugIn + * + * Generates a PDF Outline + * @name outline + * @module + */ + (function (jsPDFAPI) { + + jsPDFAPI.events.push(["postPutResources", function () { + var pdf = this; + var rx = /^(\d+) 0 obj$/; // Write action goto objects for each page + // this.outline.destsGoto = []; + // for (var i = 0; i < totalPages; i++) { + // var id = pdf.internal.newObject(); + // this.outline.destsGoto.push(id); + // pdf.internal.write("<> endobj"); + // } + // + // for (var i = 0; i < dests.length; i++) { + // pdf.internal.write("(page_" + (i + 1) + ")" + dests[i] + " 0 + // R"); + // } + // + + if (this.outline.root.children.length > 0) { + var lines = pdf.outline.render().split(/\r\n/); + + for (var i = 0; i < lines.length; i++) { + var line = lines[i]; + var m = rx.exec(line); + + if (m != null) { + var oid = m[1]; + pdf.internal.newObjectDeferredBegin(oid); + } + + pdf.internal.write(line); + } + } // This code will write named destination for each page reference + // (page_1, etc) + + + if (this.outline.createNamedDestinations) { + var totalPages = this.internal.pages.length; // WARNING: this assumes jsPDF starts on page 3 and pageIDs + // follow 5, 7, 9, etc + // Write destination objects for each page + + var dests = []; + + for (var i = 0; i < totalPages; i++) { + var id = pdf.internal.newObject(); + dests.push(id); + var info = pdf.internal.getPageInfo(i + 1); + pdf.internal.write("<< /D[" + info.objId + " 0 R /XYZ null null null]>> endobj"); + } // assign a name for each destination + + + var names2Oid = pdf.internal.newObject(); + pdf.internal.write("<< /Names [ "); + + for (var i = 0; i < dests.length; i++) { + pdf.internal.write("(page_" + (i + 1) + ")" + dests[i] + " 0 R"); + } + + pdf.internal.write(" ] >>", "endobj"); // var kids = pdf.internal.newObject(); + // pdf.internal.write('<< /Kids [ ' + names2Oid + ' 0 R'); + // pdf.internal.write(' ] >>', 'endobj'); + + var namesOid = pdf.internal.newObject(); + pdf.internal.write("<< /Dests " + names2Oid + " 0 R"); + pdf.internal.write(">>", "endobj"); + } + }]); + jsPDFAPI.events.push(["putCatalog", function () { + var pdf = this; + + if (pdf.outline.root.children.length > 0) { + pdf.internal.write("/Outlines", this.outline.makeRef(this.outline.root)); + + if (this.outline.createNamedDestinations) { + pdf.internal.write("/Names " + namesOid + " 0 R"); + } // Open with Bookmarks showing + // pdf.internal.write("/PageMode /UseOutlines"); + + } + }]); + jsPDFAPI.events.push(["initialized", function () { + var pdf = this; + pdf.outline = { + createNamedDestinations: false, + root: { + children: [] + } + }; + /** + * Options: pageNumber + */ + + pdf.outline.add = function (parent, title, options) { + var item = { + title: title, + options: options, + children: [] + }; + + if (parent == null) { + parent = this.root; + } + + parent.children.push(item); + return item; + }; + + pdf.outline.render = function () { + this.ctx = {}; + this.ctx.val = ""; + this.ctx.pdf = pdf; + this.genIds_r(this.root); + this.renderRoot(this.root); + this.renderItems(this.root); + return this.ctx.val; + }; + + pdf.outline.genIds_r = function (node) { + node.id = pdf.internal.newObjectDeferred(); + + for (var i = 0; i < node.children.length; i++) { + this.genIds_r(node.children[i]); + } + }; + + pdf.outline.renderRoot = function (node) { + this.objStart(node); + this.line("/Type /Outlines"); + + if (node.children.length > 0) { + this.line("/First " + this.makeRef(node.children[0])); + this.line("/Last " + this.makeRef(node.children[node.children.length - 1])); + } + + this.line("/Count " + this.count_r({ + count: 0 + }, node)); + this.objEnd(); + }; + + pdf.outline.renderItems = function (node) { + for (var i = 0; i < node.children.length; i++) { + var item = node.children[i]; + this.objStart(item); + this.line("/Title " + this.makeString(item.title)); + this.line("/Parent " + this.makeRef(node)); + + if (i > 0) { + this.line("/Prev " + this.makeRef(node.children[i - 1])); + } + + if (i < node.children.length - 1) { + this.line("/Next " + this.makeRef(node.children[i + 1])); + } + + if (item.children.length > 0) { + this.line("/First " + this.makeRef(item.children[0])); + this.line("/Last " + this.makeRef(item.children[item.children.length - 1])); + } + + var count = this.count = this.count_r({ + count: 0 + }, item); + + if (count > 0) { + this.line("/Count " + count); + } + + if (item.options) { + if (item.options.pageNumber) { + // Explicit Destination + //WARNING this assumes page ids are 3,5,7, etc. + var info = pdf.internal.getPageInfo(item.options.pageNumber); + this.line("/Dest " + "[" + info.objId + " 0 R /XYZ 0 " + this.ctx.pdf.internal.pageSize.getHeight() * this.ctx.pdf.internal.scaleFactor + " 0]"); // this line does not work on all clients (pageNumber instead of page ref) + //this.line('/Dest ' + '[' + (item.options.pageNumber - 1) + ' /XYZ 0 ' + this.ctx.pdf.internal.pageSize.getHeight() + ' 0]'); + // Named Destination + // this.line('/Dest (page_' + (item.options.pageNumber) + ')'); + // Action Destination + // var id = pdf.internal.newObject(); + // pdf.internal.write('<> endobj'); + // this.line('/A ' + id + ' 0 R' ); + } + } + + this.objEnd(); + } + + for (var i = 0; i < node.children.length; i++) { + var item = node.children[i]; + this.renderItems(item); + } + }; + + pdf.outline.line = function (text) { + this.ctx.val += text + "\r\n"; + }; + + pdf.outline.makeRef = function (node) { + return node.id + " 0 R"; + }; + + pdf.outline.makeString = function (val) { + return "(" + pdf.internal.pdfEscape(val) + ")"; + }; + + pdf.outline.objStart = function (node) { + this.ctx.val += "\r\n" + node.id + " 0 obj" + "\r\n<<\r\n"; + }; + + pdf.outline.objEnd = function (node) { + this.ctx.val += ">> \r\n" + "endobj" + "\r\n"; + }; + + pdf.outline.count_r = function (ctx, node) { + for (var i = 0; i < node.children.length; i++) { + ctx.count++; + this.count_r(ctx, node.children[i]); + } + + return ctx.count; + }; + }]); + return this; + })(jsPDF.API); + + /** + * @license + * + * Copyright (c) 2014 James Robb, https://github.com/jamesbrobb + * + * + * ==================================================================== + */ + + /** + * jsPDF PNG PlugIn + * @name png_support + * @module + */ + (function (jsPDFAPI) { + /* + * @see http://www.w3.org/TR/PNG-Chunks.html + * + Color Allowed Interpretation + Type Bit Depths + 0 1,2,4,8,16 Each pixel is a grayscale sample. + 2 8,16 Each pixel is an R,G,B triple. + 3 1,2,4,8 Each pixel is a palette index; + a PLTE chunk must appear. + 4 8,16 Each pixel is a grayscale sample, + followed by an alpha sample. + 6 8,16 Each pixel is an R,G,B triple, + followed by an alpha sample. + */ + + /* + * PNG filter method types + * + * @see http://www.w3.org/TR/PNG-Filters.html + * @see http://www.libpng.org/pub/png/book/chapter09.html + * + * This is what the value 'Predictor' in decode params relates to + * + * 15 is "optimal prediction", which means the prediction algorithm can change from line to line. + * In that case, you actually have to read the first byte off each line for the prediction algorthim (which should be 0-4, corresponding to PDF 10-14) and select the appropriate unprediction algorithm based on that byte. + * + 0 None + 1 Sub + 2 Up + 3 Average + 4 Paeth + */ + + var doesNotHavePngJS = function doesNotHavePngJS() { + return typeof PNG !== "function" || typeof FlateStream !== "function"; + }, + canCompress = function canCompress(value) { + return value !== jsPDFAPI.image_compression.NONE && hasCompressionJS(); + }, + hasCompressionJS = function hasCompressionJS() { + var inst = typeof Deflater === "function"; + if (!inst) throw new Error("requires deflate.js for compression"); + return inst; + }, + compressBytes = function compressBytes(bytes, lineLength, colorsPerPixel, compression) { + var level = 5, + filter_method = filterUp; + + switch (compression) { + case jsPDFAPI.image_compression.FAST: + level = 3; + filter_method = filterSub; + break; + + case jsPDFAPI.image_compression.MEDIUM: + level = 6; + filter_method = filterAverage; + break; + + case jsPDFAPI.image_compression.SLOW: + level = 9; + filter_method = filterPaeth; //uses to sum to choose best filter for each line + + break; + } + + bytes = applyPngFilterMethod(bytes, lineLength, colorsPerPixel, filter_method); + var header = new Uint8Array(createZlibHeader(level)); + var checksum = adler32(bytes); + var deflate = new Deflater(level); + var a = deflate.append(bytes); + var cBytes = deflate.flush(); + var len = header.length + a.length + cBytes.length; + var cmpd = new Uint8Array(len + 4); + cmpd.set(header); + cmpd.set(a, header.length); + cmpd.set(cBytes, header.length + a.length); + cmpd[len++] = checksum >>> 24 & 0xff; + cmpd[len++] = checksum >>> 16 & 0xff; + cmpd[len++] = checksum >>> 8 & 0xff; + cmpd[len++] = checksum & 0xff; + return jsPDFAPI.arrayBufferToBinaryString(cmpd); + }, + createZlibHeader = function createZlibHeader(bytes, level) { + /* + * @see http://www.ietf.org/rfc/rfc1950.txt for zlib header + */ + var cm = 8; + var cinfo = Math.LOG2E * Math.log(0x8000) - 8; + var cmf = cinfo << 4 | cm; + var hdr = cmf << 8; + var flevel = Math.min(3, (level - 1 & 0xff) >> 1); + hdr |= flevel << 6; + hdr |= 0; //FDICT + + hdr += 31 - hdr % 31; + return [cmf, hdr & 0xff & 0xff]; + }, + adler32 = function adler32(array, param) { + var adler = 1; + var s1 = adler & 0xffff, + s2 = adler >>> 16 & 0xffff; + var len = array.length; + var tlen; + var i = 0; + + while (len > 0) { + tlen = len > param ? param : len; + len -= tlen; + + do { + s1 += array[i++]; + s2 += s1; + } while (--tlen); + + s1 %= 65521; + s2 %= 65521; + } + + return (s2 << 16 | s1) >>> 0; + }, + applyPngFilterMethod = function applyPngFilterMethod(bytes, lineLength, colorsPerPixel, filter_method) { + var lines = bytes.length / lineLength, + result = new Uint8Array(bytes.length + lines), + filter_methods = getFilterMethods(), + i = 0, + line, + prevLine, + offset; + + for (; i < lines; i++) { + offset = i * lineLength; + line = bytes.subarray(offset, offset + lineLength); + + if (filter_method) { + result.set(filter_method(line, colorsPerPixel, prevLine), offset + i); + } else { + var j = 0, + len = filter_methods.length, + results = []; + + for (; j < len; j++) { + results[j] = filter_methods[j](line, colorsPerPixel, prevLine); + } + + var ind = getIndexOfSmallestSum(results.concat()); + result.set(results[ind], offset + i); + } + + prevLine = line; + } + + return result; + }, + filterNone = function filterNone(line, colorsPerPixel, prevLine) { + /*var result = new Uint8Array(line.length + 1); + result[0] = 0; + result.set(line, 1);*/ + var result = Array.apply([], line); + result.unshift(0); + return result; + }, + filterSub = function filterSub(line, colorsPerPixel, prevLine) { + var result = [], + i = 0, + len = line.length, + left; + result[0] = 1; + + for (; i < len; i++) { + left = line[i - colorsPerPixel] || 0; + result[i + 1] = line[i] - left + 0x0100 & 0xff; + } + + return result; + }, + filterUp = function filterUp(line, colorsPerPixel, prevLine) { + var result = [], + i = 0, + len = line.length, + up; + result[0] = 2; + + for (; i < len; i++) { + up = prevLine && prevLine[i] || 0; + result[i + 1] = line[i] - up + 0x0100 & 0xff; + } + + return result; + }, + filterAverage = function filterAverage(line, colorsPerPixel, prevLine) { + var result = [], + i = 0, + len = line.length, + left, + up; + result[0] = 3; + + for (; i < len; i++) { + left = line[i - colorsPerPixel] || 0; + up = prevLine && prevLine[i] || 0; + result[i + 1] = line[i] + 0x0100 - (left + up >>> 1) & 0xff; + } + + return result; + }, + filterPaeth = function filterPaeth(line, colorsPerPixel, prevLine) { + var result = [], + i = 0, + len = line.length, + left, + up, + upLeft, + paeth; + result[0] = 4; + + for (; i < len; i++) { + left = line[i - colorsPerPixel] || 0; + up = prevLine && prevLine[i] || 0; + upLeft = prevLine && prevLine[i - colorsPerPixel] || 0; + paeth = paethPredictor(left, up, upLeft); + result[i + 1] = line[i] - paeth + 0x0100 & 0xff; + } + + return result; + }, + paethPredictor = function paethPredictor(left, up, upLeft) { + var p = left + up - upLeft, + pLeft = Math.abs(p - left), + pUp = Math.abs(p - up), + pUpLeft = Math.abs(p - upLeft); + return pLeft <= pUp && pLeft <= pUpLeft ? left : pUp <= pUpLeft ? up : upLeft; + }, + getFilterMethods = function getFilterMethods() { + return [filterNone, filterSub, filterUp, filterAverage, filterPaeth]; + }, + getIndexOfSmallestSum = function getIndexOfSmallestSum(arrays) { + var i = 0, + len = arrays.length, + sum, + min, + ind; + + while (i < len) { + sum = absSum(arrays[i].slice(1)); + + if (sum < min || !min) { + min = sum; + ind = i; + } + + i++; + } + + return ind; + }, + absSum = function absSum(array) { + var i = 0, + len = array.length, + sum = 0; + + while (i < len) { + sum += Math.abs(array[i++]); + } + + return sum; + }, + getPredictorFromCompression = function getPredictorFromCompression(compression) { + var predictor; + + switch (compression) { + case jsPDFAPI.image_compression.FAST: + predictor = 11; + break; + + case jsPDFAPI.image_compression.MEDIUM: + predictor = 13; + break; + + case jsPDFAPI.image_compression.SLOW: + predictor = 14; + break; + + default: + predictor = 12; + break; + } + + return predictor; + }; + /** + * + * @name processPNG + * @function + * @ignore + */ + + + jsPDFAPI.processPNG = function (imageData, imageIndex, alias, compression, dataAsBinaryString) { + + var colorSpace = this.color_spaces.DEVICE_RGB, + decode = this.decode.FLATE_DECODE, + bpc = 8, + img, + dp, + trns, + colors, + pal, + smask; + /* if(this.isString(imageData)) { + }*/ + + if (this.isArrayBuffer(imageData)) imageData = new Uint8Array(imageData); + + if (this.isArrayBufferView(imageData)) { + if (doesNotHavePngJS()) throw new Error("PNG support requires png.js and zlib.js"); + img = new PNG(imageData); + imageData = img.imgData; + bpc = img.bits; + colorSpace = img.colorSpace; + colors = img.colors; //logImg(img); + + /* + * colorType 6 - Each pixel is an R,G,B triple, followed by an alpha sample. + * + * colorType 4 - Each pixel is a grayscale sample, followed by an alpha sample. + * + * Extract alpha to create two separate images, using the alpha as a sMask + */ + + if ([4, 6].indexOf(img.colorType) !== -1) { + /* + * processes 8 bit RGBA and grayscale + alpha images + */ + if (img.bits === 8) { + var pixels = img.pixelBitlength == 32 ? new Uint32Array(img.decodePixels().buffer) : img.pixelBitlength == 16 ? new Uint16Array(img.decodePixels().buffer) : new Uint8Array(img.decodePixels().buffer), + len = pixels.length, + imgData = new Uint8Array(len * img.colors), + alphaData = new Uint8Array(len), + pDiff = img.pixelBitlength - img.bits, + i = 0, + n = 0, + pixel, + pbl; + + for (; i < len; i++) { + pixel = pixels[i]; + pbl = 0; + + while (pbl < pDiff) { + imgData[n++] = pixel >>> pbl & 0xff; + pbl = pbl + img.bits; + } + + alphaData[i] = pixel >>> pbl & 0xff; + } + } + /* + * processes 16 bit RGBA and grayscale + alpha images + */ + + + if (img.bits === 16) { + var pixels = new Uint32Array(img.decodePixels().buffer), + len = pixels.length, + imgData = new Uint8Array(len * (32 / img.pixelBitlength) * img.colors), + alphaData = new Uint8Array(len * (32 / img.pixelBitlength)), + hasColors = img.colors > 1, + i = 0, + n = 0, + a = 0, + pixel; + + while (i < len) { + pixel = pixels[i++]; + imgData[n++] = pixel >>> 0 & 0xff; + + if (hasColors) { + imgData[n++] = pixel >>> 16 & 0xff; + pixel = pixels[i++]; + imgData[n++] = pixel >>> 0 & 0xff; + } + + alphaData[a++] = pixel >>> 16 & 0xff; + } + + bpc = 8; + } + + if (canCompress(compression)) { + imageData = compressBytes(imgData, img.width * img.colors, img.colors, compression); + smask = compressBytes(alphaData, img.width, 1, compression); + } else { + imageData = imgData; + smask = alphaData; + decode = null; + } + } + /* + * Indexed png. Each pixel is a palette index. + */ + + + if (img.colorType === 3) { + colorSpace = this.color_spaces.INDEXED; + pal = img.palette; + + if (img.transparency.indexed) { + var trans = img.transparency.indexed; + var total = 0, + i = 0, + len = trans.length; + + for (; i < len; ++i) { + total += trans[i]; + } + + total = total / 255; + /* + * a single color is specified as 100% transparent (0), + * so we set trns to use a /Mask with that index + */ + + if (total === len - 1 && trans.indexOf(0) !== -1) { + trns = [trans.indexOf(0)]; + /* + * there's more than one colour within the palette that specifies + * a transparency value less than 255, so we unroll the pixels to create an image sMask + */ + } else if (total !== len) { + var pixels = img.decodePixels(), + alphaData = new Uint8Array(pixels.length), + i = 0, + len = pixels.length; + + for (; i < len; i++) { + alphaData[i] = trans[pixels[i]]; + } + + smask = compressBytes(alphaData, img.width, 1); + } + } + } + + var predictor = getPredictorFromCompression(compression); + if (decode === this.decode.FLATE_DECODE) dp = "/Predictor " + predictor + " /Colors " + colors + " /BitsPerComponent " + bpc + " /Columns " + img.width; //remove 'Predictor' as it applies to the type of png filter applied to its IDAT - we only apply with compression + else dp = "/Colors " + colors + " /BitsPerComponent " + bpc + " /Columns " + img.width; + if (this.isArrayBuffer(imageData) || this.isArrayBufferView(imageData)) imageData = this.arrayBufferToBinaryString(imageData); + if (smask && this.isArrayBuffer(smask) || this.isArrayBufferView(smask)) smask = this.arrayBufferToBinaryString(smask); + return this.createImageInfo(imageData, img.width, img.height, colorSpace, bpc, decode, imageIndex, alias, dp, trns, pal, smask, predictor); + } + + throw new Error("Unsupported PNG image data, try using JPEG instead."); + }; + })(jsPDF.API); + + /** + * @license + * Copyright (c) 2017 Aras Abbasi + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF gif Support PlugIn + * + * @name gif_support + * @module + */ + (function (jsPDFAPI) { + + jsPDFAPI.processGIF89A = function (imageData, imageIndex, alias, compression, dataAsBinaryString) { + var reader = new GifReader(imageData); + var width = reader.width, + height = reader.height; + var qu = 100; + var pixels = []; + reader.decodeAndBlitFrameRGBA(0, pixels); + var rawImageData = { + data: pixels, + width: width, + height: height + }; + var encoder = new JPEGEncoder(qu); + var data = encoder.encode(rawImageData, qu); + return jsPDFAPI.processJPEG.call(this, data, imageIndex, alias, compression); + }; + + jsPDFAPI.processGIF87A = jsPDFAPI.processGIF89A; + })(jsPDF.API); + + /** + * Copyright (c) 2018 Aras Abbasi + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF bmp Support PlugIn + * @name bmp_support + * @module + */ + (function (jsPDFAPI) { + + jsPDFAPI.processBMP = function (imageData, imageIndex, alias, compression, dataAsBinaryString) { + var reader = new BmpDecoder(imageData, false); + var width = reader.width, + height = reader.height; + var qu = 100; + var pixels = reader.getData(); + var rawImageData = { + data: pixels, + width: width, + height: height + }; + var encoder = new JPEGEncoder(qu); + var data = encoder.encode(rawImageData, qu); + return jsPDFAPI.processJPEG.call(this, data, imageIndex, alias, compression); + }; + })(jsPDF.API); + + /** + * @license + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF setLanguage Plugin + * + * @name setLanguage + * @module + */ + (function (jsPDFAPI) { + /** + * Add Language Tag to the generated PDF + * + * @name setLanguage + * @function + * @param {string} langCode The Language code as ISO-639-1 (e.g. 'en') or as country language code (e.g. 'en-GB'). + * @returns {jsPDF} + * @example + * var doc = new jsPDF() + * doc.text(10, 10, 'This is a test') + * doc.setLanguage("en-US") + * doc.save('english.pdf') + */ + + jsPDFAPI.setLanguage = function (langCode) { + + var langCodes = { + af: "Afrikaans", + sq: "Albanian", + ar: "Arabic (Standard)", + "ar-DZ": "Arabic (Algeria)", + "ar-BH": "Arabic (Bahrain)", + "ar-EG": "Arabic (Egypt)", + "ar-IQ": "Arabic (Iraq)", + "ar-JO": "Arabic (Jordan)", + "ar-KW": "Arabic (Kuwait)", + "ar-LB": "Arabic (Lebanon)", + "ar-LY": "Arabic (Libya)", + "ar-MA": "Arabic (Morocco)", + "ar-OM": "Arabic (Oman)", + "ar-QA": "Arabic (Qatar)", + "ar-SA": "Arabic (Saudi Arabia)", + "ar-SY": "Arabic (Syria)", + "ar-TN": "Arabic (Tunisia)", + "ar-AE": "Arabic (U.A.E.)", + "ar-YE": "Arabic (Yemen)", + an: "Aragonese", + hy: "Armenian", + as: "Assamese", + ast: "Asturian", + az: "Azerbaijani", + eu: "Basque", + be: "Belarusian", + bn: "Bengali", + bs: "Bosnian", + br: "Breton", + bg: "Bulgarian", + my: "Burmese", + ca: "Catalan", + ch: "Chamorro", + ce: "Chechen", + zh: "Chinese", + "zh-HK": "Chinese (Hong Kong)", + "zh-CN": "Chinese (PRC)", + "zh-SG": "Chinese (Singapore)", + "zh-TW": "Chinese (Taiwan)", + cv: "Chuvash", + co: "Corsican", + cr: "Cree", + hr: "Croatian", + cs: "Czech", + da: "Danish", + nl: "Dutch (Standard)", + "nl-BE": "Dutch (Belgian)", + en: "English", + "en-AU": "English (Australia)", + "en-BZ": "English (Belize)", + "en-CA": "English (Canada)", + "en-IE": "English (Ireland)", + "en-JM": "English (Jamaica)", + "en-NZ": "English (New Zealand)", + "en-PH": "English (Philippines)", + "en-ZA": "English (South Africa)", + "en-TT": "English (Trinidad & Tobago)", + "en-GB": "English (United Kingdom)", + "en-US": "English (United States)", + "en-ZW": "English (Zimbabwe)", + eo: "Esperanto", + et: "Estonian", + fo: "Faeroese", + fj: "Fijian", + fi: "Finnish", + fr: "French (Standard)", + "fr-BE": "French (Belgium)", + "fr-CA": "French (Canada)", + "fr-FR": "French (France)", + "fr-LU": "French (Luxembourg)", + "fr-MC": "French (Monaco)", + "fr-CH": "French (Switzerland)", + fy: "Frisian", + fur: "Friulian", + gd: "Gaelic (Scots)", + "gd-IE": "Gaelic (Irish)", + gl: "Galacian", + ka: "Georgian", + de: "German (Standard)", + "de-AT": "German (Austria)", + "de-DE": "German (Germany)", + "de-LI": "German (Liechtenstein)", + "de-LU": "German (Luxembourg)", + "de-CH": "German (Switzerland)", + el: "Greek", + gu: "Gujurati", + ht: "Haitian", + he: "Hebrew", + hi: "Hindi", + hu: "Hungarian", + is: "Icelandic", + id: "Indonesian", + iu: "Inuktitut", + ga: "Irish", + it: "Italian (Standard)", + "it-CH": "Italian (Switzerland)", + ja: "Japanese", + kn: "Kannada", + ks: "Kashmiri", + kk: "Kazakh", + km: "Khmer", + ky: "Kirghiz", + tlh: "Klingon", + ko: "Korean", + "ko-KP": "Korean (North Korea)", + "ko-KR": "Korean (South Korea)", + la: "Latin", + lv: "Latvian", + lt: "Lithuanian", + lb: "Luxembourgish", + mk: "FYRO Macedonian", + ms: "Malay", + ml: "Malayalam", + mt: "Maltese", + mi: "Maori", + mr: "Marathi", + mo: "Moldavian", + nv: "Navajo", + ng: "Ndonga", + ne: "Nepali", + no: "Norwegian", + nb: "Norwegian (Bokmal)", + nn: "Norwegian (Nynorsk)", + oc: "Occitan", + or: "Oriya", + om: "Oromo", + fa: "Persian", + "fa-IR": "Persian/Iran", + pl: "Polish", + pt: "Portuguese", + "pt-BR": "Portuguese (Brazil)", + pa: "Punjabi", + "pa-IN": "Punjabi (India)", + "pa-PK": "Punjabi (Pakistan)", + qu: "Quechua", + rm: "Rhaeto-Romanic", + ro: "Romanian", + "ro-MO": "Romanian (Moldavia)", + ru: "Russian", + "ru-MO": "Russian (Moldavia)", + sz: "Sami (Lappish)", + sg: "Sango", + sa: "Sanskrit", + sc: "Sardinian", + sd: "Sindhi", + si: "Singhalese", + sr: "Serbian", + sk: "Slovak", + sl: "Slovenian", + so: "Somani", + sb: "Sorbian", + es: "Spanish", + "es-AR": "Spanish (Argentina)", + "es-BO": "Spanish (Bolivia)", + "es-CL": "Spanish (Chile)", + "es-CO": "Spanish (Colombia)", + "es-CR": "Spanish (Costa Rica)", + "es-DO": "Spanish (Dominican Republic)", + "es-EC": "Spanish (Ecuador)", + "es-SV": "Spanish (El Salvador)", + "es-GT": "Spanish (Guatemala)", + "es-HN": "Spanish (Honduras)", + "es-MX": "Spanish (Mexico)", + "es-NI": "Spanish (Nicaragua)", + "es-PA": "Spanish (Panama)", + "es-PY": "Spanish (Paraguay)", + "es-PE": "Spanish (Peru)", + "es-PR": "Spanish (Puerto Rico)", + "es-ES": "Spanish (Spain)", + "es-UY": "Spanish (Uruguay)", + "es-VE": "Spanish (Venezuela)", + sx: "Sutu", + sw: "Swahili", + sv: "Swedish", + "sv-FI": "Swedish (Finland)", + "sv-SV": "Swedish (Sweden)", + ta: "Tamil", + tt: "Tatar", + te: "Teluga", + th: "Thai", + tig: "Tigre", + ts: "Tsonga", + tn: "Tswana", + tr: "Turkish", + tk: "Turkmen", + uk: "Ukrainian", + hsb: "Upper Sorbian", + ur: "Urdu", + ve: "Venda", + vi: "Vietnamese", + vo: "Volapuk", + wa: "Walloon", + cy: "Welsh", + xh: "Xhosa", + ji: "Yiddish", + zu: "Zulu" + }; + + if (this.internal.languageSettings === undefined) { + this.internal.languageSettings = {}; + this.internal.languageSettings.isSubscribed = false; + } + + if (langCodes[langCode] !== undefined) { + this.internal.languageSettings.languageCode = langCode; + + if (this.internal.languageSettings.isSubscribed === false) { + this.internal.events.subscribe("putCatalog", function () { + this.internal.write("/Lang (" + this.internal.languageSettings.languageCode + ")"); + }); + this.internal.languageSettings.isSubscribed = true; + } + } + + return this; + }; + })(jsPDF.API); + + /** @license + * MIT license. + * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com + * 2014 Diego Casorran, https://github.com/diegocr + * + * + * ==================================================================== + */ + + /** + * jsPDF split_text_to_size plugin + * + * @name split_text_to_size + * @module + */ + (function (API) { + /** + * Returns an array of length matching length of the 'word' string, with each + * cell occupied by the width of the char in that position. + * + * @name getCharWidthsArray + * @function + * @param {string} text + * @param {Object} options + * @returns {Array} + */ + + var getCharWidthsArray = API.getCharWidthsArray = function (text, options) { + options = options || {}; + var activeFont = options.font || this.internal.getFont(); + var fontSize = options.fontSize || this.internal.getFontSize(); + var charSpace = options.charSpace || this.internal.getCharSpace(); + var widths = options.widths ? options.widths : activeFont.metadata.Unicode.widths; + var widthsFractionOf = widths.fof ? widths.fof : 1; + var kerning = options.kerning ? options.kerning : activeFont.metadata.Unicode.kerning; + var kerningFractionOf = kerning.fof ? kerning.fof : 1; + var i; + var l; + var char_code; + var prior_char_code = 0; //for kerning + + var default_char_width = widths[0] || widthsFractionOf; + var output = []; + + for (i = 0, l = text.length; i < l; i++) { + char_code = text.charCodeAt(i); + + if (typeof activeFont.metadata.widthOfString === "function") { + output.push((activeFont.metadata.widthOfGlyph(activeFont.metadata.characterToGlyph(char_code)) + charSpace * (1000 / fontSize) || 0) / 1000); + } else { + output.push((widths[char_code] || default_char_width) / widthsFractionOf + (kerning[char_code] && kerning[char_code][prior_char_code] || 0) / kerningFractionOf); + } + + prior_char_code = char_code; + } + + return output; + }; + /** + * Calculate the sum of a number-array + * + * @name getArraySum + * @public + * @function + * @param {Array} array Array of numbers + * @returns {number} + */ + + + var getArraySum = API.getArraySum = function (array) { + var i = array.length, + output = 0; + + while (i) { + i--; + output += array[i]; + } + + return output; + }; + /** + * Returns a widths of string in a given font, if the font size is set as 1 point. + * + * In other words, this is "proportional" value. For 1 unit of font size, the length + * of the string will be that much. + * + * Multiply by font size to get actual width in *points* + * Then divide by 72 to get inches or divide by (72/25.6) to get 'mm' etc. + * + * @name getStringUnitWidth + * @public + * @function + * @param {string} text + * @param {string} options + * @returns {number} result + */ + + + var getStringUnitWidth = API.getStringUnitWidth = function (text, options) { + options = options || {}; + var fontSize = options.fontSize || this.internal.getFontSize(); + var font = options.font || this.internal.getFont(); + var charSpace = options.charSpace || this.internal.getCharSpace(); + var result = 0; + + if (typeof font.metadata.widthOfString === "function") { + result = font.metadata.widthOfString(text, fontSize, charSpace) / fontSize; + } else { + result = getArraySum(getCharWidthsArray.apply(this, arguments)); + } + + return result; + }; + /** + returns array of lines + */ + + + var splitLongWord = function splitLongWord(word, widths_array, firstLineMaxLen, maxLen) { + var answer = []; // 1st, chop off the piece that can fit on the hanging line. + + var i = 0, + l = word.length, + workingLen = 0; + + while (i !== l && workingLen + widths_array[i] < firstLineMaxLen) { + workingLen += widths_array[i]; + i++; + } // this is first line. + + + answer.push(word.slice(0, i)); // 2nd. Split the rest into maxLen pieces. + + var startOfLine = i; + workingLen = 0; + + while (i !== l) { + if (workingLen + widths_array[i] > maxLen) { + answer.push(word.slice(startOfLine, i)); + workingLen = 0; + startOfLine = i; + } + + workingLen += widths_array[i]; + i++; + } + + if (startOfLine !== i) { + answer.push(word.slice(startOfLine, i)); + } + + return answer; + }; // Note, all sizing inputs for this function must be in "font measurement units" + // By default, for PDF, it's "point". + + + var splitParagraphIntoLines = function splitParagraphIntoLines(text, maxlen, options) { + // at this time works only on Western scripts, ones with space char + // separating the words. Feel free to expand. + if (!options) { + options = {}; + } + + var line = [], + lines = [line], + line_length = options.textIndent || 0, + separator_length = 0, + current_word_length = 0, + word, + widths_array, + words = text.split(" "), + spaceCharWidth = getCharWidthsArray.apply(this, [" ", options])[0], + i, + l, + tmp, + lineIndent; + + if (options.lineIndent === -1) { + lineIndent = words[0].length + 2; + } else { + lineIndent = options.lineIndent || 0; + } + + if (lineIndent) { + var pad = Array(lineIndent).join(" "), + wrds = []; + words.map(function (wrd) { + wrd = wrd.split(/\s*\n/); + + if (wrd.length > 1) { + wrds = wrds.concat(wrd.map(function (wrd, idx) { + return (idx && wrd.length ? "\n" : "") + wrd; + })); + } else { + wrds.push(wrd[0]); + } + }); + words = wrds; + lineIndent = getStringUnitWidth.apply(this, [pad, options]); + } + + for (i = 0, l = words.length; i < l; i++) { + var force = 0; + word = words[i]; + + if (lineIndent && word[0] == "\n") { + word = word.substr(1); + force = 1; + } + + widths_array = getCharWidthsArray.apply(this, [word, options]); + current_word_length = getArraySum(widths_array); + + if (line_length + separator_length + current_word_length > maxlen || force) { + if (current_word_length > maxlen) { + // this happens when you have space-less long URLs for example. + // we just chop these to size. We do NOT insert hiphens + tmp = splitLongWord.apply(this, [word, widths_array, maxlen - (line_length + separator_length), maxlen]); // first line we add to existing line object + + line.push(tmp.shift()); // it's ok to have extra space indicator there + // last line we make into new line object + + line = [tmp.pop()]; // lines in the middle we apped to lines object as whole lines + + while (tmp.length) { + lines.push([tmp.shift()]); // single fragment occupies whole line + } + + current_word_length = getArraySum(widths_array.slice(word.length - (line[0] ? line[0].length : 0))); + } else { + // just put it on a new line + line = [word]; + } // now we attach new line to lines + + + lines.push(line); + line_length = current_word_length + lineIndent; + separator_length = spaceCharWidth; + } else { + line.push(word); + line_length += separator_length + current_word_length; + separator_length = spaceCharWidth; + } + } + + if (lineIndent) { + var postProcess = function postProcess(ln, idx) { + return (idx ? pad : "") + ln.join(" "); + }; + } else { + var postProcess = function postProcess(ln) { + return ln.join(" "); + }; + } + + return lines.map(postProcess); + }; + /** + * Splits a given string into an array of strings. Uses 'size' value + * (in measurement units declared as default for the jsPDF instance) + * and the font's "widths" and "Kerning" tables, where available, to + * determine display length of a given string for a given font. + * + * We use character's 100% of unit size (height) as width when Width + * table or other default width is not available. + * + * @name splitTextToSize + * @public + * @function + * @param {string} text Unencoded, regular JavaScript (Unicode, UTF-16 / UCS-2) string. + * @param {number} size Nominal number, measured in units default to this instance of jsPDF. + * @param {Object} options Optional flags needed for chopper to do the right thing. + * @returns {Array} array Array with strings chopped to size. + */ + + + API.splitTextToSize = function (text, maxlen, options) { + + options = options || {}; + + var fsize = options.fontSize || this.internal.getFontSize(), + newOptions = function (options) { + var widths = { + 0: 1 + }, + kerning = {}; + + if (!options.widths || !options.kerning) { + var f = this.internal.getFont(options.fontName, options.fontStyle), + encoding = "Unicode"; // NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE + // Actual JavaScript-native String's 16bit char codes used. + // no multi-byte logic here + + if (f.metadata[encoding]) { + return { + widths: f.metadata[encoding].widths || widths, + kerning: f.metadata[encoding].kerning || kerning + }; + } else { + return { + font: f.metadata, + fontSize: this.internal.getFontSize(), + charSpace: this.internal.getCharSpace() + }; + } + } else { + return { + widths: options.widths, + kerning: options.kerning + }; + } // then use default values + + + return { + widths: widths, + kerning: kerning + }; + }.call(this, options); // first we split on end-of-line chars + + + var paragraphs; + + if (Array.isArray(text)) { + paragraphs = text; + } else { + paragraphs = text.split(/\r?\n/); + } // now we convert size (max length of line) into "font size units" + // at present time, the "font size unit" is always 'point' + // 'proportional' means, "in proportion to font size" + + + var fontUnit_maxLen = 1.0 * this.internal.scaleFactor * maxlen / fsize; // at this time, fsize is always in "points" regardless of the default measurement unit of the doc. + // this may change in the future? + // until then, proportional_maxlen is likely to be in 'points' + // If first line is to be indented (shorter or longer) than maxLen + // we indicate that by using CSS-style "text-indent" option. + // here it's in font units too (which is likely 'points') + // it can be negative (which makes the first line longer than maxLen) + + newOptions.textIndent = options.textIndent ? options.textIndent * 1.0 * this.internal.scaleFactor / fsize : 0; + newOptions.lineIndent = options.lineIndent; + var i, + l, + output = []; + + for (i = 0, l = paragraphs.length; i < l; i++) { + output = output.concat(splitParagraphIntoLines.apply(this, [paragraphs[i], fontUnit_maxLen, newOptions])); + } + + return output; + }; + })(jsPDF.API); + + /** @license + jsPDF standard_fonts_metrics plugin + * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com + * MIT license. + * + * ==================================================================== + */ + + /** + * This file adds the standard font metrics to jsPDF. + * + * Font metrics data is reprocessed derivative of contents of + * "Font Metrics for PDF Core 14 Fonts" package, which exhibits the following copyright and license: + * + * Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. + * + * This file and the 14 PostScript(R) AFM files it accompanies may be used, + * copied, and distributed for any purpose and without charge, with or without + * modification, provided that all copyright notices are retained; that the AFM + * files are not distributed without this file; that all modifications to this + * file or any of the AFM files are prominently noted in the modified file(s); + * and that this paragraph is not modified. Adobe Systems has no responsibility + * or obligation to support the use of the AFM files. + * + * @name standard_fonts_metrics + * @module + */ + (function (API) { + /* + # reference (Python) versions of 'compress' and 'uncompress' + # only 'uncompress' function is featured lower as JavaScript + # if you want to unit test "roundtrip", just transcribe the reference + # 'compress' function from Python into JavaScript + def compress(data): + keys = '0123456789abcdef' + values = 'klmnopqrstuvwxyz' + mapping = dict(zip(keys, values)) + vals = [] + for key in data.keys(): + value = data[key] + try: + keystring = hex(key)[2:] + keystring = keystring[:-1] + mapping[keystring[-1:]] + except: + keystring = key.join(["'","'"]) + #print('Keystring is %s' % keystring) + try: + if value < 0: + valuestring = hex(value)[3:] + numberprefix = '-' + else: + valuestring = hex(value)[2:] + numberprefix = '' + valuestring = numberprefix + valuestring[:-1] + mapping[valuestring[-1:]] + except: + if type(value) == dict: + valuestring = compress(value) + else: + raise Exception("Don't know what to do with value type %s" % type(value)) + vals.append(keystring+valuestring) + + return '{' + ''.join(vals) + '}' + def uncompress(data): + decoded = '0123456789abcdef' + encoded = 'klmnopqrstuvwxyz' + mapping = dict(zip(encoded, decoded)) + sign = +1 + stringmode = False + stringparts = [] + output = {} + activeobject = output + parentchain = [] + keyparts = '' + valueparts = '' + key = None + ending = set(encoded) + i = 1 + l = len(data) - 1 # stripping starting, ending {} + while i != l: # stripping {} + # -, {, }, ' are special. + ch = data[i] + i += 1 + if ch == "'": + if stringmode: + # end of string mode + stringmode = False + key = ''.join(stringparts) + else: + # start of string mode + stringmode = True + stringparts = [] + elif stringmode == True: + #print("Adding %s to stringpart" % ch) + stringparts.append(ch) + elif ch == '{': + # start of object + parentchain.append( [activeobject, key] ) + activeobject = {} + key = None + #DEBUG = True + elif ch == '}': + # end of object + parent, key = parentchain.pop() + parent[key] = activeobject + key = None + activeobject = parent + #DEBUG = False + elif ch == '-': + sign = -1 + else: + # must be number + if key == None: + #debug("In Key. It is '%s', ch is '%s'" % (keyparts, ch)) + if ch in ending: + #debug("End of key") + keyparts += mapping[ch] + key = int(keyparts, 16) * sign + sign = +1 + keyparts = '' + else: + keyparts += ch + else: + #debug("In value. It is '%s', ch is '%s'" % (valueparts, ch)) + if ch in ending: + #debug("End of value") + valueparts += mapping[ch] + activeobject[key] = int(valueparts, 16) * sign + sign = +1 + key = None + valueparts = '' + else: + valueparts += ch + #debug(activeobject) + return output + */ + + /** + Uncompresses data compressed into custom, base16-like format. + @public + @function + @param + @returns {Type} + */ + + var uncompress = function uncompress(data) { + var decoded = "0123456789abcdef", + encoded = "klmnopqrstuvwxyz", + mapping = {}; + + for (var i = 0; i < encoded.length; i++) { + mapping[encoded[i]] = decoded[i]; + } + + var undef, + output = {}, + sign = 1, + stringparts, + // undef. will be [] in string mode + activeobject = output, + parentchain = [], + parent_key_pair, + keyparts = "", + valueparts = "", + key, + // undef. will be Truthy when Key is resolved. + datalen = data.length - 1, + // stripping ending } + ch; + i = 1; // stripping starting { + + while (i != datalen) { + // - { } ' are special. + ch = data[i]; + i += 1; + + if (ch == "'") { + if (stringparts) { + // end of string mode + key = stringparts.join(""); + stringparts = undef; + } else { + // start of string mode + stringparts = []; + } + } else if (stringparts) { + stringparts.push(ch); + } else if (ch == "{") { + // start of object + parentchain.push([activeobject, key]); + activeobject = {}; + key = undef; + } else if (ch == "}") { + // end of object + parent_key_pair = parentchain.pop(); + parent_key_pair[0][parent_key_pair[1]] = activeobject; + key = undef; + activeobject = parent_key_pair[0]; + } else if (ch == "-") { + sign = -1; + } else { + // must be number + if (key === undef) { + if (mapping.hasOwnProperty(ch)) { + keyparts += mapping[ch]; + key = parseInt(keyparts, 16) * sign; + sign = +1; + keyparts = ""; + } else { + keyparts += ch; + } + } else { + if (mapping.hasOwnProperty(ch)) { + valueparts += mapping[ch]; + activeobject[key] = parseInt(valueparts, 16) * sign; + sign = +1; + key = undef; + valueparts = ""; + } else { + valueparts += ch; + } + } + } + } // end while + + + return output; + }; // encoding = 'Unicode' + // NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE. NO clever BOM behavior + // Actual 16bit char codes used. + // no multi-byte logic here + // Unicode characters to WinAnsiEncoding: + // {402: 131, 8211: 150, 8212: 151, 8216: 145, 8217: 146, 8218: 130, 8220: 147, 8221: 148, 8222: 132, 8224: 134, 8225: 135, 8226: 149, 8230: 133, 8364: 128, 8240:137, 8249: 139, 8250: 155, 710: 136, 8482: 153, 338: 140, 339: 156, 732: 152, 352: 138, 353: 154, 376: 159, 381: 142, 382: 158} + // as you can see, all Unicode chars are outside of 0-255 range. No char code conflicts. + // this means that you can give Win cp1252 encoded strings to jsPDF for rendering directly + // as well as give strings with some (supported by these fonts) Unicode characters and + // these will be mapped to win cp1252 + // for example, you can send char code (cp1252) 0x80 or (unicode) 0x20AC, getting "Euro" glyph displayed in both cases. + + + var encodingBlock = { + codePages: ["WinAnsiEncoding"], + WinAnsiEncoding: uncompress("{19m8n201n9q201o9r201s9l201t9m201u8m201w9n201x9o201y8o202k8q202l8r202m9p202q8p20aw8k203k8t203t8v203u9v2cq8s212m9t15m8w15n9w2dw9s16k8u16l9u17s9z17x8y17y9y}") + }, + encodings = { + Unicode: { + Courier: encodingBlock, + "Courier-Bold": encodingBlock, + "Courier-BoldOblique": encodingBlock, + "Courier-Oblique": encodingBlock, + Helvetica: encodingBlock, + "Helvetica-Bold": encodingBlock, + "Helvetica-BoldOblique": encodingBlock, + "Helvetica-Oblique": encodingBlock, + "Times-Roman": encodingBlock, + "Times-Bold": encodingBlock, + "Times-BoldItalic": encodingBlock, + "Times-Italic": encodingBlock // , 'Symbol' + // , 'ZapfDingbats' + + } + }, + fontMetrics = { + Unicode: { + // all sizing numbers are n/fontMetricsFractionOf = one font size unit + // this means that if fontMetricsFractionOf = 1000, and letter A's width is 476, it's + // width is 476/1000 or 47.6% of its height (regardless of font size) + // At this time this value applies to "widths" and "kerning" numbers. + // char code 0 represents "default" (average) width - use it for chars missing in this table. + // key 'fof' represents the "fontMetricsFractionOf" value + "Courier-Oblique": uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"), + "Times-BoldItalic": uncompress("{'widths'{k3o2q4ycx2r201n3m201o6o201s2l201t2l201u2l201w3m201x3m201y3m2k1t2l2r202m2n2n3m2o3m2p5n202q6o2r1w2s2l2t2l2u3m2v3t2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w3t3x3t3y3t3z3m4k5n4l4m4m4m4n4m4o4s4p4m4q4m4r4s4s4y4t2r4u3m4v4m4w3x4x5t4y4s4z4s5k3x5l4s5m4m5n3r5o3x5p4s5q4m5r5t5s4m5t3x5u3x5v2l5w1w5x2l5y3t5z3m6k2l6l3m6m3m6n2w6o3m6p2w6q2l6r3m6s3r6t1w6u1w6v3m6w1w6x4y6y3r6z3m7k3m7l3m7m2r7n2r7o1w7p3r7q2w7r4m7s3m7t2w7u2r7v2n7w1q7x2n7y3t202l3mcl4mal2ram3man3mao3map3mar3mas2lat4uau1uav3maw3way4uaz2lbk2sbl3t'fof'6obo2lbp3tbq3mbr1tbs2lbu1ybv3mbz3mck4m202k3mcm4mcn4mco4mcp4mcq5ycr4mcs4mct4mcu4mcv4mcw2r2m3rcy2rcz2rdl4sdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek3mel3mem3men3meo3mep3meq4ser2wes2wet2weu2wev2wew1wex1wey1wez1wfl3rfm3mfn3mfo3mfp3mfq3mfr3tfs3mft3rfu3rfv3rfw3rfz2w203k6o212m6o2dw2l2cq2l3t3m3u2l17s3x19m3m}'kerning'{cl{4qu5kt5qt5rs17ss5ts}201s{201ss}201t{cks4lscmscnscoscpscls2wu2yu201ts}201x{2wu2yu}2k{201ts}2w{4qx5kx5ou5qx5rs17su5tu}2x{17su5tu5ou}2y{4qx5kx5ou5qx5rs17ss5ts}'fof'-6ofn{17sw5tw5ou5qw5rs}7t{cksclscmscnscoscps4ls}3u{17su5tu5os5qs}3v{17su5tu5os5qs}7p{17su5tu}ck{4qu5kt5qt5rs17ss5ts}4l{4qu5kt5qt5rs17ss5ts}cm{4qu5kt5qt5rs17ss5ts}cn{4qu5kt5qt5rs17ss5ts}co{4qu5kt5qt5rs17ss5ts}cp{4qu5kt5qt5rs17ss5ts}6l{4qu5ou5qw5rt17su5tu}5q{ckuclucmucnucoucpu4lu}5r{ckuclucmucnucoucpu4lu}7q{cksclscmscnscoscps4ls}6p{4qu5ou5qw5rt17sw5tw}ek{4qu5ou5qw5rt17su5tu}el{4qu5ou5qw5rt17su5tu}em{4qu5ou5qw5rt17su5tu}en{4qu5ou5qw5rt17su5tu}eo{4qu5ou5qw5rt17su5tu}ep{4qu5ou5qw5rt17su5tu}es{17ss5ts5qs4qu}et{4qu5ou5qw5rt17sw5tw}eu{4qu5ou5qw5rt17ss5ts}ev{17ss5ts5qs4qu}6z{17sw5tw5ou5qw5rs}fm{17sw5tw5ou5qw5rs}7n{201ts}fo{17sw5tw5ou5qw5rs}fp{17sw5tw5ou5qw5rs}fq{17sw5tw5ou5qw5rs}7r{cksclscmscnscoscps4ls}fs{17sw5tw5ou5qw5rs}ft{17su5tu}fu{17su5tu}fv{17su5tu}fw{17su5tu}fz{cksclscmscnscoscps4ls}}}"), + "Helvetica-Bold": uncompress("{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'kerning'{cl{4qs5ku5ot5qs17sv5tv}201t{2ww4wy2yw}201w{2ks}201x{2ww4wy2yw}2k{201ts201xs}2w{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}2x{5ow5qs}2y{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}'fof'-6o7p{17su5tu5ot}ck{4qs5ku5ot5qs17sv5tv}4l{4qs5ku5ot5qs17sv5tv}cm{4qs5ku5ot5qs17sv5tv}cn{4qs5ku5ot5qs17sv5tv}co{4qs5ku5ot5qs17sv5tv}cp{4qs5ku5ot5qs17sv5tv}6l{17st5tt5os}17s{2kwclvcmvcnvcovcpv4lv4wwckv}5o{2kucltcmtcntcotcpt4lt4wtckt}5q{2ksclscmscnscoscps4ls4wvcks}5r{2ks4ws}5t{2kwclvcmvcnvcovcpv4lv4wwckv}eo{17st5tt5os}fu{17su5tu5ot}6p{17ss5ts}ek{17st5tt5os}el{17st5tt5os}em{17st5tt5os}en{17st5tt5os}6o{201ts}ep{17st5tt5os}es{17ss5ts}et{17ss5ts}eu{17ss5ts}ev{17ss5ts}6z{17su5tu5os5qt}fm{17su5tu5os5qt}fn{17su5tu5os5qt}fo{17su5tu5os5qt}fp{17su5tu5os5qt}fq{17su5tu5os5qt}fs{17su5tu5os5qt}ft{17su5tu5ot}7m{5os}fv{17su5tu5ot}fw{17su5tu5ot}}}"), + Courier: uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"), + "Courier-BoldOblique": uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"), + "Times-Bold": uncompress("{'widths'{k3q2q5ncx2r201n3m201o6o201s2l201t2l201u2l201w3m201x3m201y3m2k1t2l2l202m2n2n3m2o3m2p6o202q6o2r1w2s2l2t2l2u3m2v3t2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w3t3x3t3y3t3z3m4k5x4l4s4m4m4n4s4o4s4p4m4q3x4r4y4s4y4t2r4u3m4v4y4w4m4x5y4y4s4z4y5k3x5l4y5m4s5n3r5o4m5p4s5q4s5r6o5s4s5t4s5u4m5v2l5w1w5x2l5y3u5z3m6k2l6l3m6m3r6n2w6o3r6p2w6q2l6r3m6s3r6t1w6u2l6v3r6w1w6x5n6y3r6z3m7k3r7l3r7m2w7n2r7o2l7p3r7q3m7r4s7s3m7t3m7u2w7v2r7w1q7x2r7y3o202l3mcl4sal2lam3man3mao3map3mar3mas2lat4uau1yav3maw3tay4uaz2lbk2sbl3t'fof'6obo2lbp3rbr1tbs2lbu2lbv3mbz3mck4s202k3mcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw2r2m3rcy2rcz2rdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3rek3mel3mem3men3meo3mep3meq4ser2wes2wet2weu2wev2wew1wex1wey1wez1wfl3rfm3mfn3mfo3mfp3mfq3mfr3tfs3mft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3m3u2l17s4s19m3m}'kerning'{cl{4qt5ks5ot5qy5rw17sv5tv}201t{cks4lscmscnscoscpscls4wv}2k{201ts}2w{4qu5ku7mu5os5qx5ru17su5tu}2x{17su5tu5ou5qs}2y{4qv5kv7mu5ot5qz5ru17su5tu}'fof'-6o7t{cksclscmscnscoscps4ls}3u{17su5tu5os5qu}3v{17su5tu5os5qu}fu{17su5tu5ou5qu}7p{17su5tu5ou5qu}ck{4qt5ks5ot5qy5rw17sv5tv}4l{4qt5ks5ot5qy5rw17sv5tv}cm{4qt5ks5ot5qy5rw17sv5tv}cn{4qt5ks5ot5qy5rw17sv5tv}co{4qt5ks5ot5qy5rw17sv5tv}cp{4qt5ks5ot5qy5rw17sv5tv}6l{17st5tt5ou5qu}17s{ckuclucmucnucoucpu4lu4wu}5o{ckuclucmucnucoucpu4lu4wu}5q{ckzclzcmzcnzcozcpz4lz4wu}5r{ckxclxcmxcnxcoxcpx4lx4wu}5t{ckuclucmucnucoucpu4lu4wu}7q{ckuclucmucnucoucpu4lu}6p{17sw5tw5ou5qu}ek{17st5tt5qu}el{17st5tt5ou5qu}em{17st5tt5qu}en{17st5tt5qu}eo{17st5tt5qu}ep{17st5tt5ou5qu}es{17ss5ts5qu}et{17sw5tw5ou5qu}eu{17sw5tw5ou5qu}ev{17ss5ts5qu}6z{17sw5tw5ou5qu5rs}fm{17sw5tw5ou5qu5rs}fn{17sw5tw5ou5qu5rs}fo{17sw5tw5ou5qu5rs}fp{17sw5tw5ou5qu5rs}fq{17sw5tw5ou5qu5rs}7r{cktcltcmtcntcotcpt4lt5os}fs{17sw5tw5ou5qu5rs}ft{17su5tu5ou5qu}7m{5os}fv{17su5tu5ou5qu}fw{17su5tu5ou5qu}fz{cksclscmscnscoscps4ls}}}"), + Symbol: uncompress("{'widths'{k3uaw4r19m3m2k1t2l2l202m2y2n3m2p5n202q6o3k3m2s2l2t2l2v3r2w1t3m3m2y1t2z1wbk2sbl3r'fof'6o3n3m3o3m3p3m3q3m3r3m3s3m3t3m3u1w3v1w3w3r3x3r3y3r3z2wbp3t3l3m5v2l5x2l5z3m2q4yfr3r7v3k7w1o7x3k}'kerning'{'fof'-6o}}"), + Helvetica: uncompress("{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'kerning'{5q{4wv}cl{4qs5kw5ow5qs17sv5tv}201t{2wu4w1k2yu}201x{2wu4wy2yu}17s{2ktclucmucnu4otcpu4lu4wycoucku}2w{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}2x{17sy5ty5oy5qs}2y{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}'fof'-6o7p{17sv5tv5ow}ck{4qs5kw5ow5qs17sv5tv}4l{4qs5kw5ow5qs17sv5tv}cm{4qs5kw5ow5qs17sv5tv}cn{4qs5kw5ow5qs17sv5tv}co{4qs5kw5ow5qs17sv5tv}cp{4qs5kw5ow5qs17sv5tv}6l{17sy5ty5ow}do{17st5tt}4z{17st5tt}7s{fst}dm{17st5tt}dn{17st5tt}5o{ckwclwcmwcnwcowcpw4lw4wv}dp{17st5tt}dq{17st5tt}7t{5ow}ds{17st5tt}5t{2ktclucmucnu4otcpu4lu4wycoucku}fu{17sv5tv5ow}6p{17sy5ty5ow5qs}ek{17sy5ty5ow}el{17sy5ty5ow}em{17sy5ty5ow}en{5ty}eo{17sy5ty5ow}ep{17sy5ty5ow}es{17sy5ty5qs}et{17sy5ty5ow5qs}eu{17sy5ty5ow5qs}ev{17sy5ty5ow5qs}6z{17sy5ty5ow5qs}fm{17sy5ty5ow5qs}fn{17sy5ty5ow5qs}fo{17sy5ty5ow5qs}fp{17sy5ty5qs}fq{17sy5ty5ow5qs}7r{5ow}fs{17sy5ty5ow5qs}ft{17sv5tv5ow}7m{5ow}fv{17sv5tv5ow}fw{17sv5tv5ow}}}"), + "Helvetica-BoldOblique": uncompress("{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'kerning'{cl{4qs5ku5ot5qs17sv5tv}201t{2ww4wy2yw}201w{2ks}201x{2ww4wy2yw}2k{201ts201xs}2w{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}2x{5ow5qs}2y{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}'fof'-6o7p{17su5tu5ot}ck{4qs5ku5ot5qs17sv5tv}4l{4qs5ku5ot5qs17sv5tv}cm{4qs5ku5ot5qs17sv5tv}cn{4qs5ku5ot5qs17sv5tv}co{4qs5ku5ot5qs17sv5tv}cp{4qs5ku5ot5qs17sv5tv}6l{17st5tt5os}17s{2kwclvcmvcnvcovcpv4lv4wwckv}5o{2kucltcmtcntcotcpt4lt4wtckt}5q{2ksclscmscnscoscps4ls4wvcks}5r{2ks4ws}5t{2kwclvcmvcnvcovcpv4lv4wwckv}eo{17st5tt5os}fu{17su5tu5ot}6p{17ss5ts}ek{17st5tt5os}el{17st5tt5os}em{17st5tt5os}en{17st5tt5os}6o{201ts}ep{17st5tt5os}es{17ss5ts}et{17ss5ts}eu{17ss5ts}ev{17ss5ts}6z{17su5tu5os5qt}fm{17su5tu5os5qt}fn{17su5tu5os5qt}fo{17su5tu5os5qt}fp{17su5tu5os5qt}fq{17su5tu5os5qt}fs{17su5tu5os5qt}ft{17su5tu5ot}7m{5os}fv{17su5tu5ot}fw{17su5tu5ot}}}"), + ZapfDingbats: uncompress("{'widths'{k4u2k1w'fof'6o}'kerning'{'fof'-6o}}"), + "Courier-Bold": uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"), + "Times-Italic": uncompress("{'widths'{k3n2q4ycx2l201n3m201o5t201s2l201t2l201u2l201w3r201x3r201y3r2k1t2l2l202m2n2n3m2o3m2p5n202q5t2r1p2s2l2t2l2u3m2v4n2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w4n3x4n3y4n3z3m4k5w4l3x4m3x4n4m4o4s4p3x4q3x4r4s4s4s4t2l4u2w4v4m4w3r4x5n4y4m4z4s5k3x5l4s5m3x5n3m5o3r5p4s5q3x5r5n5s3x5t3r5u3r5v2r5w1w5x2r5y2u5z3m6k2l6l3m6m3m6n2w6o3m6p2w6q1w6r3m6s3m6t1w6u1w6v2w6w1w6x4s6y3m6z3m7k3m7l3m7m2r7n2r7o1w7p3m7q2w7r4m7s2w7t2w7u2r7v2s7w1v7x2s7y3q202l3mcl3xal2ram3man3mao3map3mar3mas2lat4wau1vav3maw4nay4waz2lbk2sbl4n'fof'6obo2lbp3mbq3obr1tbs2lbu1zbv3mbz3mck3x202k3mcm3xcn3xco3xcp3xcq5tcr4mcs3xct3xcu3xcv3xcw2l2m2ucy2lcz2ldl4mdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek3mel3mem3men3meo3mep3meq4mer2wes2wet2weu2wev2wew1wex1wey1wez1wfl3mfm3mfn3mfo3mfp3mfq3mfr4nfs3mft3mfu3mfv3mfw3mfz2w203k6o212m6m2dw2l2cq2l3t3m3u2l17s3r19m3m}'kerning'{cl{5kt4qw}201s{201sw}201t{201tw2wy2yy6q-t}201x{2wy2yy}2k{201tw}2w{7qs4qy7rs5ky7mw5os5qx5ru17su5tu}2x{17ss5ts5os}2y{7qs4qy7rs5ky7mw5os5qx5ru17su5tu}'fof'-6o6t{17ss5ts5qs}7t{5os}3v{5qs}7p{17su5tu5qs}ck{5kt4qw}4l{5kt4qw}cm{5kt4qw}cn{5kt4qw}co{5kt4qw}cp{5kt4qw}6l{4qs5ks5ou5qw5ru17su5tu}17s{2ks}5q{ckvclvcmvcnvcovcpv4lv}5r{ckuclucmucnucoucpu4lu}5t{2ks}6p{4qs5ks5ou5qw5ru17su5tu}ek{4qs5ks5ou5qw5ru17su5tu}el{4qs5ks5ou5qw5ru17su5tu}em{4qs5ks5ou5qw5ru17su5tu}en{4qs5ks5ou5qw5ru17su5tu}eo{4qs5ks5ou5qw5ru17su5tu}ep{4qs5ks5ou5qw5ru17su5tu}es{5ks5qs4qs}et{4qs5ks5ou5qw5ru17su5tu}eu{4qs5ks5qw5ru17su5tu}ev{5ks5qs4qs}ex{17ss5ts5qs}6z{4qv5ks5ou5qw5ru17su5tu}fm{4qv5ks5ou5qw5ru17su5tu}fn{4qv5ks5ou5qw5ru17su5tu}fo{4qv5ks5ou5qw5ru17su5tu}fp{4qv5ks5ou5qw5ru17su5tu}fq{4qv5ks5ou5qw5ru17su5tu}7r{5os}fs{4qv5ks5ou5qw5ru17su5tu}ft{17su5tu5qs}fu{17su5tu5qs}fv{17su5tu5qs}fw{17su5tu5qs}}}"), + "Times-Roman": uncompress("{'widths'{k3n2q4ycx2l201n3m201o6o201s2l201t2l201u2l201w2w201x2w201y2w2k1t2l2l202m2n2n3m2o3m2p5n202q6o2r1m2s2l2t2l2u3m2v3s2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v1w3w3s3x3s3y3s3z2w4k5w4l4s4m4m4n4m4o4s4p3x4q3r4r4s4s4s4t2l4u2r4v4s4w3x4x5t4y4s4z4s5k3r5l4s5m4m5n3r5o3x5p4s5q4s5r5y5s4s5t4s5u3x5v2l5w1w5x2l5y2z5z3m6k2l6l2w6m3m6n2w6o3m6p2w6q2l6r3m6s3m6t1w6u1w6v3m6w1w6x4y6y3m6z3m7k3m7l3m7m2l7n2r7o1w7p3m7q3m7r4s7s3m7t3m7u2w7v3k7w1o7x3k7y3q202l3mcl4sal2lam3man3mao3map3mar3mas2lat4wau1vav3maw3say4waz2lbk2sbl3s'fof'6obo2lbp3mbq2xbr1tbs2lbu1zbv3mbz2wck4s202k3mcm4scn4sco4scp4scq5tcr4mcs3xct3xcu3xcv3xcw2l2m2tcy2lcz2ldl4sdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek2wel2wem2wen2weo2wep2weq4mer2wes2wet2weu2wev2wew1wex1wey1wez1wfl3mfm3mfn3mfo3mfp3mfq3mfr3sfs3mft3mfu3mfv3mfw3mfz3m203k6o212m6m2dw2l2cq2l3t3m3u1w17s4s19m3m}'kerning'{cl{4qs5ku17sw5ou5qy5rw201ss5tw201ws}201s{201ss}201t{ckw4lwcmwcnwcowcpwclw4wu201ts}2k{201ts}2w{4qs5kw5os5qx5ru17sx5tx}2x{17sw5tw5ou5qu}2y{4qs5kw5os5qx5ru17sx5tx}'fof'-6o7t{ckuclucmucnucoucpu4lu5os5rs}3u{17su5tu5qs}3v{17su5tu5qs}7p{17sw5tw5qs}ck{4qs5ku17sw5ou5qy5rw201ss5tw201ws}4l{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cm{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cn{4qs5ku17sw5ou5qy5rw201ss5tw201ws}co{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cp{4qs5ku17sw5ou5qy5rw201ss5tw201ws}6l{17su5tu5os5qw5rs}17s{2ktclvcmvcnvcovcpv4lv4wuckv}5o{ckwclwcmwcnwcowcpw4lw4wu}5q{ckyclycmycnycoycpy4ly4wu5ms}5r{cktcltcmtcntcotcpt4lt4ws}5t{2ktclvcmvcnvcovcpv4lv4wuckv}7q{cksclscmscnscoscps4ls}6p{17su5tu5qw5rs}ek{5qs5rs}el{17su5tu5os5qw5rs}em{17su5tu5os5qs5rs}en{17su5qs5rs}eo{5qs5rs}ep{17su5tu5os5qw5rs}es{5qs}et{17su5tu5qw5rs}eu{17su5tu5qs5rs}ev{5qs}6z{17sv5tv5os5qx5rs}fm{5os5qt5rs}fn{17sv5tv5os5qx5rs}fo{17sv5tv5os5qx5rs}fp{5os5qt5rs}fq{5os5qt5rs}7r{ckuclucmucnucoucpu4lu5os}fs{17sv5tv5os5qx5rs}ft{17ss5ts5qs}fu{17sw5tw5qs}fv{17sw5tw5qs}fw{17ss5ts5qs}fz{ckuclucmucnucoucpu4lu5os5rs}}}"), + "Helvetica-Oblique": uncompress("{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'kerning'{5q{4wv}cl{4qs5kw5ow5qs17sv5tv}201t{2wu4w1k2yu}201x{2wu4wy2yu}17s{2ktclucmucnu4otcpu4lu4wycoucku}2w{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}2x{17sy5ty5oy5qs}2y{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}'fof'-6o7p{17sv5tv5ow}ck{4qs5kw5ow5qs17sv5tv}4l{4qs5kw5ow5qs17sv5tv}cm{4qs5kw5ow5qs17sv5tv}cn{4qs5kw5ow5qs17sv5tv}co{4qs5kw5ow5qs17sv5tv}cp{4qs5kw5ow5qs17sv5tv}6l{17sy5ty5ow}do{17st5tt}4z{17st5tt}7s{fst}dm{17st5tt}dn{17st5tt}5o{ckwclwcmwcnwcowcpw4lw4wv}dp{17st5tt}dq{17st5tt}7t{5ow}ds{17st5tt}5t{2ktclucmucnu4otcpu4lu4wycoucku}fu{17sv5tv5ow}6p{17sy5ty5ow5qs}ek{17sy5ty5ow}el{17sy5ty5ow}em{17sy5ty5ow}en{5ty}eo{17sy5ty5ow}ep{17sy5ty5ow}es{17sy5ty5qs}et{17sy5ty5ow5qs}eu{17sy5ty5ow5qs}ev{17sy5ty5ow5qs}6z{17sy5ty5ow5qs}fm{17sy5ty5ow5qs}fn{17sy5ty5ow5qs}fo{17sy5ty5ow5qs}fp{17sy5ty5qs}fq{17sy5ty5ow5qs}7r{5ow}fs{17sy5ty5ow5qs}ft{17sv5tv5ow}7m{5ow}fv{17sv5tv5ow}fw{17sv5tv5ow}}}") + } + }; + /* + This event handler is fired when a new jsPDF object is initialized + This event handler appends metrics data to standard fonts within + that jsPDF instance. The metrics are mapped over Unicode character + codes, NOT CIDs or other codes matching the StandardEncoding table of the + standard PDF fonts. + Future: + Also included is the encoding maping table, converting Unicode (UCS-2, UTF-16) + char codes to StandardEncoding character codes. The encoding table is to be used + somewhere around "pdfEscape" call. + */ + + API.events.push(["addFont", function (data) { + var font = data.font; + var metrics, + unicode_section, + encoding = "Unicode", + encodingBlock; + metrics = fontMetrics[encoding][font.postScriptName]; + + if (metrics) { + if (font.metadata[encoding]) { + unicode_section = font.metadata[encoding]; + } else { + unicode_section = font.metadata[encoding] = {}; + } + + unicode_section.widths = metrics.widths; + unicode_section.kerning = metrics.kerning; + } + + encodingBlock = encodings[encoding][font.postScriptName]; + + if (encodingBlock) { + if (font.metadata[encoding]) { + unicode_section = font.metadata[encoding]; + } else { + unicode_section = font.metadata[encoding] = {}; + } + + unicode_section.encoding = encodingBlock; + + if (encodingBlock.codePages && encodingBlock.codePages.length) { + font.encoding = encodingBlock.codePages[0]; + } + } + }]); // end of adding event handler + })(jsPDF.API); + + /** + * @license + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * @name ttfsupport + * @module + */ + (function (jsPDF, global) { + + jsPDF.API.events.push(["addFont", function (data) { + var font = data.font; + var instance = data.instance; + + if (typeof instance !== "undefined" && instance.existsFileInVFS(font.postScriptName)) { + var file = instance.getFileFromVFS(font.postScriptName); + + if (typeof file !== "string") { + throw new Error("Font is not stored as string-data in vFS, import fonts or remove declaration doc.addFont('" + font.postScriptName + "')."); + } + + font.metadata = jsPDF.API.TTFFont.open(font.postScriptName, font.fontName, file, font.encoding); + font.metadata.Unicode = font.metadata.Unicode || { + encoding: {}, + kerning: {}, + widths: [] + }; + font.metadata.glyIdsUsed = [0]; + } else if (font.isStandardFont === false) { + throw new Error("Font does not exist in vFS, import fonts or remove declaration doc.addFont('" + font.postScriptName + "')."); + } + }]); // end of adding event handler + })(jsPDF, typeof self !== "undefined" && self || typeof global !== "undefined" && global || typeof window !== "undefined" && window || Function("return this")()); + + /** @license + * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com + * + * + * ==================================================================== + */ + + /** + * jsPDF SVG plugin + * + * @name svg + * @module + */ + (function (jsPDFAPI) { + /** + * Parses SVG XML and converts only some of the SVG elements into + * PDF elements. + * + * Supports: + * paths + * + * @name addSvg + * @public + * @function + * @param {string} SVG-Data as Text + * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {number} width of SVG (in units declared at inception of PDF document) + * @param {number} height of SVG (in units declared at inception of PDF document) + * @returns {Object} jsPDF-instance + */ + + jsPDFAPI.addSvg = function (svgtext, x, y, w, h) { + // 'this' is _jsPDF object returned when jsPDF is inited (new jsPDF()) + var undef; + + if (x === undef || y === undef) { + throw new Error("addSVG needs values for 'x' and 'y'"); + } + + function InjectCSS(cssbody, document) { + var styletag = document.createElement("style"); + styletag.type = "text/css"; + + if (styletag.styleSheet) { + // ie + styletag.styleSheet.cssText = cssbody; + } else { + // others + styletag.appendChild(document.createTextNode(cssbody)); + } + + document.getElementsByTagName("head")[0].appendChild(styletag); + } + + function createWorkerNode(document) { + var frameID = "childframe", + // Date.now().toString() + '_' + (Math.random() * 100).toString() + frame = document.createElement("iframe"); + InjectCSS(".jsPDF_sillysvg_iframe {display:none;position:absolute;}", document); + frame.name = frameID; + frame.setAttribute("width", 0); + frame.setAttribute("height", 0); + frame.setAttribute("frameborder", "0"); + frame.setAttribute("scrolling", "no"); + frame.setAttribute("seamless", "seamless"); + frame.setAttribute("class", "jsPDF_sillysvg_iframe"); + document.body.appendChild(frame); + return frame; + } + + function attachSVGToWorkerNode(svgtext, frame) { + var framedoc = (frame.contentWindow || frame.contentDocument).document; + framedoc.write(svgtext); + framedoc.close(); + return framedoc.getElementsByTagName("svg")[0]; + } + + function convertPathToPDFLinesArgs(path) { + // - starting coordinate pair + // - array of arrays of vector shifts (2-len for line, 6 len for bezier) + // - scale array [horizontal, vertical] ratios + // - style (stroke, fill, both) + + var x = parseFloat(path[1]), + y = parseFloat(path[2]), + vectors = [], + position = 3, + len = path.length; + + while (position < len) { + if (path[position] === "c") { + vectors.push([parseFloat(path[position + 1]), parseFloat(path[position + 2]), parseFloat(path[position + 3]), parseFloat(path[position + 4]), parseFloat(path[position + 5]), parseFloat(path[position + 6])]); + position += 7; + } else if (path[position] === "l") { + vectors.push([parseFloat(path[position + 1]), parseFloat(path[position + 2])]); + position += 3; + } else { + position += 1; + } + } + + return [x, y, vectors]; + } + + var workernode = createWorkerNode(document), + svgnode = attachSVGToWorkerNode(svgtext, workernode), + scale = [1, 1], + svgw = parseFloat(svgnode.getAttribute("width")), + svgh = parseFloat(svgnode.getAttribute("height")); + + if (svgw && svgh) { + // setting both w and h makes image stretch to size. + // this may distort the image, but fits your demanded size + if (w && h) { + scale = [w / svgw, h / svgh]; + } // if only one is set, that value is set as max and SVG + // is scaled proportionately. + else if (w) { + scale = [w / svgw, w / svgw]; + } else if (h) { + scale = [h / svgh, h / svgh]; + } + } + + var i, + l, + tmp, + linesargs, + items = svgnode.childNodes; + + for (i = 0, l = items.length; i < l; i++) { + tmp = items[i]; + + if (tmp.tagName && tmp.tagName.toUpperCase() === "PATH") { + linesargs = convertPathToPDFLinesArgs(tmp.getAttribute("d").split(" ")); // path start x coordinate + + linesargs[0] = linesargs[0] * scale[0] + x; // where x is upper left X of image + // path start y coordinate + + linesargs[1] = linesargs[1] * scale[1] + y; // where y is upper left Y of image + // the rest of lines are vectors. these will adjust with scale value auto. + + this.lines.call(this, linesargs[2], // lines + linesargs[0], // starting x + linesargs[1], // starting y + scale); + } + } // clean up + // workernode.parentNode.removeChild(workernode) + + + return this; + }; //fallback + + + jsPDFAPI.addSVG = jsPDFAPI.addSvg; + /** + * Parses SVG XML and saves it as image into the PDF. + * + * Depends on canvas-element and canvg + * + * @name addSvgAsImage + * @public + * @function + * @param {string} SVG-Data as Text + * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {number} width of SVG-Image (in units declared at inception of PDF document) + * @param {number} height of SVG-Image (in units declared at inception of PDF document) + * @param {string} alias of SVG-Image (if used multiple times) + * @param {string} compression of the generated JPEG, can have the values 'NONE', 'FAST', 'MEDIUM' and 'SLOW' + * @param {number} rotation of the image in degrees (0-359) + * + * @returns jsPDF jsPDF-instance + */ + + jsPDFAPI.addSvgAsImage = function (svg, x, y, w, h, alias, compression, rotation) { + if (isNaN(x) || isNaN(y)) { + console.error("jsPDF.addSvgAsImage: Invalid coordinates", arguments); + throw new Error("Invalid coordinates passed to jsPDF.addSvgAsImage"); + } + + if (isNaN(w) || isNaN(h)) { + console.error("jsPDF.addSvgAsImage: Invalid measurements", arguments); + throw new Error("Invalid measurements (width and/or height) passed to jsPDF.addSvgAsImage"); + } + + var canvas = document.createElement("canvas"); + canvas.width = w; + canvas.height = h; + var ctx = canvas.getContext("2d"); + ctx.fillStyle = "#fff"; /// set white fill style + + ctx.fillRect(0, 0, canvas.width, canvas.height); //load a svg snippet in the canvas with id = 'drawingArea' + + canvg(canvas, svg, { + ignoreMouse: true, + ignoreAnimation: true, + ignoreDimensions: true, + ignoreClear: true + }); + this.addImage(canvas.toDataURL("image/jpeg", 1.0), x, y, w, h, compression, rotation); + return this; + }; + })(jsPDF.API); + + /** + * @license + * ==================================================================== + * Copyright (c) 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br + * + * + * ==================================================================== + */ + + /** + * jsPDF total_pages plugin + * @name total_pages + * @module + */ + (function (jsPDFAPI) { + /** + * @name putTotalPages + * @function + * @param {string} pageExpression Regular Expression + * @returns {jsPDF} jsPDF-instance + */ + + jsPDFAPI.putTotalPages = function (pageExpression) { + + var replaceExpression = new RegExp(pageExpression, "g"); + + for (var n = 1; n <= this.internal.getNumberOfPages(); n++) { + for (var i = 0; i < this.internal.pages[n].length; i++) { + this.internal.pages[n][i] = this.internal.pages[n][i].replace(replaceExpression, this.internal.getNumberOfPages()); + } + } + + return this; + }; + })(jsPDF.API); + + /** + * jsPDF viewerPreferences Plugin + * @author Aras Abbasi (github.com/arasabbasi) + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * Adds the ability to set ViewerPreferences and by thus + * controlling the way the document is to be presented on the + * screen or in print. + * @name viewerpreferences + * @module + */ + (function (jsPDFAPI) { + /** + * Set the ViewerPreferences of the generated PDF + * + * @name viewerPreferences + * @function + * @public + * @param {Object} options Array with the ViewerPreferences
    + * Example: doc.viewerPreferences({"FitWindow":true});
    + *
    + * You can set following preferences:
    + *
    + * HideToolbar (boolean)
    + * Default value: false
    + *
    + * HideMenubar (boolean)
    + * Default value: false.
    + *
    + * HideWindowUI (boolean)
    + * Default value: false.
    + *
    + * FitWindow (boolean)
    + * Default value: false.
    + *
    + * CenterWindow (boolean)
    + * Default value: false
    + *
    + * DisplayDocTitle (boolean)
    + * Default value: false.
    + *
    + * NonFullScreenPageMode (string)
    + * Possible values: UseNone, UseOutlines, UseThumbs, UseOC
    + * Default value: UseNone
    + *
    + * Direction (string)
    + * Possible values: L2R, R2L
    + * Default value: L2R.
    + *
    + * ViewArea (string)
    + * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox
    + * Default value: CropBox.
    + *
    + * ViewClip (string)
    + * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox
    + * Default value: CropBox
    + *
    + * PrintArea (string)
    + * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox
    + * Default value: CropBox
    + *
    + * PrintClip (string)
    + * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox
    + * Default value: CropBox.
    + *
    + * PrintScaling (string)
    + * Possible values: AppDefault, None
    + * Default value: AppDefault.
    + *
    + * Duplex (string)
    + * Possible values: Simplex, DuplexFlipLongEdge, DuplexFlipShortEdge + * Default value: none
    + *
    + * PickTrayByPDFSize (boolean)
    + * Default value: false
    + *
    + * PrintPageRange (Array)
    + * Example: [[1,5], [7,9]]
    + * Default value: as defined by PDF viewer application
    + *
    + * NumCopies (Number)
    + * Possible values: 1, 2, 3, 4, 5
    + * Default value: 1
    + *
    + * For more information see the PDF Reference, sixth edition on Page 577 + * @param {boolean} doReset True to reset the settings + * @function + * @returns jsPDF jsPDF-instance + * @example + * var doc = new jsPDF() + * doc.text('This is a test', 10, 10) + * doc.viewerPreferences({'FitWindow': true}, true) + * doc.save("viewerPreferences.pdf") + * + * // Example printing 10 copies, using cropbox, and hiding UI. + * doc.viewerPreferences({ + * 'HideWindowUI': true, + * 'PrintArea': 'CropBox', + * 'NumCopies': 10 + * }) + */ + + jsPDFAPI.viewerPreferences = function (options, doReset) { + options = options || {}; + doReset = doReset || false; + var configuration; + var configurationTemplate = { + HideToolbar: { + defaultValue: false, + value: false, + type: "boolean", + explicitSet: false, + valueSet: [true, false], + pdfVersion: 1.3 + }, + HideMenubar: { + defaultValue: false, + value: false, + type: "boolean", + explicitSet: false, + valueSet: [true, false], + pdfVersion: 1.3 + }, + HideWindowUI: { + defaultValue: false, + value: false, + type: "boolean", + explicitSet: false, + valueSet: [true, false], + pdfVersion: 1.3 + }, + FitWindow: { + defaultValue: false, + value: false, + type: "boolean", + explicitSet: false, + valueSet: [true, false], + pdfVersion: 1.3 + }, + CenterWindow: { + defaultValue: false, + value: false, + type: "boolean", + explicitSet: false, + valueSet: [true, false], + pdfVersion: 1.3 + }, + DisplayDocTitle: { + defaultValue: false, + value: false, + type: "boolean", + explicitSet: false, + valueSet: [true, false], + pdfVersion: 1.4 + }, + NonFullScreenPageMode: { + defaultValue: "UseNone", + value: "UseNone", + type: "name", + explicitSet: false, + valueSet: ["UseNone", "UseOutlines", "UseThumbs", "UseOC"], + pdfVersion: 1.3 + }, + Direction: { + defaultValue: "L2R", + value: "L2R", + type: "name", + explicitSet: false, + valueSet: ["L2R", "R2L"], + pdfVersion: 1.3 + }, + ViewArea: { + defaultValue: "CropBox", + value: "CropBox", + type: "name", + explicitSet: false, + valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"], + pdfVersion: 1.4 + }, + ViewClip: { + defaultValue: "CropBox", + value: "CropBox", + type: "name", + explicitSet: false, + valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"], + pdfVersion: 1.4 + }, + PrintArea: { + defaultValue: "CropBox", + value: "CropBox", + type: "name", + explicitSet: false, + valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"], + pdfVersion: 1.4 + }, + PrintClip: { + defaultValue: "CropBox", + value: "CropBox", + type: "name", + explicitSet: false, + valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"], + pdfVersion: 1.4 + }, + PrintScaling: { + defaultValue: "AppDefault", + value: "AppDefault", + type: "name", + explicitSet: false, + valueSet: ["AppDefault", "None"], + pdfVersion: 1.6 + }, + Duplex: { + defaultValue: "", + value: "none", + type: "name", + explicitSet: false, + valueSet: ["Simplex", "DuplexFlipShortEdge", "DuplexFlipLongEdge", "none"], + pdfVersion: 1.7 + }, + PickTrayByPDFSize: { + defaultValue: false, + value: false, + type: "boolean", + explicitSet: false, + valueSet: [true, false], + pdfVersion: 1.7 + }, + PrintPageRange: { + defaultValue: "", + value: "", + type: "array", + explicitSet: false, + valueSet: null, + pdfVersion: 1.7 + }, + NumCopies: { + defaultValue: 1, + value: 1, + type: "integer", + explicitSet: false, + valueSet: null, + pdfVersion: 1.7 + } + }; + var configurationKeys = Object.keys(configurationTemplate); + var rangeArray = []; + var i = 0; + var j = 0; + var k = 0; + var isValid = true; + var method; + var value; + + function arrayContainsElement(array, element) { + var iterator; + var result = false; + + for (iterator = 0; iterator < array.length; iterator += 1) { + if (array[iterator] === element) { + result = true; + } + } + + return result; + } + + if (this.internal.viewerpreferences === undefined) { + this.internal.viewerpreferences = {}; + this.internal.viewerpreferences.configuration = JSON.parse(JSON.stringify(configurationTemplate)); + this.internal.viewerpreferences.isSubscribed = false; + } + + configuration = this.internal.viewerpreferences.configuration; + + if (options === "reset" || doReset === true) { + var len = configurationKeys.length; + + for (k = 0; k < len; k += 1) { + configuration[configurationKeys[k]].value = configuration[configurationKeys[k]].defaultValue; + configuration[configurationKeys[k]].explicitSet = false; + } + } + + if (_typeof(options) === "object") { + for (method in options) { + value = options[method]; + + if (arrayContainsElement(configurationKeys, method) && value !== undefined) { + if (configuration[method].type === "boolean" && typeof value === "boolean") { + configuration[method].value = value; + } else if (configuration[method].type === "name" && arrayContainsElement(configuration[method].valueSet, value)) { + configuration[method].value = value; + } else if (configuration[method].type === "integer" && Number.isInteger(value)) { + configuration[method].value = value; + } else if (configuration[method].type === "array") { + for (i = 0; i < value.length; i += 1) { + isValid = true; + + if (value[i].length === 1 && typeof value[i][0] === "number") { + rangeArray.push(String(value[i])); + } else if (value[i].length > 1) { + for (j = 0; j < value[i].length; j += 1) { + if (typeof value[i][j] !== "number") { + isValid = false; + } + } + + if (isValid === true) { + rangeArray.push(String(value[i].join("-"))); + } + } + } + + configuration[method].value = String(rangeArray); + } else { + configuration[method].value = configuration[method].defaultValue; + } + + configuration[method].explicitSet = true; + } + } + } + + if (this.internal.viewerpreferences.isSubscribed === false) { + this.internal.events.subscribe("putCatalog", function () { + var pdfDict = []; + var vPref; + + for (vPref in configuration) { + if (configuration[vPref].explicitSet === true) { + if (configuration[vPref].type === "name") { + pdfDict.push("/" + vPref + " /" + configuration[vPref].value); + } else { + pdfDict.push("/" + vPref + " " + configuration[vPref].value); + } + } + } + + if (pdfDict.length !== 0) { + this.internal.write("/ViewerPreferences\n<<\n" + pdfDict.join("\n") + "\n>>"); + } + }); + this.internal.viewerpreferences.isSubscribed = true; + } + + this.internal.viewerpreferences.configuration = configuration; + return this; + }; + })(jsPDF.API); + + /** ==================================================================== + * jsPDF XMP metadata plugin + * Copyright (c) 2016 Jussi Utunen, u-jussi@suomi24.fi + * + * + * ==================================================================== + */ + + /*global jsPDF */ + + /** + * @name xmp_metadata + * @module + */ + (function (jsPDFAPI) { + + var xmpmetadata = ""; + var xmpnamespaceuri = ""; + var metadata_object_number = ""; + /** + * Adds XMP formatted metadata to PDF + * + * @name addMetadata + * @function + * @param {String} metadata The actual metadata to be added. The metadata shall be stored as XMP simple value. Note that if the metadata string contains XML markup characters "<", ">" or "&", those characters should be written using XML entities. + * @param {String} namespaceuri Sets the namespace URI for the metadata. Last character should be slash or hash. + * @returns {jsPDF} jsPDF-instance + */ + + jsPDFAPI.addMetadata = function (metadata, namespaceuri) { + xmpnamespaceuri = namespaceuri || "http://jspdf.default.namespaceuri/"; //The namespace URI for an XMP name shall not be empty + + xmpmetadata = metadata; + this.internal.events.subscribe("postPutResources", function () { + if (!xmpmetadata) { + metadata_object_number = ""; + } else { + var xmpmeta_beginning = ''; + var rdf_beginning = ''; + var rdf_ending = ""; + var xmpmeta_ending = ""; + var utf8_xmpmeta_beginning = unescape(encodeURIComponent(xmpmeta_beginning)); + var utf8_rdf_beginning = unescape(encodeURIComponent(rdf_beginning)); + var utf8_metadata = unescape(encodeURIComponent(xmpmetadata)); + var utf8_rdf_ending = unescape(encodeURIComponent(rdf_ending)); + var utf8_xmpmeta_ending = unescape(encodeURIComponent(xmpmeta_ending)); + var total_len = utf8_rdf_beginning.length + utf8_metadata.length + utf8_rdf_ending.length + utf8_xmpmeta_beginning.length + utf8_xmpmeta_ending.length; + metadata_object_number = this.internal.newObject(); + this.internal.write("<< /Type /Metadata /Subtype /XML /Length " + total_len + " >>"); + this.internal.write("stream"); + this.internal.write(utf8_xmpmeta_beginning + utf8_rdf_beginning + utf8_metadata + utf8_rdf_ending + utf8_xmpmeta_ending); + this.internal.write("endstream"); + this.internal.write("endobj"); + } + }); + this.internal.events.subscribe("putCatalog", function () { + if (metadata_object_number) { + this.internal.write("/Metadata " + metadata_object_number + " 0 R"); + } + }); + return this; + }; + })(jsPDF.API); + + /** + * @name utf8 + * @module + */ + (function (jsPDF, global) { + + var jsPDFAPI = jsPDF.API; + /**************************************************/ + + /* function : toHex */ + + /* comment : Replace str with a hex string. */ + + /**************************************************/ + + function toHex(str) { + var hex = ""; + + for (var i = 0; i < str.length; i++) { + hex += "" + str.charCodeAt(i).toString(16); + } + + return hex; + } + /***************************************************************************************************/ + + /* function : pdfEscape16 */ + + /* comment : The character id of a 2-byte string is converted to a hexadecimal number by obtaining */ + + /* the corresponding glyph id and width, and then adding padding to the string. */ + + /***************************************************************************************************/ + + + var pdfEscape16 = jsPDFAPI.pdfEscape16 = function (text, font) { + var widths = font.metadata.Unicode.widths; + var padz = ["", "0", "00", "000", "0000"]; + var ar = [""]; + + for (var i = 0, l = text.length, t; i < l; ++i) { + t = font.metadata.characterToGlyph(text.charCodeAt(i)); + font.metadata.glyIdsUsed.push(t); + font.metadata.toUnicode[t] = text.charCodeAt(i); + + if (widths.indexOf(t) == -1) { + widths.push(t); + widths.push([parseInt(font.metadata.widthOfGlyph(t), 10)]); + } + + if (t == "0") { + //Spaces are not allowed in cmap. + return ar.join(""); + } else { + t = t.toString(16); + ar.push(padz[4 - t.length], t); + } + } + + return ar.join(""); + }; + + var toUnicodeCmap = function toUnicodeCmap(map) { + var code, codes, range, unicode, unicodeMap, _i, _len; + + unicodeMap = "/CIDInit /ProcSet findresource begin\n12 dict begin\nbegincmap\n/CIDSystemInfo <<\n /Registry (Adobe)\n /Ordering (UCS)\n /Supplement 0\n>> def\n/CMapName /Adobe-Identity-UCS def\n/CMapType 2 def\n1 begincodespacerange\n<0000>\nendcodespacerange"; + codes = Object.keys(map).sort(function (a, b) { + return a - b; + }); + range = []; + + for (_i = 0, _len = codes.length; _i < _len; _i++) { + code = codes[_i]; + + if (range.length >= 100) { + unicodeMap += "\n" + range.length + " beginbfchar\n" + range.join("\n") + "\nendbfchar"; + range = []; + } + + unicode = ("0000" + map[code].toString(16)).slice(-4); + code = ("0000" + (+code).toString(16)).slice(-4); + range.push("<" + code + "><" + unicode + ">"); + } + + if (range.length) { + unicodeMap += "\n" + range.length + " beginbfchar\n" + range.join("\n") + "\nendbfchar\n"; + } + + unicodeMap += "endcmap\nCMapName currentdict /CMap defineresource pop\nend\nend"; + return unicodeMap; + }; + + var identityHFunction = function identityHFunction(font, out, newObject, putStream) { + if (font.metadata instanceof jsPDF.API.TTFFont && font.encoding === "Identity-H") { + //Tag with Identity-H + var widths = font.metadata.Unicode.widths; + var data = font.metadata.subset.encode(font.metadata.glyIdsUsed, 1); + var pdfOutput = data; + var pdfOutput2 = ""; + + for (var i = 0; i < pdfOutput.length; i++) { + pdfOutput2 += String.fromCharCode(pdfOutput[i]); + } + + var fontTable = newObject(); + out("<<"); + out("/Length " + pdfOutput2.length); + out("/Length1 " + pdfOutput2.length); + out(">>"); + putStream(pdfOutput2); + out("endobj"); + var cmap = newObject(); + var cmapData = toUnicodeCmap(font.metadata.toUnicode); + out("<<"); + out("/Length " + cmapData.length); + out("/Length1 " + cmapData.length); + out(">>"); + putStream(cmapData); + out("endobj"); + var fontDescriptor = newObject(); + out("<<"); + out("/Type /FontDescriptor"); + out("/FontName /" + font.fontName); + out("/FontFile2 " + fontTable + " 0 R"); + out("/FontBBox " + jsPDF.API.PDFObject.convert(font.metadata.bbox)); + out("/Flags " + font.metadata.flags); + out("/StemV " + font.metadata.stemV); + out("/ItalicAngle " + font.metadata.italicAngle); + out("/Ascent " + font.metadata.ascender); + out("/Descent " + font.metadata.decender); + out("/CapHeight " + font.metadata.capHeight); + out(">>"); + out("endobj"); + var DescendantFont = newObject(); + out("<<"); + out("/Type /Font"); + out("/BaseFont /" + font.fontName); + out("/FontDescriptor " + fontDescriptor + " 0 R"); + out("/W " + jsPDF.API.PDFObject.convert(widths)); + out("/CIDToGIDMap /Identity"); + out("/DW 1000"); + out("/Subtype /CIDFontType2"); + out("/CIDSystemInfo"); + out("<<"); + out("/Supplement 0"); + out("/Registry (Adobe)"); + out("/Ordering (" + font.encoding + ")"); + out(">>"); + out(">>"); + out("endobj"); + font.objectNumber = newObject(); + out("<<"); + out("/Type /Font"); + out("/Subtype /Type0"); + out("/ToUnicode " + cmap + " 0 R"); + out("/BaseFont /" + font.fontName); + out("/Encoding /" + font.encoding); + out("/DescendantFonts [" + DescendantFont + " 0 R]"); + out(">>"); + out("endobj"); + font.isAlreadyPutted = true; + } + }; + + jsPDFAPI.events.push(["putFont", function (args) { + identityHFunction(args.font, args.out, args.newObject, args.putStream); + }]); + + var winAnsiEncodingFunction = function winAnsiEncodingFunction(font, out, newObject, putStream) { + if (font.metadata instanceof jsPDF.API.TTFFont && font.encoding === "WinAnsiEncoding") { + //Tag with WinAnsi encoding + var widths = font.metadata.Unicode.widths; + var data = font.metadata.rawData; + var pdfOutput = data; + var pdfOutput2 = ""; + + for (var i = 0; i < pdfOutput.length; i++) { + pdfOutput2 += String.fromCharCode(pdfOutput[i]); + } + + var fontTable = newObject(); + putStream({ + data: pdfOutput2, + addLength1: true + }); + out("endobj"); + var cmap = newObject(); + var cmapData = toUnicodeCmap(font.metadata.toUnicode); + putStream({ + data: cmapData, + addLength1: true + }); + out("endobj"); + var fontDescriptor = newObject(); + out("<<"); + out("/Descent " + font.metadata.decender); + out("/CapHeight " + font.metadata.capHeight); + out("/StemV " + font.metadata.stemV); + out("/Type /FontDescriptor"); + out("/FontFile2 " + fontTable + " 0 R"); + out("/Flags 96"); + out("/FontBBox " + jsPDF.API.PDFObject.convert(font.metadata.bbox)); + out("/FontName /" + font.fontName); + out("/ItalicAngle " + font.metadata.italicAngle); + out("/Ascent " + font.metadata.ascender); + out(">>"); + out("endobj"); + font.objectNumber = newObject(); + + for (var i = 0; i < font.metadata.hmtx.widths.length; i++) { + font.metadata.hmtx.widths[i] = parseInt(font.metadata.hmtx.widths[i] * (1000 / font.metadata.head.unitsPerEm)); //Change the width of Em units to Point units. + } + + out("<>"); + out("endobj"); + font.isAlreadyPutted = true; + } + }; + + jsPDFAPI.events.push(["putFont", function (args) { + winAnsiEncodingFunction(args.font, args.out, args.newObject, args.putStream); + }]); + + var utf8TextFunction = function utf8TextFunction(args) { + var text = args.text || ""; + var x = args.x; + var y = args.y; + var options = args.options || {}; + var mutex = args.mutex || {}; + var pdfEscape = mutex.pdfEscape; + var activeFontKey = mutex.activeFontKey; + var fonts = mutex.fonts; + var key, + fontSize = mutex.activeFontSize; + var str = "", + s = 0, + cmapConfirm; + var strText = ""; + var key = activeFontKey; + var encoding = fonts[key].encoding; + + if (fonts[key].encoding !== "Identity-H") { + return { + text: text, + x: x, + y: y, + options: options, + mutex: mutex + }; + } + strText = text; + key = activeFontKey; + + if (Object.prototype.toString.call(text) === "[object Array]") { + strText = text[0]; + } + + for (s = 0; s < strText.length; s += 1) { + if (fonts[key].metadata.hasOwnProperty("cmap")) { + cmapConfirm = fonts[key].metadata.cmap.unicode.codeMap[strText[s].charCodeAt(0)]; + /* + if (Object.prototype.toString.call(text) === '[object Array]') { + var i = 0; + // for (i = 0; i < text.length; i += 1) { + if (Object.prototype.toString.call(text[s]) === '[object Array]') { + cmapConfirm = fonts[key].metadata.cmap.unicode.codeMap[strText[s][0].charCodeAt(0)]; //Make sure the cmap has the corresponding glyph id + } else { + + } + //} + + } else { + cmapConfirm = fonts[key].metadata.cmap.unicode.codeMap[strText[s].charCodeAt(0)]; //Make sure the cmap has the corresponding glyph id + }*/ + } + + if (!cmapConfirm) { + if (strText[s].charCodeAt(0) < 256 && fonts[key].metadata.hasOwnProperty("Unicode")) { + str += strText[s]; + } else { + str += ""; + } + } else { + str += strText[s]; + } + } + + var result = ""; + + if (parseInt(key.slice(1)) < 14 || encoding === "WinAnsiEncoding") { + //For the default 13 font + result = toHex(pdfEscape(str, key)); + } else if (encoding === "Identity-H") { + result = pdfEscape16(str, fonts[key]); + } + + mutex.isHex = true; + return { + text: result, + x: x, + y: y, + options: options, + mutex: mutex + }; + }; + + var utf8EscapeFunction = function utf8EscapeFunction(parms) { + var text = parms.text || "", + x = parms.x, + y = parms.y, + options = parms.options, + mutex = parms.mutex; + var lang = options.lang; + var tmpText = []; + var args = { + text: text, + x: x, + y: y, + options: options, + mutex: mutex + }; + + if (Object.prototype.toString.call(text) === "[object Array]") { + var i = 0; + + for (i = 0; i < text.length; i += 1) { + if (Object.prototype.toString.call(text[i]) === "[object Array]") { + if (text[i].length === 3) { + tmpText.push([utf8TextFunction(Object.assign({}, args, { + text: text[i][0] + })).text, text[i][1], text[i][2]]); + } else { + tmpText.push(utf8TextFunction(Object.assign({}, args, { + text: text[i] + })).text); + } + } else { + tmpText.push(utf8TextFunction(Object.assign({}, args, { + text: text[i] + })).text); + } + } + + parms.text = tmpText; + } else { + parms.text = utf8TextFunction(Object.assign({}, args, { + text: text + })).text; + } + }; + + jsPDFAPI.events.push(["postProcessText", utf8EscapeFunction]); + })(jsPDF, typeof self !== "undefined" && self || typeof global !== "undefined" && global || typeof window !== "undefined" && window || Function("return this")()); + + /** + * jsPDF virtual FileSystem functionality + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * Use the vFS to handle files + * + * @name vFS + * @module + */ + (function (jsPDFAPI) { + + var vFS = {}; + /** + * Check if the file exists in the vFS + * + * @name existsFileInVFS + * @function + * @param {string} Possible filename in the vFS. + * @returns {boolean} + * @example + * doc.existsFileInVFS("someFile.txt"); + */ + + jsPDFAPI.existsFileInVFS = function (filename) { + return vFS.hasOwnProperty(filename); + }; + /** + * Add a file to the vFS + * + * @name addFileToVFS + * @function + * @param {string} filename The name of the file which should be added. + * @param {string} filecontent The content of the file. + * @returns {jsPDF} + * @example + * doc.addFileToVFS("someFile.txt", "BADFACE1"); + */ + + + jsPDFAPI.addFileToVFS = function (filename, filecontent) { + vFS[filename] = filecontent; + return this; + }; + /** + * Get the file from the vFS + * + * @name getFileFromVFS + * @function + * @returns {string} The name of the file which gets requested. + * @example + * doc.getFileFromVFS("someFile.txt"); + */ + + + jsPDFAPI.getFileFromVFS = function (filename) { + if (vFS.hasOwnProperty(filename)) { + return vFS[filename]; + } + + return null; + }; + })(jsPDF.API); + + /* Blob.js + * A Blob implementation. + * 2014-07-24 + * + * By Eli Grey, http://eligrey.com + * By Devin Samarin, https://github.com/dsamarin + * License: X11/MIT + * See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md + */ + + /*global self, unescape */ + + /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, + plusplus: true */ + + /*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */ + (function (view) { + + view.URL = view.URL || view.webkitURL; + + if (view.Blob && view.URL) { + try { + new Blob(); + return; + } catch (e) {} + } // Internally we use a BlobBuilder implementation to base Blob off of + // in order to support older browsers that only have BlobBuilder + + + var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || function (view) { + var get_class = function (object) { + return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1]; + }, + FakeBlobBuilder = function BlobBuilder() { + this.data = []; + }, + FakeBlob = function Blob(data, type, encoding) { + this.data = data; + this.size = data.length; + this.type = type; + this.encoding = encoding; + }, + FBB_proto = FakeBlobBuilder.prototype, + FB_proto = FakeBlob.prototype, + FileReaderSync = view.FileReaderSync, + FileException = function (type) { + this.code = this[this.name = type]; + }, + file_ex_codes = ("NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR").split(" "), + file_ex_code = file_ex_codes.length, + real_URL = view.URL || view.webkitURL || view, + real_create_object_URL = real_URL.createObjectURL, + real_revoke_object_URL = real_URL.revokeObjectURL, + URL = real_URL, + btoa = view.btoa, + atob = view.atob, + ArrayBuffer = view.ArrayBuffer, + Uint8Array = view.Uint8Array, + origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/; + + FakeBlob.fake = FB_proto.fake = true; + + while (file_ex_code--) { + FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1; + } // Polyfill URL + + + if (!real_URL.createObjectURL) { + URL = view.URL = function (uri) { + var uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a"), + uri_origin; + uri_info.href = uri; + + if (!("origin" in uri_info)) { + if (uri_info.protocol.toLowerCase() === "data:") { + uri_info.origin = null; + } else { + uri_origin = uri.match(origin); + uri_info.origin = uri_origin && uri_origin[1]; + } + } + + return uri_info; + }; + } + + URL.createObjectURL = function (blob) { + var type = blob.type, + data_URI_header; + + if (type === null) { + type = "application/octet-stream"; + } + + if (blob instanceof FakeBlob) { + data_URI_header = "data:" + type; + + if (blob.encoding === "base64") { + return data_URI_header + ";base64," + blob.data; + } else if (blob.encoding === "URI") { + return data_URI_header + "," + decodeURIComponent(blob.data); + } + + if (btoa) { + return data_URI_header + ";base64," + btoa(blob.data); + } else { + return data_URI_header + "," + encodeURIComponent(blob.data); + } + } else if (real_create_object_URL) { + return real_create_object_URL.call(real_URL, blob); + } + }; + + URL.revokeObjectURL = function (object_URL) { + if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) { + real_revoke_object_URL.call(real_URL, object_URL); + } + }; + + FBB_proto.append = function (data + /*, endings*/ + ) { + var bb = this.data; // decode data to a binary string + + if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) { + var str = "", + buf = new Uint8Array(data), + i = 0, + buf_len = buf.length; + + for (; i < buf_len; i++) { + str += String.fromCharCode(buf[i]); + } + + bb.push(str); + } else if (get_class(data) === "Blob" || get_class(data) === "File") { + if (FileReaderSync) { + var fr = new FileReaderSync(); + bb.push(fr.readAsBinaryString(data)); + } else { + // async FileReader won't work as BlobBuilder is sync + throw new FileException("NOT_READABLE_ERR"); + } + } else if (data instanceof FakeBlob) { + if (data.encoding === "base64" && atob) { + bb.push(atob(data.data)); + } else if (data.encoding === "URI") { + bb.push(decodeURIComponent(data.data)); + } else if (data.encoding === "raw") { + bb.push(data.data); + } + } else { + if (typeof data !== "string") { + data += ""; // convert unsupported types to strings + } // decode UTF-16 to binary string + + + bb.push(unescape(encodeURIComponent(data))); + } + }; + + FBB_proto.getBlob = function (type) { + if (!arguments.length) { + type = null; + } + + return new FakeBlob(this.data.join(""), type, "raw"); + }; + + FBB_proto.toString = function () { + return "[object BlobBuilder]"; + }; + + FB_proto.slice = function (start, end, type) { + var args = arguments.length; + + if (args < 3) { + type = null; + } + + return new FakeBlob(this.data.slice(start, args > 1 ? end : this.data.length), type, this.encoding); + }; + + FB_proto.toString = function () { + return "[object Blob]"; + }; + + FB_proto.close = function () { + this.size = 0; + delete this.data; + }; + + return FakeBlobBuilder; + }(view); + + view.Blob = function (blobParts, options) { + var type = options ? options.type || "" : ""; + var builder = new BlobBuilder(); + + if (blobParts) { + for (var i = 0, len = blobParts.length; i < len; i++) { + if (Uint8Array && blobParts[i] instanceof Uint8Array) { + builder.append(blobParts[i].buffer); + } else { + builder.append(blobParts[i]); + } + } + } + + var blob = builder.getBlob(type); + + if (!blob.slice && blob.webkitSlice) { + blob.slice = blob.webkitSlice; + } + + return blob; + }; + + var getPrototypeOf = Object.getPrototypeOf || function (object) { + return object.__proto__; + }; + + view.Blob.prototype = getPrototypeOf(new view.Blob()); + })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || window.content || window); + + /* FileSaver.js + * A saveAs() FileSaver implementation. + * 1.3.2 + * 2016-06-16 18:25:19 + * + * By Eli Grey, http://eligrey.com + * License: MIT + * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md + */ + + /*global self */ + + /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ + + /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ + var saveAs = saveAs || function (view) { + + if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { + return; + } + + var doc = view.document // only get URL when necessary in case Blob.js hasn't overridden it yet + , + get_URL = function () { + return view.URL || view.webkitURL || view; + }, + save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"), + can_use_save_link = "download" in save_link, + click = function (node) { + var event = new MouseEvent("click"); + node.dispatchEvent(event); + }, + is_safari = /constructor/i.test(view.HTMLElement) || view.safari, + is_chrome_ios = /CriOS\/[\d]+/.test(navigator.userAgent), + throw_outside = function (ex) { + (view.setImmediate || view.setTimeout)(function () { + throw ex; + }, 0); + }, + force_saveable_type = "application/octet-stream" // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to + , + arbitrary_revoke_timeout = 1000 * 40 // in ms + , + revoke = function (file) { + var revoker = function () { + if (typeof file === "string") { + // file is an object URL + get_URL().revokeObjectURL(file); + } else { + // file is a File + file.remove(); + } + }; + + setTimeout(revoker, arbitrary_revoke_timeout); + }, + dispatch = function (filesaver, event_types, event) { + event_types = [].concat(event_types); + var i = event_types.length; + + while (i--) { + var listener = filesaver["on" + event_types[i]]; + + if (typeof listener === "function") { + try { + listener.call(filesaver, event || filesaver); + } catch (ex) { + throw_outside(ex); + } + } + } + }, + auto_bom = function (blob) { + // prepend BOM for UTF-8 XML and text/* types (including HTML) + // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF + if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { + return new Blob([String.fromCharCode(0xFEFF), blob], { + type: blob.type + }); + } + + return blob; + }, + FileSaver = function (blob, name, no_auto_bom) { + if (!no_auto_bom) { + blob = auto_bom(blob); + } // First try a.download, then web filesystem, then object URLs + + + var filesaver = this, + type = blob.type, + force = type === force_saveable_type, + object_url, + dispatch_all = function () { + dispatch(filesaver, "writestart progress write writeend".split(" ")); + } // on any filesys errors revert to saving with object URLs + , + fs_error = function () { + if ((is_chrome_ios || force && is_safari) && view.FileReader) { + // Safari doesn't allow downloading of blob urls + var reader = new FileReader(); + + reader.onloadend = function () { + var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;'); + var popup = view.open(url, '_blank'); + if (!popup) view.location.href = url; + url = undefined; // release reference before dispatching + + filesaver.readyState = filesaver.DONE; + dispatch_all(); + }; + + reader.readAsDataURL(blob); + filesaver.readyState = filesaver.INIT; + return; + } // don't create more object URLs than needed + + + if (!object_url) { + object_url = get_URL().createObjectURL(blob); + } + + if (force) { + view.location.href = object_url; + } else { + var opened = view.open(object_url, "_blank"); + + if (!opened) { + // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html + view.location.href = object_url; + } + } + + filesaver.readyState = filesaver.DONE; + dispatch_all(); + revoke(object_url); + }; + + filesaver.readyState = filesaver.INIT; + + if (can_use_save_link) { + object_url = get_URL().createObjectURL(blob); + setTimeout(function () { + save_link.href = object_url; + save_link.download = name; + click(save_link); + dispatch_all(); + revoke(object_url); + filesaver.readyState = filesaver.DONE; + }); + return; + } + + fs_error(); + }, + FS_proto = FileSaver.prototype, + saveAs = function (blob, name, no_auto_bom) { + return new FileSaver(blob, name || blob.name || "download", no_auto_bom); + }; // IE 10+ (native saveAs) + + + if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { + return function (blob, name, no_auto_bom) { + name = name || blob.name || "download"; + + if (!no_auto_bom) { + blob = auto_bom(blob); + } + + return navigator.msSaveOrOpenBlob(blob, name); + }; + } + + FS_proto.abort = function () {}; + + FS_proto.readyState = FS_proto.INIT = 0; + FS_proto.WRITING = 1; + FS_proto.DONE = 2; + FS_proto.error = FS_proto.onwritestart = FS_proto.onprogress = FS_proto.onwrite = FS_proto.onabort = FS_proto.onerror = FS_proto.onwriteend = null; + return saveAs; + }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || window.content); // `self` is undefined in Firefox for Android content script context + // while `this` is nsIContentFrameMessageManager + // with an attribute `content` that corresponds to the window + + + if (typeof module !== "undefined" && module.exports) { + module.exports.saveAs = saveAs; + } else if (typeof define !== "undefined" && define !== null && define.amd !== null) { + define("FileSaver.js", function () { + return saveAs; + }); + } + + // (c) Dean McNamee , 2013. + // + // https://github.com/deanm/omggif + // + // + // + // omggif is a JavaScript implementation of a GIF 89a encoder and decoder, + // including animation and compression. It does not rely on any specific + // underlying system, so should run in the browser, Node, or Plask. + function GifWriter(buf, width, height, gopts) { + var p = 0; + var gopts = gopts === undefined ? {} : gopts; + var loop_count = gopts.loop === undefined ? null : gopts.loop; + var global_palette = gopts.palette === undefined ? null : gopts.palette; + if (width <= 0 || height <= 0 || width > 65535 || height > 65535) throw "Width/Height invalid."; + + function check_palette_and_num_colors(palette) { + var num_colors = palette.length; + if (num_colors < 2 || num_colors > 256 || num_colors & num_colors - 1) throw "Invalid code/color length, must be power of 2 and 2 .. 256."; + return num_colors; + } // - Header. + + + buf[p++] = 0x47; + buf[p++] = 0x49; + buf[p++] = 0x46; // GIF + + buf[p++] = 0x38; + buf[p++] = 0x39; + buf[p++] = 0x61; // 89a + // Handling of Global Color Table (palette) and background index. + + var gp_num_colors_pow2 = 0; + var background = 0; + + if (global_palette !== null) { + var gp_num_colors = check_palette_and_num_colors(global_palette); + + while (gp_num_colors >>= 1) ++gp_num_colors_pow2; + + gp_num_colors = 1 << gp_num_colors_pow2; + --gp_num_colors_pow2; + + if (gopts.background !== undefined) { + background = gopts.background; + if (background >= gp_num_colors) throw "Background index out of range."; // The GIF spec states that a background index of 0 should be ignored, so + // this is probably a mistake and you really want to set it to another + // slot in the palette. But actually in the end most browsers, etc end + // up ignoring this almost completely (including for dispose background). + + if (background === 0) throw "Background index explicitly passed as 0."; + } + } // - Logical Screen Descriptor. + // NOTE(deanm): w/h apparently ignored by implementations, but set anyway. + + + buf[p++] = width & 0xff; + buf[p++] = width >> 8 & 0xff; + buf[p++] = height & 0xff; + buf[p++] = height >> 8 & 0xff; // NOTE: Indicates 0-bpp original color resolution (unused?). + + buf[p++] = (global_palette !== null ? 0x80 : 0) | // Global Color Table Flag. + gp_num_colors_pow2; // NOTE: No sort flag (unused?). + + buf[p++] = background; // Background Color Index. + + buf[p++] = 0; // Pixel aspect ratio (unused?). + // - Global Color Table + + if (global_palette !== null) { + for (var i = 0, il = global_palette.length; i < il; ++i) { + var rgb = global_palette[i]; + buf[p++] = rgb >> 16 & 0xff; + buf[p++] = rgb >> 8 & 0xff; + buf[p++] = rgb & 0xff; + } + } + + if (loop_count !== null) { + // Netscape block for looping. + if (loop_count < 0 || loop_count > 65535) throw "Loop count invalid."; // Extension code, label, and length. + + buf[p++] = 0x21; + buf[p++] = 0xff; + buf[p++] = 0x0b; // NETSCAPE2.0 + + buf[p++] = 0x4e; + buf[p++] = 0x45; + buf[p++] = 0x54; + buf[p++] = 0x53; + buf[p++] = 0x43; + buf[p++] = 0x41; + buf[p++] = 0x50; + buf[p++] = 0x45; + buf[p++] = 0x32; + buf[p++] = 0x2e; + buf[p++] = 0x30; // Sub-block + + buf[p++] = 0x03; + buf[p++] = 0x01; + buf[p++] = loop_count & 0xff; + buf[p++] = loop_count >> 8 & 0xff; + buf[p++] = 0x00; // Terminator. + } + + var ended = false; + + this.addFrame = function (x, y, w, h, indexed_pixels, opts) { + if (ended === true) { + --p; + ended = false; + } // Un-end. + + + opts = opts === undefined ? {} : opts; // TODO(deanm): Bounds check x, y. Do they need to be within the virtual + // canvas width/height, I imagine? + + if (x < 0 || y < 0 || x > 65535 || y > 65535) throw "x/y invalid."; + if (w <= 0 || h <= 0 || w > 65535 || h > 65535) throw "Width/Height invalid."; + if (indexed_pixels.length < w * h) throw "Not enough pixels for the frame size."; + var using_local_palette = true; + var palette = opts.palette; + + if (palette === undefined || palette === null) { + using_local_palette = false; + palette = global_palette; + } + + if (palette === undefined || palette === null) throw "Must supply either a local or global palette."; + var num_colors = check_palette_and_num_colors(palette); // Compute the min_code_size (power of 2), destroying num_colors. + + var min_code_size = 0; + + while (num_colors >>= 1) ++min_code_size; + + num_colors = 1 << min_code_size; // Now we can easily get it back. + + var delay = opts.delay === undefined ? 0 : opts.delay; // From the spec: + // 0 - No disposal specified. The decoder is + // not required to take any action. + // 1 - Do not dispose. The graphic is to be left + // in place. + // 2 - Restore to background color. The area used by the + // graphic must be restored to the background color. + // 3 - Restore to previous. The decoder is required to + // restore the area overwritten by the graphic with + // what was there prior to rendering the graphic. + // 4-7 - To be defined. + // NOTE(deanm): Dispose background doesn't really work, apparently most + // browsers ignore the background palette index and clear to transparency. + + var disposal = opts.disposal === undefined ? 0 : opts.disposal; + if (disposal < 0 || disposal > 3) // 4-7 is reserved. + throw "Disposal out of range."; + var use_transparency = false; + var transparent_index = 0; + + if (opts.transparent !== undefined && opts.transparent !== null) { + use_transparency = true; + transparent_index = opts.transparent; + if (transparent_index < 0 || transparent_index >= num_colors) throw "Transparent color index."; + } + + if (disposal !== 0 || use_transparency || delay !== 0) { + // - Graphics Control Extension + buf[p++] = 0x21; + buf[p++] = 0xf9; // Extension / Label. + + buf[p++] = 4; // Byte size. + + buf[p++] = disposal << 2 | (use_transparency === true ? 1 : 0); + buf[p++] = delay & 0xff; + buf[p++] = delay >> 8 & 0xff; + buf[p++] = transparent_index; // Transparent color index. + + buf[p++] = 0; // Block Terminator. + } // - Image Descriptor + + + buf[p++] = 0x2c; // Image Seperator. + + buf[p++] = x & 0xff; + buf[p++] = x >> 8 & 0xff; // Left. + + buf[p++] = y & 0xff; + buf[p++] = y >> 8 & 0xff; // Top. + + buf[p++] = w & 0xff; + buf[p++] = w >> 8 & 0xff; + buf[p++] = h & 0xff; + buf[p++] = h >> 8 & 0xff; // NOTE: No sort flag (unused?). + // TODO(deanm): Support interlace. + + buf[p++] = using_local_palette === true ? 0x80 | min_code_size - 1 : 0; // - Local Color Table + + if (using_local_palette === true) { + for (var i = 0, il = palette.length; i < il; ++i) { + var rgb = palette[i]; + buf[p++] = rgb >> 16 & 0xff; + buf[p++] = rgb >> 8 & 0xff; + buf[p++] = rgb & 0xff; + } + } + + p = GifWriterOutputLZWCodeStream(buf, p, min_code_size < 2 ? 2 : min_code_size, indexed_pixels); + }; + + this.end = function () { + if (ended === false) { + buf[p++] = 0x3b; // Trailer. + + ended = true; + } + + return p; + }; + } // Main compression routine, palette indexes -> LZW code stream. + // |index_stream| must have at least one entry. + + + function GifWriterOutputLZWCodeStream(buf, p, min_code_size, index_stream) { + buf[p++] = min_code_size; + var cur_subblock = p++; // Pointing at the length field. + + var clear_code = 1 << min_code_size; + var code_mask = clear_code - 1; + var eoi_code = clear_code + 1; + var next_code = eoi_code + 1; + var cur_code_size = min_code_size + 1; // Number of bits per code. + + var cur_shift = 0; // We have at most 12-bit codes, so we should have to hold a max of 19 + // bits here (and then we would write out). + + var cur = 0; + + function emit_bytes_to_buffer(bit_block_size) { + while (cur_shift >= bit_block_size) { + buf[p++] = cur & 0xff; + cur >>= 8; + cur_shift -= 8; + + if (p === cur_subblock + 256) { + // Finished a subblock. + buf[cur_subblock] = 255; + cur_subblock = p++; + } + } + } + + function emit_code(c) { + cur |= c << cur_shift; + cur_shift += cur_code_size; + emit_bytes_to_buffer(8); + } // I am not an expert on the topic, and I don't want to write a thesis. + // However, it is good to outline here the basic algorithm and the few data + // structures and optimizations here that make this implementation fast. + // The basic idea behind LZW is to build a table of previously seen runs + // addressed by a short id (herein called output code). All data is + // referenced by a code, which represents one or more values from the + // original input stream. All input bytes can be referenced as the same + // value as an output code. So if you didn't want any compression, you + // could more or less just output the original bytes as codes (there are + // some details to this, but it is the idea). In order to achieve + // compression, values greater then the input range (codes can be up to + // 12-bit while input only 8-bit) represent a sequence of previously seen + // inputs. The decompressor is able to build the same mapping while + // decoding, so there is always a shared common knowledge between the + // encoding and decoder, which is also important for "timing" aspects like + // how to handle variable bit width code encoding. + // + // One obvious but very important consequence of the table system is there + // is always a unique id (at most 12-bits) to map the runs. 'A' might be + // 4, then 'AA' might be 10, 'AAA' 11, 'AAAA' 12, etc. This relationship + // can be used for an effecient lookup strategy for the code mapping. We + // need to know if a run has been seen before, and be able to map that run + // to the output code. Since we start with known unique ids (input bytes), + // and then from those build more unique ids (table entries), we can + // continue this chain (almost like a linked list) to always have small + // integer values that represent the current byte chains in the encoder. + // This means instead of tracking the input bytes (AAAABCD) to know our + // current state, we can track the table entry for AAAABC (it is guaranteed + // to exist by the nature of the algorithm) and the next character D. + // Therefor the tuple of (table_entry, byte) is guaranteed to also be + // unique. This allows us to create a simple lookup key for mapping input + // sequences to codes (table indices) without having to store or search + // any of the code sequences. So if 'AAAA' has a table entry of 12, the + // tuple of ('AAAA', K) for any input byte K will be unique, and can be our + // key. This leads to a integer value at most 20-bits, which can always + // fit in an SMI value and be used as a fast sparse array / object key. + // Output code for the current contents of the index buffer. + + + var ib_code = index_stream[0] & code_mask; // Load first input index. + + var code_table = {}; // Key'd on our 20-bit "tuple". + + emit_code(clear_code); // Spec says first code should be a clear code. + // First index already loaded, process the rest of the stream. + + for (var i = 1, il = index_stream.length; i < il; ++i) { + var k = index_stream[i] & code_mask; + var cur_key = ib_code << 8 | k; // (prev, k) unique tuple. + + var cur_code = code_table[cur_key]; // buffer + k. + // Check if we have to create a new code table entry. + + if (cur_code === undefined) { + // We don't have buffer + k. + // Emit index buffer (without k). + // This is an inline version of emit_code, because this is the core + // writing routine of the compressor (and V8 cannot inline emit_code + // because it is a closure here in a different context). Additionally + // we can call emit_byte_to_buffer less often, because we can have + // 30-bits (from our 31-bit signed SMI), and we know our codes will only + // be 12-bits, so can safely have 18-bits there without overflow. + // emit_code(ib_code); + cur |= ib_code << cur_shift; + cur_shift += cur_code_size; + + while (cur_shift >= 8) { + buf[p++] = cur & 0xff; + cur >>= 8; + cur_shift -= 8; + + if (p === cur_subblock + 256) { + // Finished a subblock. + buf[cur_subblock] = 255; + cur_subblock = p++; + } + } + + if (next_code === 4096) { + // Table full, need a clear. + emit_code(clear_code); + next_code = eoi_code + 1; + cur_code_size = min_code_size + 1; + code_table = {}; + } else { + // Table not full, insert a new entry. + // Increase our variable bit code sizes if necessary. This is a bit + // tricky as it is based on "timing" between the encoding and + // decoder. From the encoders perspective this should happen after + // we've already emitted the index buffer and are about to create the + // first table entry that would overflow our current code bit size. + if (next_code >= 1 << cur_code_size) ++cur_code_size; + code_table[cur_key] = next_code++; // Insert into code table. + } + + ib_code = k; // Index buffer to single input k. + } else { + ib_code = cur_code; // Index buffer to sequence in code table. + } + } + + emit_code(ib_code); // There will still be something in the index buffer. + + emit_code(eoi_code); // End Of Information. + // Flush / finalize the sub-blocks stream to the buffer. + + emit_bytes_to_buffer(1); // Finish the sub-blocks, writing out any unfinished lengths and + // terminating with a sub-block of length 0. If we have already started + // but not yet used a sub-block it can just become the terminator. + + if (cur_subblock + 1 === p) { + // Started but unused. + buf[cur_subblock] = 0; + } else { + // Started and used, write length and additional terminator block. + buf[cur_subblock] = p - cur_subblock - 1; + buf[p++] = 0; + } + + return p; + } + + function GifReader(buf) { + var p = 0; // - Header (GIF87a or GIF89a). + + if (buf[p++] !== 0x47 || buf[p++] !== 0x49 || buf[p++] !== 0x46 || buf[p++] !== 0x38 || (buf[p++] + 1 & 0xfd) !== 0x38 || buf[p++] !== 0x61) { + throw "Invalid GIF 87a/89a header."; + } // - Logical Screen Descriptor. + + + var width = buf[p++] | buf[p++] << 8; + var height = buf[p++] | buf[p++] << 8; + var pf0 = buf[p++]; // . + + var global_palette_flag = pf0 >> 7; + var num_global_colors_pow2 = pf0 & 0x7; + var num_global_colors = 1 << num_global_colors_pow2 + 1; + var background = buf[p++]; + buf[p++]; // Pixel aspect ratio (unused?). + + var global_palette_offset = null; + + if (global_palette_flag) { + global_palette_offset = p; + p += num_global_colors * 3; // Seek past palette. + } + + var no_eof = true; + var frames = []; + var delay = 0; + var transparent_index = null; + var disposal = 0; // 0 - No disposal specified. + + var loop_count = null; + this.width = width; + this.height = height; + + while (no_eof && p < buf.length) { + switch (buf[p++]) { + case 0x21: + // Graphics Control Extension Block + switch (buf[p++]) { + case 0xff: + // Application specific block + // Try if it's a Netscape block (with animation loop counter). + if (buf[p] !== 0x0b || // 21 FF already read, check block size. + // NETSCAPE2.0 + buf[p + 1] == 0x4e && buf[p + 2] == 0x45 && buf[p + 3] == 0x54 && buf[p + 4] == 0x53 && buf[p + 5] == 0x43 && buf[p + 6] == 0x41 && buf[p + 7] == 0x50 && buf[p + 8] == 0x45 && buf[p + 9] == 0x32 && buf[p + 10] == 0x2e && buf[p + 11] == 0x30 && // Sub-block + buf[p + 12] == 0x03 && buf[p + 13] == 0x01 && buf[p + 16] == 0) { + p += 14; + loop_count = buf[p++] | buf[p++] << 8; + p++; // Skip terminator. + } else { + // We don't know what it is, just try to get past it. + p += 12; + + while (true) { + // Seek through subblocks. + var block_size = buf[p++]; + if (block_size === 0) break; + p += block_size; + } + } + + break; + + case 0xf9: + // Graphics Control Extension + if (buf[p++] !== 0x4 || buf[p + 4] !== 0) throw "Invalid graphics extension block."; + var pf1 = buf[p++]; + delay = buf[p++] | buf[p++] << 8; + transparent_index = buf[p++]; + if ((pf1 & 1) === 0) transparent_index = null; + disposal = pf1 >> 2 & 0x7; + p++; // Skip terminator. + + break; + + case 0xfe: + // Comment Extension. + while (true) { + // Seek through subblocks. + var block_size = buf[p++]; + if (block_size === 0) break; // console.log(buf.slice(p, p+block_size).toString('ascii')); + + p += block_size; + } + + break; + + default: + throw "Unknown graphic control label: 0x" + buf[p - 1].toString(16); + } + + break; + + case 0x2c: + // Image Descriptor. + var x = buf[p++] | buf[p++] << 8; + var y = buf[p++] | buf[p++] << 8; + var w = buf[p++] | buf[p++] << 8; + var h = buf[p++] | buf[p++] << 8; + var pf2 = buf[p++]; + var local_palette_flag = pf2 >> 7; + var interlace_flag = pf2 >> 6 & 1; + var num_local_colors_pow2 = pf2 & 0x7; + var num_local_colors = 1 << num_local_colors_pow2 + 1; + var palette_offset = global_palette_offset; + var has_local_palette = false; + + if (local_palette_flag) { + var has_local_palette = true; + palette_offset = p; // Override with local palette. + + p += num_local_colors * 3; // Seek past palette. + } + + var data_offset = p; + p++; // codesize + + while (true) { + var block_size = buf[p++]; + if (block_size === 0) break; + p += block_size; + } + + frames.push({ + x: x, + y: y, + width: w, + height: h, + has_local_palette: has_local_palette, + palette_offset: palette_offset, + data_offset: data_offset, + data_length: p - data_offset, + transparent_index: transparent_index, + interlaced: !!interlace_flag, + delay: delay, + disposal: disposal + }); + break; + + case 0x3b: + // Trailer Marker (end of file). + no_eof = false; + break; + + default: + throw "Unknown gif block: 0x" + buf[p - 1].toString(16); + break; + } + } + + this.numFrames = function () { + return frames.length; + }; + + this.loopCount = function () { + return loop_count; + }; + + this.frameInfo = function (frame_num) { + if (frame_num < 0 || frame_num >= frames.length) throw "Frame index out of range."; + return frames[frame_num]; + }; + + this.decodeAndBlitFrameBGRA = function (frame_num, pixels) { + var frame = this.frameInfo(frame_num); + var num_pixels = frame.width * frame.height; + var index_stream = new Uint8Array(num_pixels); // At most 8-bit indices. + + GifReaderLZWOutputIndexStream(buf, frame.data_offset, index_stream, num_pixels); + var palette_offset = frame.palette_offset; // NOTE(deanm): It seems to be much faster to compare index to 256 than + // to === null. Not sure why, but CompareStub_EQ_STRICT shows up high in + // the profile, not sure if it's related to using a Uint8Array. + + var trans = frame.transparent_index; + if (trans === null) trans = 256; // We are possibly just blitting to a portion of the entire frame. + // That is a subrect within the framerect, so the additional pixels + // must be skipped over after we finished a scanline. + + var framewidth = frame.width; + var framestride = width - framewidth; + var xleft = framewidth; // Number of subrect pixels left in scanline. + // Output indicies of the top left and bottom right corners of the subrect. + + var opbeg = (frame.y * width + frame.x) * 4; + var opend = ((frame.y + frame.height) * width + frame.x) * 4; + var op = opbeg; + var scanstride = framestride * 4; // Use scanstride to skip past the rows when interlacing. This is skipping + // 7 rows for the first two passes, then 3 then 1. + + if (frame.interlaced === true) { + scanstride += (framewidth + framestride) * 4 * 7; // Pass 1. + } + + var interlaceskip = 8; // Tracking the row interval in the current pass. + + for (var i = 0, il = index_stream.length; i < il; ++i) { + var index = index_stream[i]; + + if (xleft === 0) { + // Beginning of new scan line + op += scanstride; + xleft = framewidth; + + if (op >= opend) { + // Catch the wrap to switch passes when interlacing. + scanstride = framestride + (framewidth + framestride) * 4 * (interlaceskip - 1); // interlaceskip / 2 * 4 is interlaceskip << 1. + + op = opbeg + (framewidth + framestride) * (interlaceskip << 1); + interlaceskip >>= 1; + } + } + + if (index === trans) { + op += 4; + } else { + var r = buf[palette_offset + index * 3]; + var g = buf[palette_offset + index * 3 + 1]; + var b = buf[palette_offset + index * 3 + 2]; + pixels[op++] = b; + pixels[op++] = g; + pixels[op++] = r; + pixels[op++] = 255; + } + + --xleft; + } + }; // I will go to copy and paste hell one day... + + + this.decodeAndBlitFrameRGBA = function (frame_num, pixels) { + var frame = this.frameInfo(frame_num); + var num_pixels = frame.width * frame.height; + var index_stream = new Uint8Array(num_pixels); // At most 8-bit indices. + + GifReaderLZWOutputIndexStream(buf, frame.data_offset, index_stream, num_pixels); + var palette_offset = frame.palette_offset; // NOTE(deanm): It seems to be much faster to compare index to 256 than + // to === null. Not sure why, but CompareStub_EQ_STRICT shows up high in + // the profile, not sure if it's related to using a Uint8Array. + + var trans = frame.transparent_index; + if (trans === null) trans = 256; // We are possibly just blitting to a portion of the entire frame. + // That is a subrect within the framerect, so the additional pixels + // must be skipped over after we finished a scanline. + + var framewidth = frame.width; + var framestride = width - framewidth; + var xleft = framewidth; // Number of subrect pixels left in scanline. + // Output indicies of the top left and bottom right corners of the subrect. + + var opbeg = (frame.y * width + frame.x) * 4; + var opend = ((frame.y + frame.height) * width + frame.x) * 4; + var op = opbeg; + var scanstride = framestride * 4; // Use scanstride to skip past the rows when interlacing. This is skipping + // 7 rows for the first two passes, then 3 then 1. + + if (frame.interlaced === true) { + scanstride += (framewidth + framestride) * 4 * 7; // Pass 1. + } + + var interlaceskip = 8; // Tracking the row interval in the current pass. + + for (var i = 0, il = index_stream.length; i < il; ++i) { + var index = index_stream[i]; + + if (xleft === 0) { + // Beginning of new scan line + op += scanstride; + xleft = framewidth; + + if (op >= opend) { + // Catch the wrap to switch passes when interlacing. + scanstride = framestride + (framewidth + framestride) * 4 * (interlaceskip - 1); // interlaceskip / 2 * 4 is interlaceskip << 1. + + op = opbeg + (framewidth + framestride) * (interlaceskip << 1); + interlaceskip >>= 1; + } + } + + if (index === trans) { + op += 4; + } else { + var r = buf[palette_offset + index * 3]; + var g = buf[palette_offset + index * 3 + 1]; + var b = buf[palette_offset + index * 3 + 2]; + pixels[op++] = r; + pixels[op++] = g; + pixels[op++] = b; + pixels[op++] = 255; + } + + --xleft; + } + }; + } + + function GifReaderLZWOutputIndexStream(code_stream, p, output, output_length) { + var min_code_size = code_stream[p++]; + var clear_code = 1 << min_code_size; + var eoi_code = clear_code + 1; + var next_code = eoi_code + 1; + var cur_code_size = min_code_size + 1; // Number of bits per code. + // NOTE: This shares the same name as the encoder, but has a different + // meaning here. Here this masks each code coming from the code stream. + + var code_mask = (1 << cur_code_size) - 1; + var cur_shift = 0; + var cur = 0; + var op = 0; // Output pointer. + + var subblock_size = code_stream[p++]; // TODO(deanm): Would using a TypedArray be any faster? At least it would + // solve the fast mode / backing store uncertainty. + // var code_table = Array(4096); + + var code_table = new Int32Array(4096); // Can be signed, we only use 20 bits. + + var prev_code = null; // Track code-1. + + while (true) { + // Read up to two bytes, making sure we always 12-bits for max sized code. + while (cur_shift < 16) { + if (subblock_size === 0) break; // No more data to be read. + + cur |= code_stream[p++] << cur_shift; + cur_shift += 8; + + if (subblock_size === 1) { + // Never let it get to 0 to hold logic above. + subblock_size = code_stream[p++]; // Next subblock. + } else { + --subblock_size; + } + } // TODO(deanm): We should never really get here, we should have received + // and EOI. + + + if (cur_shift < cur_code_size) break; + var code = cur & code_mask; + cur >>= cur_code_size; + cur_shift -= cur_code_size; // TODO(deanm): Maybe should check that the first code was a clear code, + // at least this is what you're supposed to do. But actually our encoder + // now doesn't emit a clear code first anyway. + + if (code === clear_code) { + // We don't actually have to clear the table. This could be a good idea + // for greater error checking, but we don't really do any anyway. We + // will just track it with next_code and overwrite old entries. + next_code = eoi_code + 1; + cur_code_size = min_code_size + 1; + code_mask = (1 << cur_code_size) - 1; // Don't update prev_code ? + + prev_code = null; + continue; + } else if (code === eoi_code) { + break; + } // We have a similar situation as the decoder, where we want to store + // variable length entries (code table entries), but we want to do in a + // faster manner than an array of arrays. The code below stores sort of a + // linked list within the code table, and then "chases" through it to + // construct the dictionary entries. When a new entry is created, just the + // last byte is stored, and the rest (prefix) of the entry is only + // referenced by its table entry. Then the code chases through the + // prefixes until it reaches a single byte code. We have to chase twice, + // first to compute the length, and then to actually copy the data to the + // output (backwards, since we know the length). The alternative would be + // storing something in an intermediate stack, but that doesn't make any + // more sense. I implemented an approach where it also stored the length + // in the code table, although it's a bit tricky because you run out of + // bits (12 + 12 + 8), but I didn't measure much improvements (the table + // entries are generally not the long). Even when I created benchmarks for + // very long table entries the complexity did not seem worth it. + // The code table stores the prefix entry in 12 bits and then the suffix + // byte in 8 bits, so each entry is 20 bits. + + + var chase_code = code < next_code ? code : prev_code; // Chase what we will output, either {CODE} or {CODE-1}. + + var chase_length = 0; + var chase = chase_code; + + while (chase > clear_code) { + chase = code_table[chase] >> 8; + ++chase_length; + } + + var k = chase; + var op_end = op + chase_length + (chase_code !== code ? 1 : 0); + + if (op_end > output_length) { + console.log("Warning, gif stream longer than expected."); + return; + } // Already have the first byte from the chase, might as well write it fast. + + + output[op++] = k; + op += chase_length; + var b = op; // Track pointer, writing backwards. + + if (chase_code !== code) // The case of emitting {CODE-1} + k. + output[op++] = k; + chase = chase_code; + + while (chase_length--) { + chase = code_table[chase]; + output[--b] = chase & 0xff; // Write backwards. + + chase >>= 8; // Pull down to the prefix code. + } + + if (prev_code !== null && next_code < 4096) { + code_table[next_code++] = prev_code << 8 | k; // TODO(deanm): Figure out this clearing vs code growth logic better. I + // have an feeling that it should just happen somewhere else, for now it + // is awkward between when we grow past the max and then hit a clear code. + // For now just check if we hit the max 12-bits (then a clear code should + // follow, also of course encoded in 12-bits). + + if (next_code >= code_mask + 1 && cur_code_size < 12) { + ++cur_code_size; + code_mask = code_mask << 1 | 1; + } + } + + prev_code = code; + } + + if (op !== output_length) { + console.log("Warning, gif stream shorter than expected."); + } + + return output; + } + + try { + + + } catch (e) {} // CommonJS. + + /* + * Copyright (c) 2012 chick307 + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + (function (jsPDF, callback) { + jsPDF.API.adler32cs = callback(); + })(jsPDF, function () { + var _hasArrayBuffer = typeof ArrayBuffer === "function" && typeof Uint8Array === "function"; + + var _Buffer = null, + _isBuffer = function () { + if (!_hasArrayBuffer) return function _isBuffer() { + return false; + }; + + return function _isBuffer(value) { + return value instanceof ArrayBuffer || _Buffer !== null && value instanceof _Buffer; + }; + }(); + + var _utf8ToBinary = function () { + if (_Buffer !== null) { + return function _utf8ToBinary(utf8String) { + return new _Buffer(utf8String, "utf8").toString("binary"); + }; + } else { + return function _utf8ToBinary(utf8String) { + return unescape(encodeURIComponent(utf8String)); + }; + } + }(); + + var MOD = 65521; + + var _update = function _update(checksum, binaryString) { + var a = checksum & 0xffff, + b = checksum >>> 16; + + for (var i = 0, length = binaryString.length; i < length; i++) { + a = (a + (binaryString.charCodeAt(i) & 0xff)) % MOD; + b = (b + a) % MOD; + } + + return (b << 16 | a) >>> 0; + }; + + var _updateUint8Array = function _updateUint8Array(checksum, uint8Array) { + var a = checksum & 0xffff, + b = checksum >>> 16; + + for (var i = 0, length = uint8Array.length; i < length; i++) { + a = (a + uint8Array[i]) % MOD; + b = (b + a) % MOD; + } + + return (b << 16 | a) >>> 0; + }; + + var exports = {}; + + var Adler32 = exports.Adler32 = function () { + var ctor = function Adler32(checksum) { + if (!(this instanceof ctor)) { + throw new TypeError("Constructor cannot called be as a function."); + } + + if (!isFinite(checksum = checksum == null ? 1 : +checksum)) { + throw new Error("First arguments needs to be a finite number."); + } + + this.checksum = checksum >>> 0; + }; + + var proto = ctor.prototype = {}; + proto.constructor = ctor; + + ctor.from = function (from) { + from.prototype = proto; + return from; + }(function from(binaryString) { + if (!(this instanceof ctor)) { + throw new TypeError("Constructor cannot called be as a function."); + } + + if (binaryString == null) throw new Error("First argument needs to be a string."); + this.checksum = _update(1, binaryString.toString()); + }); + + ctor.fromUtf8 = function (fromUtf8) { + fromUtf8.prototype = proto; + return fromUtf8; + }(function fromUtf8(utf8String) { + if (!(this instanceof ctor)) { + throw new TypeError("Constructor cannot called be as a function."); + } + + if (utf8String == null) throw new Error("First argument needs to be a string."); + + var binaryString = _utf8ToBinary(utf8String.toString()); + + this.checksum = _update(1, binaryString); + }); + + if (_hasArrayBuffer) { + ctor.fromBuffer = function (fromBuffer) { + fromBuffer.prototype = proto; + return fromBuffer; + }(function fromBuffer(buffer) { + if (!(this instanceof ctor)) { + throw new TypeError("Constructor cannot called be as a function."); + } + + if (!_isBuffer(buffer)) throw new Error("First argument needs to be ArrayBuffer."); + var array = new Uint8Array(buffer); + return this.checksum = _updateUint8Array(1, array); + }); + } + + proto.update = function update(binaryString) { + if (binaryString == null) throw new Error("First argument needs to be a string."); + binaryString = binaryString.toString(); + return this.checksum = _update(this.checksum, binaryString); + }; + + proto.updateUtf8 = function updateUtf8(utf8String) { + if (utf8String == null) throw new Error("First argument needs to be a string."); + + var binaryString = _utf8ToBinary(utf8String.toString()); + + return this.checksum = _update(this.checksum, binaryString); + }; + + if (_hasArrayBuffer) { + proto.updateBuffer = function updateBuffer(buffer) { + if (!_isBuffer(buffer)) throw new Error("First argument needs to be ArrayBuffer."); + var array = new Uint8Array(buffer); + return this.checksum = _updateUint8Array(this.checksum, array); + }; + } + + proto.clone = function clone() { + return new Adler32(this.checksum); + }; + + return ctor; + }(); + + exports.from = function from(binaryString) { + if (binaryString == null) throw new Error("First argument needs to be a string."); + return _update(1, binaryString.toString()); + }; + + exports.fromUtf8 = function fromUtf8(utf8String) { + if (utf8String == null) throw new Error("First argument needs to be a string."); + + var binaryString = _utf8ToBinary(utf8String.toString()); + + return _update(1, binaryString); + }; + + if (_hasArrayBuffer) { + exports.fromBuffer = function fromBuffer(buffer) { + if (!_isBuffer(buffer)) throw new Error("First argument need to be ArrayBuffer."); + var array = new Uint8Array(buffer); + return _updateUint8Array(1, array); + }; + } + + return exports; + }); + + /* + Copyright (c) 2008, Adobe Systems Incorporated + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Adobe Systems Incorporated nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + /** + * @author shaozilee + * + * Bmp format decoder,support 1bit 4bit 8bit 24bit bmp + * + */ + + /* + Copyright (c) 2013 Gildas Lormeau. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, + INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + /* + * This program is based on JZlib 1.0.2 ymnk, JCraft,Inc. + * JZlib is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + (function (global) { + + var MAX_BITS = 15; + var D_CODES = 30; + var BL_CODES = 19; + var LENGTH_CODES = 29; + var LITERALS = 256; + var L_CODES = LITERALS + 1 + LENGTH_CODES; + var HEAP_SIZE = 2 * L_CODES + 1; + var END_BLOCK = 256; // Bit length codes must not exceed MAX_BL_BITS bits + + var MAX_BL_BITS = 7; // repeat previous bit length 3-6 times (2 bits of repeat count) + + var REP_3_6 = 16; // repeat a zero length 3-10 times (3 bits of repeat count) + + var REPZ_3_10 = 17; // repeat a zero length 11-138 times (7 bits of repeat count) + + var REPZ_11_138 = 18; // The lengths of the bit length codes are sent in order of decreasing + // probability, to avoid transmitting the lengths for unused bit + // length codes. + + var Buf_size = 8 * 2; // JZlib version : "1.0.2" + + var Z_DEFAULT_COMPRESSION = -1; // compression strategy + + var Z_FILTERED = 1; + var Z_HUFFMAN_ONLY = 2; + var Z_DEFAULT_STRATEGY = 0; + var Z_NO_FLUSH = 0; + var Z_PARTIAL_FLUSH = 1; + var Z_FULL_FLUSH = 3; + var Z_FINISH = 4; + var Z_OK = 0; + var Z_STREAM_END = 1; + var Z_NEED_DICT = 2; + var Z_STREAM_ERROR = -2; + var Z_DATA_ERROR = -3; + var Z_BUF_ERROR = -5; // Tree + // see definition of array dist_code below + + var _dist_code = [0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29]; + + function Tree() { + var that = this; // dyn_tree; // the dynamic tree + // max_code; // largest code with non zero frequency + // stat_desc; // the corresponding static tree + // Compute the optimal bit lengths for a tree and update the total bit + // length + // for the current block. + // IN assertion: the fields freq and dad are set, heap[heap_max] and + // above are the tree nodes sorted by increasing frequency. + // OUT assertions: the field len is set to the optimal bit length, the + // array bl_count contains the frequencies for each bit length. + // The length opt_len is updated; static_len is also updated if stree is + // not null. + + function gen_bitlen(s) { + var tree = that.dyn_tree; + var stree = that.stat_desc.static_tree; + var extra = that.stat_desc.extra_bits; + var base = that.stat_desc.extra_base; + var max_length = that.stat_desc.max_length; + var h; // heap index + + var n, m; // iterate over the tree elements + + var bits; // bit length + + var xbits; // extra bits + + var f; // frequency + + var overflow = 0; // number of elements with bit length too large + + for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0; // In a first pass, compute the optimal bit lengths (which may + // overflow in the case of the bit length tree). + + + tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap + + for (h = s.heap_max + 1; h < HEAP_SIZE; h++) { + n = s.heap[h]; + bits = tree[tree[n * 2 + 1] * 2 + 1] + 1; + + if (bits > max_length) { + bits = max_length; + overflow++; + } + + tree[n * 2 + 1] = bits; // We overwrite tree[n*2+1] which is no longer needed + + if (n > that.max_code) continue; // not a leaf node + + s.bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n - base]; + f = tree[n * 2]; + s.opt_len += f * (bits + xbits); + if (stree) s.static_len += f * (stree[n * 2 + 1] + xbits); + } + + if (overflow === 0) return; // This happens for example on obj2 and pic of the Calgary corpus + // Find the first bit length which could increase: + + do { + bits = max_length - 1; + + while (s.bl_count[bits] === 0) bits--; + + s.bl_count[bits]--; // move one leaf down the tree + + s.bl_count[bits + 1] += 2; // move one overflow item as its brother + + s.bl_count[max_length]--; // The brother of the overflow item also moves one step up, + // but this does not affect bl_count[max_length] + + overflow -= 2; + } while (overflow > 0); + + for (bits = max_length; bits !== 0; bits--) { + n = s.bl_count[bits]; + + while (n !== 0) { + m = s.heap[--h]; + if (m > that.max_code) continue; + + if (tree[m * 2 + 1] != bits) { + s.opt_len += (bits - tree[m * 2 + 1]) * tree[m * 2]; + tree[m * 2 + 1] = bits; + } + + n--; + } + } + } // Reverse the first len bits of a code, using straightforward code (a + // faster + // method would use a table) + // IN assertion: 1 <= len <= 15 + + + function bi_reverse(code, // the value to invert + len // its bit length + ) { + var res = 0; + + do { + res |= code & 1; + code >>>= 1; + res <<= 1; + } while (--len > 0); + + return res >>> 1; + } // Generate the codes for a given tree and bit counts (which need not be + // optimal). + // IN assertion: the array bl_count contains the bit length statistics for + // the given tree and the field len is set for all tree elements. + // OUT assertion: the field code is set for all tree elements of non + // zero code length. + + + function gen_codes(tree, // the tree to decorate + max_code, // largest code with non zero frequency + bl_count // number of codes at each bit length + ) { + var next_code = []; // next code value for each + // bit length + + var code = 0; // running code value + + var bits; // bit index + + var n; // code index + + var len; // The distribution counts are first used to generate the code values + // without bit reversal. + + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = code + bl_count[bits - 1] << 1; + } // Check that the bit counts in bl_count are consistent. The last code + // must be all ones. + // Assert (code + bl_count[MAX_BITS]-1 == (1<= 1; n--) s.pqdownheap(tree, n); // Construct the Huffman tree by repeatedly combining the least two + // frequent nodes. + + + node = elems; // next internal node of the tree + + do { + // n = node of least frequency + n = s.heap[1]; + s.heap[1] = s.heap[s.heap_len--]; + s.pqdownheap(tree, 1); + m = s.heap[1]; // m = node of next least frequency + + s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency + + s.heap[--s.heap_max] = m; // Create a new node father of n and m + + tree[node * 2] = tree[n * 2] + tree[m * 2]; + s.depth[node] = Math.max(s.depth[n], s.depth[m]) + 1; + tree[n * 2 + 1] = tree[m * 2 + 1] = node; // and insert the new node in the heap + + s.heap[1] = node++; + s.pqdownheap(tree, 1); + } while (s.heap_len >= 2); + + s.heap[--s.heap_max] = s.heap[1]; // At this point, the fields freq and dad are set. We can now + // generate the bit lengths. + + gen_bitlen(s); // The field len is now set, we can generate the bit codes + + gen_codes(tree, that.max_code, s.bl_count); + }; + } + + Tree._length_code = [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28]; + Tree.base_length = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0]; + Tree.base_dist = [0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576]; // Mapping from a distance to a distance code. dist is the distance - 1 and + // must not have side effects. _dist_code[256] and _dist_code[257] are never + // used. + + Tree.d_code = function (dist) { + return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; + }; // extra bits for each length code + + + Tree.extra_lbits = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0]; // extra bits for each distance code + + Tree.extra_dbits = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13]; // extra bits for each bit length code + + Tree.extra_blbits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7]; + Tree.bl_order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; // StaticTree + + function StaticTree(static_tree, extra_bits, extra_base, elems, max_length) { + var that = this; + that.static_tree = static_tree; + that.extra_bits = extra_bits; + that.extra_base = extra_base; + that.elems = elems; + that.max_length = max_length; + } + + StaticTree.static_ltree = [12, 8, 140, 8, 76, 8, 204, 8, 44, 8, 172, 8, 108, 8, 236, 8, 28, 8, 156, 8, 92, 8, 220, 8, 60, 8, 188, 8, 124, 8, 252, 8, 2, 8, 130, 8, 66, 8, 194, 8, 34, 8, 162, 8, 98, 8, 226, 8, 18, 8, 146, 8, 82, 8, 210, 8, 50, 8, 178, 8, 114, 8, 242, 8, 10, 8, 138, 8, 74, 8, 202, 8, 42, 8, 170, 8, 106, 8, 234, 8, 26, 8, 154, 8, 90, 8, 218, 8, 58, 8, 186, 8, 122, 8, 250, 8, 6, 8, 134, 8, 70, 8, 198, 8, 38, 8, 166, 8, 102, 8, 230, 8, 22, 8, 150, 8, 86, 8, 214, 8, 54, 8, 182, 8, 118, 8, 246, 8, 14, 8, 142, 8, 78, 8, 206, 8, 46, 8, 174, 8, 110, 8, 238, 8, 30, 8, 158, 8, 94, 8, 222, 8, 62, 8, 190, 8, 126, 8, 254, 8, 1, 8, 129, 8, 65, 8, 193, 8, 33, 8, 161, 8, 97, 8, 225, 8, 17, 8, 145, 8, 81, 8, 209, 8, 49, 8, 177, 8, 113, 8, 241, 8, 9, 8, 137, 8, 73, 8, 201, 8, 41, 8, 169, 8, 105, 8, 233, 8, 25, 8, 153, 8, 89, 8, 217, 8, 57, 8, 185, 8, 121, 8, 249, 8, 5, 8, 133, 8, 69, 8, 197, 8, 37, 8, 165, 8, 101, 8, 229, 8, 21, 8, 149, 8, 85, 8, 213, 8, 53, 8, 181, 8, 117, 8, 245, 8, 13, 8, 141, 8, 77, 8, 205, 8, 45, 8, 173, 8, 109, 8, 237, 8, 29, 8, 157, 8, 93, 8, 221, 8, 61, 8, 189, 8, 125, 8, 253, 8, 19, 9, 275, 9, 147, 9, 403, 9, 83, 9, 339, 9, 211, 9, 467, 9, 51, 9, 307, 9, 179, 9, 435, 9, 115, 9, 371, 9, 243, 9, 499, 9, 11, 9, 267, 9, 139, 9, 395, 9, 75, 9, 331, 9, 203, 9, 459, 9, 43, 9, 299, 9, 171, 9, 427, 9, 107, 9, 363, 9, 235, 9, 491, 9, 27, 9, 283, 9, 155, 9, 411, 9, 91, 9, 347, 9, 219, 9, 475, 9, 59, 9, 315, 9, 187, 9, 443, 9, 123, 9, 379, 9, 251, 9, 507, 9, 7, 9, 263, 9, 135, 9, 391, 9, 71, 9, 327, 9, 199, 9, 455, 9, 39, 9, 295, 9, 167, 9, 423, 9, 103, 9, 359, 9, 231, 9, 487, 9, 23, 9, 279, 9, 151, 9, 407, 9, 87, 9, 343, 9, 215, 9, 471, 9, 55, 9, 311, 9, 183, 9, 439, 9, 119, 9, 375, 9, 247, 9, 503, 9, 15, 9, 271, 9, 143, 9, 399, 9, 79, 9, 335, 9, 207, 9, 463, 9, 47, 9, 303, 9, 175, 9, 431, 9, 111, 9, 367, 9, 239, 9, 495, 9, 31, 9, 287, 9, 159, 9, 415, 9, 95, 9, 351, 9, 223, 9, 479, 9, 63, 9, 319, 9, 191, 9, 447, 9, 127, 9, 383, 9, 255, 9, 511, 9, 0, 7, 64, 7, 32, 7, 96, 7, 16, 7, 80, 7, 48, 7, 112, 7, 8, 7, 72, 7, 40, 7, 104, 7, 24, 7, 88, 7, 56, 7, 120, 7, 4, 7, 68, 7, 36, 7, 100, 7, 20, 7, 84, 7, 52, 7, 116, 7, 3, 8, 131, 8, 67, 8, 195, 8, 35, 8, 163, 8, 99, 8, 227, 8]; + StaticTree.static_dtree = [0, 5, 16, 5, 8, 5, 24, 5, 4, 5, 20, 5, 12, 5, 28, 5, 2, 5, 18, 5, 10, 5, 26, 5, 6, 5, 22, 5, 14, 5, 30, 5, 1, 5, 17, 5, 9, 5, 25, 5, 5, 5, 21, 5, 13, 5, 29, 5, 3, 5, 19, 5, 11, 5, 27, 5, 7, 5, 23, 5]; + StaticTree.static_l_desc = new StaticTree(StaticTree.static_ltree, Tree.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); + StaticTree.static_d_desc = new StaticTree(StaticTree.static_dtree, Tree.extra_dbits, 0, D_CODES, MAX_BITS); + StaticTree.static_bl_desc = new StaticTree(null, Tree.extra_blbits, 0, BL_CODES, MAX_BL_BITS); // Deflate + + var MAX_MEM_LEVEL = 9; + var DEF_MEM_LEVEL = 8; + + function Config(good_length, max_lazy, nice_length, max_chain, func) { + var that = this; + that.good_length = good_length; + that.max_lazy = max_lazy; + that.nice_length = nice_length; + that.max_chain = max_chain; + that.func = func; + } + + var STORED = 0; + var FAST = 1; + var SLOW = 2; + var config_table = [new Config(0, 0, 0, 0, STORED), new Config(4, 4, 8, 4, FAST), new Config(4, 5, 16, 8, FAST), new Config(4, 6, 32, 32, FAST), new Config(4, 4, 16, 16, SLOW), new Config(8, 16, 32, 32, SLOW), new Config(8, 16, 128, 128, SLOW), new Config(8, 32, 128, 256, SLOW), new Config(32, 128, 258, 1024, SLOW), new Config(32, 258, 258, 4096, SLOW)]; + var z_errmsg = ["need dictionary", // Z_NEED_DICT + // 2 + "stream end", // Z_STREAM_END 1 + "", // Z_OK 0 + "", // Z_ERRNO (-1) + "stream error", // Z_STREAM_ERROR (-2) + "data error", // Z_DATA_ERROR (-3) + "", // Z_MEM_ERROR (-4) + "buffer error", // Z_BUF_ERROR (-5) + "", // Z_VERSION_ERROR (-6) + ""]; // block not completed, need more input or more output + + var NeedMore = 0; // block flush performed + + var BlockDone = 1; // finish started, need only more output at next deflate + + var FinishStarted = 2; // finish done, accept no more input or output + + var FinishDone = 3; // preset dictionary flag in zlib header + + var PRESET_DICT = 0x20; + var INIT_STATE = 42; + var BUSY_STATE = 113; + var FINISH_STATE = 666; // The deflate compression method + + var Z_DEFLATED = 8; + var STORED_BLOCK = 0; + var STATIC_TREES = 1; + var DYN_TREES = 2; + var MIN_MATCH = 3; + var MAX_MATCH = 258; + var MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1; + + function smaller(tree, n, m, depth) { + var tn2 = tree[n * 2]; + var tm2 = tree[m * 2]; + return tn2 < tm2 || tn2 == tm2 && depth[n] <= depth[m]; + } + + function Deflate() { + var that = this; + var strm; // pointer back to this zlib stream + + var status; // as the name implies + // pending_buf; // output still pending + + var pending_buf_size; // size of pending_buf + + var last_flush; // value of flush param for previous deflate call + + var w_size; // LZ77 window size (32K by default) + + var w_bits; // log2(w_size) (8..16) + + var w_mask; // w_size - 1 + + var window; // Sliding window. Input bytes are read into the second half of the window, + // and move to the first half later to keep a dictionary of at least wSize + // bytes. With this organization, matches are limited to a distance of + // wSize-MAX_MATCH bytes, but this ensures that IO is always + // performed with a length multiple of the block size. Also, it limits + // the window size to 64K, which is quite useful on MSDOS. + // To do: use the user input buffer as sliding window. + + var window_size; // Actual size of window: 2*wSize, except when the user input buffer + // is directly used as sliding window. + + var prev; // Link to older string with same hash index. To limit the size of this + // array to 64K, this link is maintained only for the last 32K strings. + // An index in this array is thus a window index modulo 32K. + + var head; // Heads of the hash chains or NIL. + + var ins_h; // hash index of string to be inserted + + var hash_size; // number of elements in hash table + + var hash_bits; // log2(hash_size) + + var hash_mask; // hash_size-1 + // Number of bits by which ins_h must be shifted at each input + // step. It must be such that after MIN_MATCH steps, the oldest + // byte no longer takes part in the hash key, that is: + // hash_shift * MIN_MATCH >= hash_bits + + var hash_shift; // Window position at the beginning of the current output block. Gets + // negative when the window is moved backwards. + + var block_start; + var match_length; // length of best match + + var prev_match; // previous match + + var match_available; // set if previous match exists + + var strstart; // start of string to insert + + var match_start; // start of matching string + + var lookahead; // number of valid bytes ahead in window + // Length of the best match at previous step. Matches not greater than this + // are discarded. This is used in the lazy match evaluation. + + var prev_length; // To speed up deflation, hash chains are never searched beyond this + // length. A higher limit improves compression ratio but degrades the speed. + + var max_chain_length; // Attempt to find a better match only when the current match is strictly + // smaller than this value. This mechanism is used only for compression + // levels >= 4. + + var max_lazy_match; // Insert new strings in the hash table only if the match length is not + // greater than this length. This saves time but degrades compression. + // max_insert_length is used only for compression levels <= 3. + + var level; // compression level (1..9) + + var strategy; // favor or force Huffman coding + // Use a faster search when the previous match is longer than this + + var good_match; // Stop searching when current match exceeds this + + var nice_match; + var dyn_ltree; // literal and length tree + + var dyn_dtree; // distance tree + + var bl_tree; // Huffman tree for bit lengths + + var l_desc = new Tree(); // desc for literal tree + + var d_desc = new Tree(); // desc for distance tree + + var bl_desc = new Tree(); // desc for bit length tree + // that.heap_len; // number of elements in the heap + // that.heap_max; // element of largest frequency + // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + // The same heap array is used to build all trees. + // Depth of each subtree used as tie breaker for trees of equal frequency + + that.depth = []; + var l_buf; // index for literals or lengths */ + // Size of match buffer for literals/lengths. There are 4 reasons for + // limiting lit_bufsize to 64K: + // - frequencies can be kept in 16 bit counters + // - if compression is not successful for the first block, all input + // data is still in the window so we can still emit a stored block even + // when input comes from standard input. (This can also be done for + // all blocks if lit_bufsize is not greater than 32K.) + // - if compression is not successful for a file smaller than 64K, we can + // even emit a stored file instead of a stored block (saving 5 bytes). + // This is applicable only for zip (not gzip or zlib). + // - creating new Huffman trees less frequently may not provide fast + // adaptation to changes in the input data statistics. (Take for + // example a binary file with poorly compressible code followed by + // a highly compressible string table.) Smaller buffer sizes give + // fast adaptation but have of course the overhead of transmitting + // trees more frequently. + // - I can't count above 4 + + var lit_bufsize; + var last_lit; // running index in l_buf + // Buffer for distances. To simplify the code, d_buf and l_buf have + // the same number of elements. To use different lengths, an extra flag + // array would be necessary. + + var d_buf; // index of pendig_buf + // that.opt_len; // bit length of current block with optimal trees + // that.static_len; // bit length of current block with static trees + + var matches; // number of string matches in current block + + var last_eob_len; // bit length of EOB code for last block + // Output buffer. bits are inserted starting at the bottom (least + // significant bits). + + var bi_buf; // Number of valid bits in bi_buf. All bits above the last valid bit + // are always zero. + + var bi_valid; // number of codes at each bit length for an optimal tree + + that.bl_count = []; // heap used to build the Huffman trees + + that.heap = []; + dyn_ltree = []; + dyn_dtree = []; + bl_tree = []; + + function lm_init() { + var i; + window_size = 2 * w_size; + head[hash_size - 1] = 0; + + for (i = 0; i < hash_size - 1; i++) { + head[i] = 0; + } // Set the default configuration parameters: + + + max_lazy_match = config_table[level].max_lazy; + good_match = config_table[level].good_length; + nice_match = config_table[level].nice_length; + max_chain_length = config_table[level].max_chain; + strstart = 0; + block_start = 0; + lookahead = 0; + match_length = prev_length = MIN_MATCH - 1; + match_available = 0; + ins_h = 0; + } + + function init_block() { + var i; // Initialize the trees. + + for (i = 0; i < L_CODES; i++) dyn_ltree[i * 2] = 0; + + for (i = 0; i < D_CODES; i++) dyn_dtree[i * 2] = 0; + + for (i = 0; i < BL_CODES; i++) bl_tree[i * 2] = 0; + + dyn_ltree[END_BLOCK * 2] = 1; + that.opt_len = that.static_len = 0; + last_lit = matches = 0; + } // Initialize the tree data structures for a new zlib stream. + + + function tr_init() { + l_desc.dyn_tree = dyn_ltree; + l_desc.stat_desc = StaticTree.static_l_desc; + d_desc.dyn_tree = dyn_dtree; + d_desc.stat_desc = StaticTree.static_d_desc; + bl_desc.dyn_tree = bl_tree; + bl_desc.stat_desc = StaticTree.static_bl_desc; + bi_buf = 0; + bi_valid = 0; + last_eob_len = 8; // enough lookahead for inflate + // Initialize the first block of the first file: + + init_block(); + } // Restore the heap property by moving down the tree starting at node k, + // exchanging a node with the smallest of its two sons if necessary, + // stopping + // when the heap property is re-established (each father smaller than its + // two sons). + + + that.pqdownheap = function (tree, // the tree to restore + k // node to move down + ) { + var heap = that.heap; + var v = heap[k]; + var j = k << 1; // left son of k + + while (j <= that.heap_len) { + // Set j to the smallest of the two sons: + if (j < that.heap_len && smaller(tree, heap[j + 1], heap[j], that.depth)) { + j++; + } // Exit if v is smaller than both sons + + + if (smaller(tree, v, heap[j], that.depth)) break; // Exchange v with the smallest son + + heap[k] = heap[j]; + k = j; // And continue down the tree, setting j to the left son of k + + j <<= 1; + } + + heap[k] = v; + }; // Scan a literal or distance tree to determine the frequencies of the codes + // in the bit length tree. + + + function scan_tree(tree, // the tree to be scanned + max_code // and its largest code of non zero frequency + ) { + var n; // iterates over all tree elements + + var prevlen = -1; // last emitted length + + var curlen; // length of current code + + var nextlen = tree[0 * 2 + 1]; // length of next code + + var count = 0; // repeat count of the current code + + var max_count = 7; // max repeat count + + var min_count = 4; // min repeat count + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + + tree[(max_code + 1) * 2 + 1] = 0xffff; // guard + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]; + + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + bl_tree[curlen * 2] += count; + } else if (curlen !== 0) { + if (curlen != prevlen) bl_tree[curlen * 2]++; + bl_tree[REP_3_6 * 2]++; + } else if (count <= 10) { + bl_tree[REPZ_3_10 * 2]++; + } else { + bl_tree[REPZ_11_138 * 2]++; + } + + count = 0; + prevlen = curlen; + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } else if (curlen == nextlen) { + max_count = 6; + min_count = 3; + } else { + max_count = 7; + min_count = 4; + } + } + } // Construct the Huffman tree for the bit lengths and return the index in + // bl_order of the last bit length code to send. + + + function build_bl_tree() { + var max_blindex; // index of last bit length code of non zero freq + // Determine the bit length frequencies for literal and distance trees + + scan_tree(dyn_ltree, l_desc.max_code); + scan_tree(dyn_dtree, d_desc.max_code); // Build the bit length tree: + + bl_desc.build_tree(that); // opt_len now includes the length of the tree representations, except + // the lengths of the bit lengths codes and the 5+5+4 bits for the + // counts. + // Determine the number of bit length codes to send. The pkzip format + // requires that at least 4 bit length codes be sent. (appnote.txt says + // 3 but the actual value used is 4.) + + for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { + if (bl_tree[Tree.bl_order[max_blindex] * 2 + 1] !== 0) break; + } // Update opt_len to include the bit length tree and counts + + + that.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; + return max_blindex; + } // Output a byte on the stream. + // IN assertion: there is enough room in pending_buf. + + + function put_byte(p) { + that.pending_buf[that.pending++] = p; + } + + function put_short(w) { + put_byte(w & 0xff); + put_byte(w >>> 8 & 0xff); + } + + function putShortMSB(b) { + put_byte(b >> 8 & 0xff); + put_byte(b & 0xff & 0xff); + } + + function send_bits(value, length) { + var val, + len = length; + + if (bi_valid > Buf_size - len) { + val = value; // bi_buf |= (val << bi_valid); + + bi_buf |= val << bi_valid & 0xffff; + put_short(bi_buf); + bi_buf = val >>> Buf_size - bi_valid; + bi_valid += len - Buf_size; + } else { + // bi_buf |= (value) << bi_valid; + bi_buf |= value << bi_valid & 0xffff; + bi_valid += len; + } + } + + function send_code(c, tree) { + var c2 = c * 2; + send_bits(tree[c2] & 0xffff, tree[c2 + 1] & 0xffff); + } // Send a literal or distance tree in compressed form, using the codes in + // bl_tree. + + + function send_tree(tree, // the tree to be sent + max_code // and its largest code of non zero frequency + ) { + var n; // iterates over all tree elements + + var prevlen = -1; // last emitted length + + var curlen; // length of current code + + var nextlen = tree[0 * 2 + 1]; // length of next code + + var count = 0; // repeat count of the current code + + var max_count = 7; // max repeat count + + var min_count = 4; // min repeat count + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]; + + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { + send_code(curlen, bl_tree); + } while (--count !== 0); + } else if (curlen !== 0) { + if (curlen != prevlen) { + send_code(curlen, bl_tree); + count--; + } + + send_code(REP_3_6, bl_tree); + send_bits(count - 3, 2); + } else if (count <= 10) { + send_code(REPZ_3_10, bl_tree); + send_bits(count - 3, 3); + } else { + send_code(REPZ_11_138, bl_tree); + send_bits(count - 11, 7); + } + + count = 0; + prevlen = curlen; + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } else if (curlen == nextlen) { + max_count = 6; + min_count = 3; + } else { + max_count = 7; + min_count = 4; + } + } + } // Send the header for a block using dynamic Huffman trees: the counts, the + // lengths of the bit length codes, the literal tree and the distance tree. + // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + + + function send_all_trees(lcodes, dcodes, blcodes) { + var rank; // index in bl_order + + send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt + + send_bits(dcodes - 1, 5); + send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt + + for (rank = 0; rank < blcodes; rank++) { + send_bits(bl_tree[Tree.bl_order[rank] * 2 + 1], 3); + } + + send_tree(dyn_ltree, lcodes - 1); // literal tree + + send_tree(dyn_dtree, dcodes - 1); // distance tree + } // Flush the bit buffer, keeping at most 7 bits in it. + + + function bi_flush() { + if (bi_valid == 16) { + put_short(bi_buf); + bi_buf = 0; + bi_valid = 0; + } else if (bi_valid >= 8) { + put_byte(bi_buf & 0xff); + bi_buf >>>= 8; + bi_valid -= 8; + } + } // Send one empty static block to give enough lookahead for inflate. + // This takes 10 bits, of which 7 may remain in the bit buffer. + // The current inflate code requires 9 bits of lookahead. If the + // last two codes for the previous block (real code plus EOB) were coded + // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + // the last real code. In this case we send two empty static blocks instead + // of one. (There are no problems if the previous block is stored or fixed.) + // To simplify the code, we assume the worst case of last real code encoded + // on one bit only. + + + function _tr_align() { + send_bits(STATIC_TREES << 1, 3); + send_code(END_BLOCK, StaticTree.static_ltree); + bi_flush(); // Of the 10 bits for the empty block, we have already sent + // (10 - bi_valid) bits. The lookahead for the last real code (before + // the EOB of the previous block) was thus at least one plus the length + // of the EOB plus what we have just sent of the empty static block. + + if (1 + last_eob_len + 10 - bi_valid < 9) { + send_bits(STATIC_TREES << 1, 3); + send_code(END_BLOCK, StaticTree.static_ltree); + bi_flush(); + } + + last_eob_len = 7; + } // Save the match info and tally the frequency counts. Return true if + // the current block must be flushed. + + + function _tr_tally(dist, // distance of matched string + lc // match length-MIN_MATCH or unmatched char (if dist==0) + ) { + var out_length, in_length, dcode; + that.pending_buf[d_buf + last_lit * 2] = dist >>> 8 & 0xff; + that.pending_buf[d_buf + last_lit * 2 + 1] = dist & 0xff; + that.pending_buf[l_buf + last_lit] = lc & 0xff; + last_lit++; + + if (dist === 0) { + // lc is the unmatched char + dyn_ltree[lc * 2]++; + } else { + matches++; // Here, lc is the match length - MIN_MATCH + + dist--; // dist = match distance - 1 + + dyn_ltree[(Tree._length_code[lc] + LITERALS + 1) * 2]++; + dyn_dtree[Tree.d_code(dist) * 2]++; + } + + if ((last_lit & 0x1fff) === 0 && level > 2) { + // Compute an upper bound for the compressed length + out_length = last_lit * 8; + in_length = strstart - block_start; + + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += dyn_dtree[dcode * 2] * (5 + Tree.extra_dbits[dcode]); + } + + out_length >>>= 3; + if (matches < Math.floor(last_lit / 2) && out_length < Math.floor(in_length / 2)) return true; + } + + return last_lit == lit_bufsize - 1; // We avoid equality with lit_bufsize because of wraparound at 64K + // on 16 bit machines and because stored blocks are restricted to + // 64K-1 bytes. + } // Send the block data compressed using the given Huffman trees + + + function compress_block(ltree, dtree) { + var dist; // distance of matched string + + var lc; // match length or unmatched char (if dist === 0) + + var lx = 0; // running index in l_buf + + var code; // the code to send + + var extra; // number of extra bits to send + + if (last_lit !== 0) { + do { + dist = that.pending_buf[d_buf + lx * 2] << 8 & 0xff00 | that.pending_buf[d_buf + lx * 2 + 1] & 0xff; + lc = that.pending_buf[l_buf + lx] & 0xff; + lx++; + + if (dist === 0) { + send_code(lc, ltree); // send a literal byte + } else { + // Here, lc is the match length - MIN_MATCH + code = Tree._length_code[lc]; + send_code(code + LITERALS + 1, ltree); // send the length + // code + + extra = Tree.extra_lbits[code]; + + if (extra !== 0) { + lc -= Tree.base_length[code]; + send_bits(lc, extra); // send the extra length bits + } + + dist--; // dist is now the match distance - 1 + + code = Tree.d_code(dist); + send_code(code, dtree); // send the distance code + + extra = Tree.extra_dbits[code]; + + if (extra !== 0) { + dist -= Tree.base_dist[code]; + send_bits(dist, extra); // send the extra distance bits + } + } // literal or match pair ? + // Check that the overlay between pending_buf and d_buf+l_buf is + // ok: + + } while (lx < last_lit); + } + + send_code(END_BLOCK, ltree); + last_eob_len = ltree[END_BLOCK * 2 + 1]; + } // Flush the bit buffer and align the output on a byte boundary + + + function bi_windup() { + if (bi_valid > 8) { + put_short(bi_buf); + } else if (bi_valid > 0) { + put_byte(bi_buf & 0xff); + } + + bi_buf = 0; + bi_valid = 0; + } // Copy a stored block, storing first the length and its + // one's complement if requested. + + + function copy_block(buf, // the input data + len, // its length + header // true if block header must be written + ) { + bi_windup(); // align on byte boundary + + last_eob_len = 8; // enough lookahead for inflate + + if (header) { + put_short(len); + put_short(~len); + } + + that.pending_buf.set(window.subarray(buf, buf + len), that.pending); + that.pending += len; + } // Send a stored block + + + function _tr_stored_block(buf, // input block + stored_len, // length of input block + eof // true if this is the last block for a file + ) { + send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type + + copy_block(buf, stored_len, true); // with header + } // Determine the best encoding for the current block: dynamic trees, static + // trees or store, and output the encoded block to the zip file. + + + function _tr_flush_block(buf, // input block, or NULL if too old + stored_len, // length of input block + eof // true if this is the last block for a file + ) { + var opt_lenb, static_lenb; // opt_len and static_len in bytes + + var max_blindex = 0; // index of last bit length code of non zero freq + // Build the Huffman trees unless a stored block is forced + + if (level > 0) { + // Construct the literal and distance trees + l_desc.build_tree(that); + d_desc.build_tree(that); // At this point, opt_len and static_len are the total bit lengths + // of + // the compressed block data, excluding the tree representations. + // Build the bit length tree for the above two trees, and get the + // index + // in bl_order of the last bit length code to send. + + max_blindex = build_bl_tree(); // Determine the best encoding. Compute first the block length in + // bytes + + opt_lenb = that.opt_len + 3 + 7 >>> 3; + static_lenb = that.static_len + 3 + 7 >>> 3; + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + } else { + opt_lenb = static_lenb = stored_len + 5; // force a stored block + } + + if (stored_len + 4 <= opt_lenb && buf != -1) { + // 4: two words for the lengths + // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + // Otherwise we can't have processed more than WSIZE input bytes + // since + // the last block flush, because compression would have been + // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + // transform a block into a stored block. + _tr_stored_block(buf, stored_len, eof); + } else if (static_lenb == opt_lenb) { + send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3); + compress_block(StaticTree.static_ltree, StaticTree.static_dtree); + } else { + send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3); + send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1); + compress_block(dyn_ltree, dyn_dtree); + } // The above check is made mod 2^32, for files larger than 512 MB + // and uLong implemented on 32 bits. + + + init_block(); + + if (eof) { + bi_windup(); + } + } + + function flush_block_only(eof) { + _tr_flush_block(block_start >= 0 ? block_start : -1, strstart - block_start, eof); + + block_start = strstart; + strm.flush_pending(); + } // Fill the window when the lookahead becomes insufficient. + // Updates strstart and lookahead. + // + // IN assertion: lookahead < MIN_LOOKAHEAD + // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + // At least one byte has been read, or avail_in === 0; reads are + // performed for at least two bytes (required for the zip translate_eol + // option -- not supported here). + + + function fill_window() { + var n, m; + var p; + var more; // Amount of free space at the end of the window. + + do { + more = window_size - lookahead - strstart; // Deal with !@#$% 64K limit: + + if (more === 0 && strstart === 0 && lookahead === 0) { + more = w_size; + } else if (more == -1) { + // Very unlikely, but possible on 16 bit machine if strstart == + // 0 + // and lookahead == 1 (input done one byte at time) + more--; // If the window is almost full and there is insufficient + // lookahead, + // move the upper half to the lower one to make room in the + // upper half. + } else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) { + window.set(window.subarray(w_size, w_size + w_size), 0); + match_start -= w_size; + strstart -= w_size; // we now have strstart >= MAX_DIST + + block_start -= w_size; // Slide the hash table (could be avoided with 32 bit values + // at the expense of memory usage). We slide even when level == + // 0 + // to keep the hash table consistent if we switch back to level + // > 0 + // later. (Using level 0 permanently is not an optimal usage of + // zlib, so we don't care about this pathological case.) + + n = hash_size; + p = n; + + do { + m = head[--p] & 0xffff; + head[p] = m >= w_size ? m - w_size : 0; + } while (--n !== 0); + + n = w_size; + p = n; + + do { + m = prev[--p] & 0xffff; + prev[p] = m >= w_size ? m - w_size : 0; // If n is not on any hash chain, prev[n] is garbage but + // its value will never be used. + } while (--n !== 0); + + more += w_size; + } + + if (strm.avail_in === 0) return; // If there was no sliding: + // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + // more == window_size - lookahead - strstart + // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + // => more >= window_size - 2*WSIZE + 2 + // In the BIG_MEM or MMAP case (not yet supported), + // window_size == input_size + MIN_LOOKAHEAD && + // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + // Otherwise, window_size == 2*WSIZE so more >= 2. + // If there was sliding, more >= WSIZE. So in all cases, more >= 2. + + n = strm.read_buf(window, strstart + lookahead, more); + lookahead += n; // Initialize the hash value now that we have some input: + + if (lookahead >= MIN_MATCH) { + ins_h = window[strstart] & 0xff; + ins_h = (ins_h << hash_shift ^ window[strstart + 1] & 0xff) & hash_mask; + } // If the whole input has less than MIN_MATCH bytes, ins_h is + // garbage, + // but this is not important since only literal bytes will be + // emitted. + + } while (lookahead < MIN_LOOKAHEAD && strm.avail_in !== 0); + } // Copy without compression as much as possible from the input stream, + // return + // the current block state. + // This function does not insert new strings in the dictionary since + // uncompressible data is probably not useful. This function is used + // only for the level=0 compression option. + // NOTE: this function should be optimized to avoid extra copying from + // window to pending_buf. + + + function deflate_stored(flush) { + // Stored blocks are limited to 0xffff bytes, pending_buf is limited + // to pending_buf_size, and each stored block has a 5 byte header: + var max_block_size = 0xffff; + var max_start; + + if (max_block_size > pending_buf_size - 5) { + max_block_size = pending_buf_size - 5; + } // Copy as much as possible from input to output: + + + while (true) { + // Fill the window as much as possible: + if (lookahead <= 1) { + fill_window(); + if (lookahead === 0 && flush == Z_NO_FLUSH) return NeedMore; + if (lookahead === 0) break; // flush the current block + } + + strstart += lookahead; + lookahead = 0; // Emit a stored block if pending_buf will be full: + + max_start = block_start + max_block_size; + + if (strstart === 0 || strstart >= max_start) { + // strstart === 0 is possible when wraparound on 16-bit machine + lookahead = strstart - max_start; + strstart = max_start; + flush_block_only(false); + if (strm.avail_out === 0) return NeedMore; + } // Flush if we may have to slide, otherwise block_start may become + // negative and the data will be gone: + + + if (strstart - block_start >= w_size - MIN_LOOKAHEAD) { + flush_block_only(false); + if (strm.avail_out === 0) return NeedMore; + } + } + + flush_block_only(flush == Z_FINISH); + if (strm.avail_out === 0) return flush == Z_FINISH ? FinishStarted : NeedMore; + return flush == Z_FINISH ? FinishDone : BlockDone; + } + + function longest_match(cur_match) { + var chain_length = max_chain_length; // max hash chain length + + var scan = strstart; // current string + + var match; // matched string + + var len; // length of current match + + var best_len = prev_length; // best match length so far + + var limit = strstart > w_size - MIN_LOOKAHEAD ? strstart - (w_size - MIN_LOOKAHEAD) : 0; + var _nice_match = nice_match; // Stop when cur_match becomes <= limit. To simplify the code, + // we prevent matches with the string of window index 0. + + var wmask = w_mask; + var strend = strstart + MAX_MATCH; + var scan_end1 = window[scan + best_len - 1]; + var scan_end = window[scan + best_len]; // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of + // 16. + // It is easy to get rid of this optimization if necessary. + // Do not waste too much time if we already have a good match: + + if (prev_length >= good_match) { + chain_length >>= 2; + } // Do not look for matches beyond the end of the input. This is + // necessary + // to make deflate deterministic. + + + if (_nice_match > lookahead) _nice_match = lookahead; + + do { + match = cur_match; // Skip to next match if the match length cannot increase + // or if the match length is less than 2: + + if (window[match + best_len] != scan_end || window[match + best_len - 1] != scan_end1 || window[match] != window[scan] || window[++match] != window[scan + 1]) continue; // The check at best_len-1 can be removed because it will be made + // again later. (This heuristic is not always a win.) + // It is not necessary to compare scan[2] and match[2] since they + // are always equal when the other bytes match, given that + // the hash keys are equal and that HASH_BITS >= 8. + + scan += 2; + match++; // We check for insufficient lookahead only every 8th comparison; + // the 256th check will be made at strstart+258. + + do {} while (window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && scan < strend); + + len = MAX_MATCH - (strend - scan); + scan = strend - MAX_MATCH; + + if (len > best_len) { + match_start = cur_match; + best_len = len; + if (len >= _nice_match) break; + scan_end1 = window[scan + best_len - 1]; + scan_end = window[scan + best_len]; + } + } while ((cur_match = prev[cur_match & wmask] & 0xffff) > limit && --chain_length !== 0); + + if (best_len <= lookahead) return best_len; + return lookahead; + } // Compress as much as possible from the input stream, return the current + // block state. + // This function does not perform lazy evaluation of matches and inserts + // new strings in the dictionary only for unmatched strings or for short + // matches. It is used only for the fast compression options. + + + function deflate_fast(flush) { + // short hash_head = 0; // head of the hash chain + var hash_head = 0; // head of the hash chain + + var bflush; // set if current block must be flushed + + while (true) { + // Make sure that we always have enough lookahead, except + // at the end of the input file. We need MAX_MATCH bytes + // for the next match, plus MIN_MATCH bytes to insert the + // string following the next match. + if (lookahead < MIN_LOOKAHEAD) { + fill_window(); + + if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return NeedMore; + } + + if (lookahead === 0) break; // flush the current block + } // Insert the string window[strstart .. strstart+2] in the + // dictionary, and set hash_head to the head of the hash chain: + + + if (lookahead >= MIN_MATCH) { + ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h]; + + hash_head = head[ins_h] & 0xffff; + prev[strstart & w_mask] = head[ins_h]; + head[ins_h] = strstart; + } // Find the longest match, discarding those <= prev_length. + // At this point we have always match_length < MIN_MATCH + + + if (hash_head !== 0 && (strstart - hash_head & 0xffff) <= w_size - MIN_LOOKAHEAD) { + // To simplify the code, we prevent matches with the string + // of window index 0 (in particular we have to avoid a match + // of the string with itself at the start of the input file). + if (strategy != Z_HUFFMAN_ONLY) { + match_length = longest_match(hash_head); + } // longest_match() sets match_start + + } + + if (match_length >= MIN_MATCH) { + // check_match(strstart, match_start, match_length); + bflush = _tr_tally(strstart - match_start, match_length - MIN_MATCH); + lookahead -= match_length; // Insert new strings in the hash table only if the match length + // is not too large. This saves time but degrades compression. + + if (match_length <= max_lazy_match && lookahead >= MIN_MATCH) { + match_length--; // string at strstart already in hash table + + do { + strstart++; + ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h]; + + hash_head = head[ins_h] & 0xffff; + prev[strstart & w_mask] = head[ins_h]; + head[ins_h] = strstart; // strstart never exceeds WSIZE-MAX_MATCH, so there are + // always MIN_MATCH bytes ahead. + } while (--match_length !== 0); + + strstart++; + } else { + strstart += match_length; + match_length = 0; + ins_h = window[strstart] & 0xff; + ins_h = (ins_h << hash_shift ^ window[strstart + 1] & 0xff) & hash_mask; // If lookahead < MIN_MATCH, ins_h is garbage, but it does + // not + // matter since it will be recomputed at next deflate call. + } + } else { + // No match, output a literal byte + bflush = _tr_tally(0, window[strstart] & 0xff); + lookahead--; + strstart++; + } + + if (bflush) { + flush_block_only(false); + if (strm.avail_out === 0) return NeedMore; + } + } + + flush_block_only(flush == Z_FINISH); + + if (strm.avail_out === 0) { + if (flush == Z_FINISH) return FinishStarted;else return NeedMore; + } + + return flush == Z_FINISH ? FinishDone : BlockDone; + } // Same as above, but achieves better compression. We use a lazy + // evaluation for matches: a match is finally adopted only if there is + // no better match at the next window position. + + + function deflate_slow(flush) { + // short hash_head = 0; // head of hash chain + var hash_head = 0; // head of hash chain + + var bflush; // set if current block must be flushed + + var max_insert; // Process the input block. + + while (true) { + // Make sure that we always have enough lookahead, except + // at the end of the input file. We need MAX_MATCH bytes + // for the next match, plus MIN_MATCH bytes to insert the + // string following the next match. + if (lookahead < MIN_LOOKAHEAD) { + fill_window(); + + if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return NeedMore; + } + + if (lookahead === 0) break; // flush the current block + } // Insert the string window[strstart .. strstart+2] in the + // dictionary, and set hash_head to the head of the hash chain: + + + if (lookahead >= MIN_MATCH) { + ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h]; + + hash_head = head[ins_h] & 0xffff; + prev[strstart & w_mask] = head[ins_h]; + head[ins_h] = strstart; + } // Find the longest match, discarding those <= prev_length. + + + prev_length = match_length; + prev_match = match_start; + match_length = MIN_MATCH - 1; + + if (hash_head !== 0 && prev_length < max_lazy_match && (strstart - hash_head & 0xffff) <= w_size - MIN_LOOKAHEAD) { + // To simplify the code, we prevent matches with the string + // of window index 0 (in particular we have to avoid a match + // of the string with itself at the start of the input file). + if (strategy != Z_HUFFMAN_ONLY) { + match_length = longest_match(hash_head); + } // longest_match() sets match_start + + + if (match_length <= 5 && (strategy == Z_FILTERED || match_length == MIN_MATCH && strstart - match_start > 4096)) { + // If prev_match is also MIN_MATCH, match_start is garbage + // but we will ignore the current match anyway. + match_length = MIN_MATCH - 1; + } + } // If there was a match at the previous step and the current + // match is not better, output the previous match: + + + if (prev_length >= MIN_MATCH && match_length <= prev_length) { + max_insert = strstart + lookahead - MIN_MATCH; // Do not insert strings in hash table beyond this. + // check_match(strstart-1, prev_match, prev_length); + + bflush = _tr_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH); // Insert in hash table all strings up to the end of the match. + // strstart-1 and strstart are already inserted. If there is not + // enough lookahead, the last two strings are not inserted in + // the hash table. + + lookahead -= prev_length - 1; + prev_length -= 2; + + do { + if (++strstart <= max_insert) { + ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h]; + + hash_head = head[ins_h] & 0xffff; + prev[strstart & w_mask] = head[ins_h]; + head[ins_h] = strstart; + } + } while (--prev_length !== 0); + + match_available = 0; + match_length = MIN_MATCH - 1; + strstart++; + + if (bflush) { + flush_block_only(false); + if (strm.avail_out === 0) return NeedMore; + } + } else if (match_available !== 0) { + // If there was no match at the previous position, output a + // single literal. If there was a match but the current match + // is longer, truncate the previous match to a single literal. + bflush = _tr_tally(0, window[strstart - 1] & 0xff); + + if (bflush) { + flush_block_only(false); + } + + strstart++; + lookahead--; + if (strm.avail_out === 0) return NeedMore; + } else { + // There is no previous match to compare with, wait for + // the next step to decide. + match_available = 1; + strstart++; + lookahead--; + } + } + + if (match_available !== 0) { + bflush = _tr_tally(0, window[strstart - 1] & 0xff); + match_available = 0; + } + + flush_block_only(flush == Z_FINISH); + + if (strm.avail_out === 0) { + if (flush == Z_FINISH) return FinishStarted;else return NeedMore; + } + + return flush == Z_FINISH ? FinishDone : BlockDone; + } + + function deflateReset(strm) { + strm.total_in = strm.total_out = 0; + strm.msg = null; // + + that.pending = 0; + that.pending_out = 0; + status = BUSY_STATE; + last_flush = Z_NO_FLUSH; + tr_init(); + lm_init(); + return Z_OK; + } + + that.deflateInit = function (strm, _level, bits, _method, memLevel, _strategy) { + if (!_method) _method = Z_DEFLATED; + if (!memLevel) memLevel = DEF_MEM_LEVEL; + if (!_strategy) _strategy = Z_DEFAULT_STRATEGY; // byte[] my_version=ZLIB_VERSION; + // + // if (!version || version[0] != my_version[0] + // || stream_size != sizeof(z_stream)) { + // return Z_VERSION_ERROR; + // } + + strm.msg = null; + if (_level == Z_DEFAULT_COMPRESSION) _level = 6; + + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || _method != Z_DEFLATED || bits < 9 || bits > 15 || _level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + + strm.dstate = that; + w_bits = bits; + w_size = 1 << w_bits; + w_mask = w_size - 1; + hash_bits = memLevel + 7; + hash_size = 1 << hash_bits; + hash_mask = hash_size - 1; + hash_shift = Math.floor((hash_bits + MIN_MATCH - 1) / MIN_MATCH); + window = new Uint8Array(w_size * 2); + prev = []; + head = []; + lit_bufsize = 1 << memLevel + 6; // 16K elements by default + // We overlay pending_buf and d_buf+l_buf. This works since the average + // output size for (length,distance) codes is <= 24 bits. + + that.pending_buf = new Uint8Array(lit_bufsize * 4); + pending_buf_size = lit_bufsize * 4; + d_buf = Math.floor(lit_bufsize / 2); + l_buf = (1 + 2) * lit_bufsize; + level = _level; + strategy = _strategy; + return deflateReset(strm); + }; + + that.deflateEnd = function () { + if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) { + return Z_STREAM_ERROR; + } // Deallocate in reverse order of allocations: + + + that.pending_buf = null; + head = null; + prev = null; + window = null; // free + + that.dstate = null; + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; + }; + + that.deflateParams = function (strm, _level, _strategy) { + var err = Z_OK; + + if (_level == Z_DEFAULT_COMPRESSION) { + _level = 6; + } + + if (_level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + + if (config_table[level].func != config_table[_level].func && strm.total_in !== 0) { + // Flush the last buffer: + err = strm.deflate(Z_PARTIAL_FLUSH); + } + + if (level != _level) { + level = _level; + max_lazy_match = config_table[level].max_lazy; + good_match = config_table[level].good_length; + nice_match = config_table[level].nice_length; + max_chain_length = config_table[level].max_chain; + } + + strategy = _strategy; + return err; + }; + + that.deflateSetDictionary = function (strm, dictionary, dictLength) { + var length = dictLength; + var n, + index = 0; + if (!dictionary || status != INIT_STATE) return Z_STREAM_ERROR; + if (length < MIN_MATCH) return Z_OK; + + if (length > w_size - MIN_LOOKAHEAD) { + length = w_size - MIN_LOOKAHEAD; + index = dictLength - length; // use the tail of the dictionary + } + + window.set(dictionary.subarray(index, index + length), 0); + strstart = length; + block_start = length; // Insert all strings in the hash table (except for the last two bytes). + // s->lookahead stays null, so s->ins_h will be recomputed at the next + // call of fill_window. + + ins_h = window[0] & 0xff; + ins_h = (ins_h << hash_shift ^ window[1] & 0xff) & hash_mask; + + for (n = 0; n <= length - MIN_MATCH; n++) { + ins_h = (ins_h << hash_shift ^ window[n + (MIN_MATCH - 1)] & 0xff) & hash_mask; + prev[n & w_mask] = head[ins_h]; + head[ins_h] = n; + } + + return Z_OK; + }; + + that.deflate = function (_strm, flush) { + var i, header, level_flags, old_flush, bstate; + + if (flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + + if (!_strm.next_out || !_strm.next_in && _strm.avail_in !== 0 || status == FINISH_STATE && flush != Z_FINISH) { + _strm.msg = z_errmsg[Z_NEED_DICT - Z_STREAM_ERROR]; + return Z_STREAM_ERROR; + } + + if (_strm.avail_out === 0) { + _strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR]; + return Z_BUF_ERROR; + } + + strm = _strm; // just in case + + old_flush = last_flush; + last_flush = flush; // Write the zlib header + + if (status == INIT_STATE) { + header = Z_DEFLATED + (w_bits - 8 << 4) << 8; + level_flags = (level - 1 & 0xff) >> 1; + if (level_flags > 3) level_flags = 3; + header |= level_flags << 6; + if (strstart !== 0) header |= PRESET_DICT; + header += 31 - header % 31; + status = BUSY_STATE; + putShortMSB(header); + } // Flush as much pending output as possible + + + if (that.pending !== 0) { + strm.flush_pending(); + + if (strm.avail_out === 0) { + // console.log(" avail_out==0"); + // Since avail_out is 0, deflate will be called again with + // more output space, but possibly with both pending and + // avail_in equal to zero. There won't be anything to do, + // but this is not an error situation so make sure we + // return OK instead of BUF_ERROR at next call of deflate: + last_flush = -1; + return Z_OK; + } // Make sure there is something to do and avoid duplicate + // consecutive + // flushes. For repeated and useless calls with Z_FINISH, we keep + // returning Z_STREAM_END instead of Z_BUFF_ERROR. + + } else if (strm.avail_in === 0 && flush <= old_flush && flush != Z_FINISH) { + strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR]; + return Z_BUF_ERROR; + } // User must not provide more input after the first FINISH: + + + if (status == FINISH_STATE && strm.avail_in !== 0) { + _strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR]; + return Z_BUF_ERROR; + } // Start a new block or continue the current one. + + + if (strm.avail_in !== 0 || lookahead !== 0 || flush != Z_NO_FLUSH && status != FINISH_STATE) { + bstate = -1; + + switch (config_table[level].func) { + case STORED: + bstate = deflate_stored(flush); + break; + + case FAST: + bstate = deflate_fast(flush); + break; + + case SLOW: + bstate = deflate_slow(flush); + break; + + default: + } + + if (bstate == FinishStarted || bstate == FinishDone) { + status = FINISH_STATE; + } + + if (bstate == NeedMore || bstate == FinishStarted) { + if (strm.avail_out === 0) { + last_flush = -1; // avoid BUF_ERROR next call, see above + } + + return Z_OK; // If flush != Z_NO_FLUSH && avail_out === 0, the next call + // of deflate should use the same flush parameter to make sure + // that the flush is complete. So we don't have to output an + // empty block here, this will be done at next call. This also + // ensures that for a very small output buffer, we emit at most + // one empty block. + } + + if (bstate == BlockDone) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(); + } else { + // FULL_FLUSH or SYNC_FLUSH + _tr_stored_block(0, 0, false); // For a full flush, this empty block will be recognized + // as a special marker by inflate_sync(). + + + if (flush == Z_FULL_FLUSH) { + // state.head[s.hash_size-1]=0; + for (i = 0; i < hash_size + /*-1*/ + ; i++) // forget history + head[i] = 0; + } + } + + strm.flush_pending(); + + if (strm.avail_out === 0) { + last_flush = -1; // avoid BUF_ERROR at next call, see above + + return Z_OK; + } + } + } + + if (flush != Z_FINISH) return Z_OK; + return Z_STREAM_END; + }; + } // ZStream + + + function ZStream() { + var that = this; + that.next_in_index = 0; + that.next_out_index = 0; // that.next_in; // next input byte + + that.avail_in = 0; // number of bytes available at next_in + + that.total_in = 0; // total nb of input bytes read so far + // that.next_out; // next output byte should be put there + + that.avail_out = 0; // remaining free space at next_out + + that.total_out = 0; // total nb of bytes output so far + // that.msg; + // that.dstate; + } + + ZStream.prototype = { + deflateInit: function (level, bits) { + var that = this; + that.dstate = new Deflate(); + if (!bits) bits = MAX_BITS; + return that.dstate.deflateInit(that, level, bits); + }, + deflate: function (flush) { + var that = this; + + if (!that.dstate) { + return Z_STREAM_ERROR; + } + + return that.dstate.deflate(that, flush); + }, + deflateEnd: function () { + var that = this; + if (!that.dstate) return Z_STREAM_ERROR; + var ret = that.dstate.deflateEnd(); + that.dstate = null; + return ret; + }, + deflateParams: function (level, strategy) { + var that = this; + if (!that.dstate) return Z_STREAM_ERROR; + return that.dstate.deflateParams(that, level, strategy); + }, + deflateSetDictionary: function (dictionary, dictLength) { + var that = this; + if (!that.dstate) return Z_STREAM_ERROR; + return that.dstate.deflateSetDictionary(that, dictionary, dictLength); + }, + // Read a new buffer from the current input stream, update the + // total number of bytes read. All deflate() input goes through + // this function so some applications may wish to modify it to avoid + // allocating a large strm->next_in buffer and copying from it. + // (See also flush_pending()). + read_buf: function (buf, start, size) { + var that = this; + var len = that.avail_in; + if (len > size) len = size; + if (len === 0) return 0; + that.avail_in -= len; + buf.set(that.next_in.subarray(that.next_in_index, that.next_in_index + len), start); + that.next_in_index += len; + that.total_in += len; + return len; + }, + // Flush as much pending output as possible. All deflate() output goes + // through this function so some applications may wish to modify it + // to avoid allocating a large strm->next_out buffer and copying into it. + // (See also read_buf()). + flush_pending: function () { + var that = this; + var len = that.dstate.pending; + if (len > that.avail_out) len = that.avail_out; + if (len === 0) return; // if (that.dstate.pending_buf.length <= that.dstate.pending_out || that.next_out.length <= that.next_out_index + // || that.dstate.pending_buf.length < (that.dstate.pending_out + len) || that.next_out.length < (that.next_out_index + + // len)) { + // console.log(that.dstate.pending_buf.length + ", " + that.dstate.pending_out + ", " + that.next_out.length + ", " + + // that.next_out_index + ", " + len); + // console.log("avail_out=" + that.avail_out); + // } + + that.next_out.set(that.dstate.pending_buf.subarray(that.dstate.pending_out, that.dstate.pending_out + len), that.next_out_index); + that.next_out_index += len; + that.dstate.pending_out += len; + that.total_out += len; + that.avail_out -= len; + that.dstate.pending -= len; + + if (that.dstate.pending === 0) { + that.dstate.pending_out = 0; + } + } + }; // Deflater + + function Deflater(options) { + var that = this; + var z = new ZStream(); + var bufsize = 512; + var flush = Z_NO_FLUSH; + var buf = new Uint8Array(bufsize); + var level = options ? options.level : Z_DEFAULT_COMPRESSION; + if (typeof level == "undefined") level = Z_DEFAULT_COMPRESSION; + z.deflateInit(level); + z.next_out = buf; + + that.append = function (data, onprogress) { + var err, + buffers = [], + lastIndex = 0, + bufferIndex = 0, + bufferSize = 0, + array; + if (!data.length) return; + z.next_in_index = 0; + z.next_in = data; + z.avail_in = data.length; + + do { + z.next_out_index = 0; + z.avail_out = bufsize; + err = z.deflate(flush); + if (err != Z_OK) throw new Error("deflating: " + z.msg); + if (z.next_out_index) if (z.next_out_index == bufsize) buffers.push(new Uint8Array(buf));else buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index))); + bufferSize += z.next_out_index; + + if (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) { + onprogress(z.next_in_index); + lastIndex = z.next_in_index; + } + } while (z.avail_in > 0 || z.avail_out === 0); + + array = new Uint8Array(bufferSize); + buffers.forEach(function (chunk) { + array.set(chunk, bufferIndex); + bufferIndex += chunk.length; + }); + return array; + }; + + that.flush = function () { + var err, + buffers = [], + bufferIndex = 0, + bufferSize = 0, + array; + + do { + z.next_out_index = 0; + z.avail_out = bufsize; + err = z.deflate(Z_FINISH); + if (err != Z_STREAM_END && err != Z_OK) throw new Error("deflating: " + z.msg); + if (bufsize - z.avail_out > 0) buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index))); + bufferSize += z.next_out_index; + } while (z.avail_in > 0 || z.avail_out === 0); + + z.deflateEnd(); + array = new Uint8Array(bufferSize); + buffers.forEach(function (chunk) { + array.set(chunk, bufferIndex); + bufferIndex += chunk.length; + }); + return array; + }; + } // 'zip' may not be defined in z-worker and some tests + + + var env = global.zip || global; + env.Deflater = env._jzlib_Deflater = Deflater; + })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")()); // `self` is undefined in Firefox for Android content script context + // while `this` is nsIContentFrameMessageManager + // with an attribute `content` that corresponds to the window + + /** + * A class to parse color values + * @author Stoyan Stefanov + * @link http://www.phpied.com/rgb-color-parser-in-javascript/ + * @license Use it if you like it + */ + (function (global) { + + function RGBColor(color_string) { + this.ok = false; // strip any leading # + + if (color_string.charAt(0) == "#") { + // remove # if any + color_string = color_string.substr(1, 6); + } + + color_string = color_string.replace(/ /g, ""); + color_string = color_string.toLowerCase(); + var channels; // before getting into regexps, try simple matches + // and overwrite the input + + var simple_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", + feldspar: "d19275", + 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", + lightslateblue: "8470ff", + 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", + violetred: "d02090", + wheat: "f5deb3", + white: "ffffff", + whitesmoke: "f5f5f5", + yellow: "ffff00", + yellowgreen: "9acd32" + }; + + for (var key in simple_colors) { + if (color_string == key) { + color_string = simple_colors[key]; + } + } // emd of simple type-in colors + // array of color definition objects + + + var color_defs = [{ + re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, + example: ["rgb(123, 234, 45)", "rgb(255,234,245)"], + process: function (bits) { + return [parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3])]; + } + }, { + re: /^(\w{2})(\w{2})(\w{2})$/, + example: ["#00ff00", "336699"], + process: function (bits) { + return [parseInt(bits[1], 16), parseInt(bits[2], 16), parseInt(bits[3], 16)]; + } + }, { + re: /^(\w{1})(\w{1})(\w{1})$/, + example: ["#fb0", "f0f"], + process: function (bits) { + return [parseInt(bits[1] + bits[1], 16), parseInt(bits[2] + bits[2], 16), parseInt(bits[3] + bits[3], 16)]; + } + }]; // search through the definitions to find a match + + for (var i = 0; i < color_defs.length; i++) { + var re = color_defs[i].re; + var processor = color_defs[i].process; + var bits = re.exec(color_string); + + if (bits) { + channels = processor(bits); + this.r = channels[0]; + this.g = channels[1]; + this.b = channels[2]; + this.ok = true; + } + } // validate/cleanup values + + + this.r = this.r < 0 || isNaN(this.r) ? 0 : this.r > 255 ? 255 : this.r; + this.g = this.g < 0 || isNaN(this.g) ? 0 : this.g > 255 ? 255 : this.g; + this.b = this.b < 0 || isNaN(this.b) ? 0 : this.b > 255 ? 255 : this.b; // some getters + + this.toRGB = function () { + return "rgb(" + this.r + ", " + this.g + ", " + this.b + ")"; + }; + + this.toHex = function () { + var r = this.r.toString(16); + var g = this.g.toString(16); + var b = this.b.toString(16); + if (r.length == 1) r = "0" + r; + if (g.length == 1) g = "0" + g; + if (b.length == 1) b = "0" + b; + return "#" + r + g + b; + }; // help + + + this.getHelpXML = function () { + var examples = new Array(); // add regexps + + for (var i = 0; i < color_defs.length; i++) { + var example = color_defs[i].example; + + for (var j = 0; j < example.length; j++) { + examples[examples.length] = example[j]; + } + } // add type-in colors + + + for (var sc in simple_colors) { + examples[examples.length] = sc; + } + + var xml = document.createElement("ul"); + xml.setAttribute("id", "rgbcolor-examples"); + + for (var i = 0; i < examples.length; i++) { + try { + var list_item = document.createElement("li"); + var list_color = new RGBColor(examples[i]); + var example_div = document.createElement("div"); + example_div.style.cssText = "margin: 3px; " + "border: 1px solid black; " + "background:" + list_color.toHex() + "; " + "color:" + list_color.toHex(); + example_div.appendChild(document.createTextNode("test")); + var list_item_value = document.createTextNode(" " + examples[i] + " -> " + list_color.toRGB() + " -> " + list_color.toHex()); + list_item.appendChild(example_div); + list_item.appendChild(list_item_value); + xml.appendChild(list_item); + } catch (e) {} + } + + return xml; + }; + } + + global.RGBColor = RGBColor; + })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")()); // `self` is undefined in Firefox for Android content script context + // while `this` is nsIContentFrameMessageManager + // with an attribute `content` that corresponds to the window + + /************************************************ + * Title : custom font * + * Start Data : 2017. 01. 22. * + * Comment : TEXT API * + ************************************************/ + + /****************************** + * jsPDF extension API Design * + * ****************************/ + (function (jsPDF) { + + var PLUS = "+".charCodeAt(0); + var SLASH = "/".charCodeAt(0); + var NUMBER = "0".charCodeAt(0); + var LOWER = "a".charCodeAt(0); + var UPPER = "A".charCodeAt(0); + var PLUS_URL_SAFE = "-".charCodeAt(0); + var SLASH_URL_SAFE = "_".charCodeAt(0); + /*****************************************************************/ + + /* function : b64ToByteArray */ + + /* comment : Base64 encoded TTF file contents (b64) are decoded */ + + /* by Byte array and stored. */ + + /*****************************************************************/ + + var b64ToByteArray = function (b64) { + var i, j, l, tmp, placeHolders, arr; + + if (b64.length % 4 > 0) { + throw new Error("Invalid string. Length must be a multiple of 4"); + } // the number of equal signs (place holders) + // if there are two placeholders, than the two characters before it + // represent one byte + // if there is only one, then the three characters before it represent 2 bytes + // this is just a cheap hack to not do indexOf twice + + + var len = b64.length; + placeHolders = "=" === b64.charAt(len - 2) ? 2 : "=" === b64.charAt(len - 1) ? 1 : 0; // base64 is 4/3 + up to two characters of the original data + + arr = new Uint8Array(b64.length * 3 / 4 - placeHolders); // if there are placeholders, only get up to the last complete 4 chars + + l = placeHolders > 0 ? b64.length - 4 : b64.length; + var L = 0; + + function push(v) { + arr[L++] = v; + } + + for (i = 0, j = 0; i < l; i += 4, j += 3) { + tmp = decode(b64.charAt(i)) << 18 | decode(b64.charAt(i + 1)) << 12 | decode(b64.charAt(i + 2)) << 6 | decode(b64.charAt(i + 3)); + push((tmp & 0xff0000) >> 16); + push((tmp & 0xff00) >> 8); + push(tmp & 0xff); + } + + if (placeHolders === 2) { + tmp = decode(b64.charAt(i)) << 2 | decode(b64.charAt(i + 1)) >> 4; + push(tmp & 0xff); + } else if (placeHolders === 1) { + tmp = decode(b64.charAt(i)) << 10 | decode(b64.charAt(i + 1)) << 4 | decode(b64.charAt(i + 2)) >> 2; + push(tmp >> 8 & 0xff); + push(tmp & 0xff); + } + + return arr; + }; + /***************************************************************/ + + /* function : decode */ + + /* comment : Change the base64 encoded font's content to match */ + + /* the base64 index value. */ + + /***************************************************************/ + + + var decode = function (elt) { + var code = elt.charCodeAt(0); + if (code === PLUS || code === PLUS_URL_SAFE) return 62; // '+' + + if (code === SLASH || code === SLASH_URL_SAFE) return 63; // '/' + + if (code < NUMBER) return -1; //no match + + if (code < NUMBER + 10) return code - NUMBER + 26 + 26; + if (code < UPPER + 26) return code - UPPER; + if (code < LOWER + 26) return code - LOWER + 26; + }; + + jsPDF.API.TTFFont = function () { + /************************************************************************/ + + /* function : open */ + + /* comment : Decode the encoded ttf content and create a TTFFont object. */ + + /************************************************************************/ + TTFFont.open = function (filename, name, vfs, encoding) { + var contents; + + if (typeof vfs !== "string") { + throw new Error("Invalid argument supplied in TTFFont.open"); + } + + contents = b64ToByteArray(vfs); + return new TTFFont(contents, name, encoding); + }; + /***************************************************************/ + + /* function : TTFFont gernerator */ + + /* comment : Decode TTF contents are parsed, Data, */ + + /* Subset object is created, and registerTTF function is called.*/ + + /***************************************************************/ + + + function TTFFont(rawData, name, encoding) { + var data; + + this.rawData = rawData; + data = this.contents = new Data(rawData); + this.contents.pos = 4; + + if (data.readString(4) === "ttcf") { + if (!name) { + throw new Error("Must specify a font name for TTC files."); + } + throw new Error("Font " + name + " not found in TTC file."); + } else { + data.pos = 0; + this.parse(); + this.subset = new Subset(this); + this.registerTTF(); + } + } + /********************************************************/ + + /* function : parse */ + + /* comment : TTF Parses the file contents by each table.*/ + + /********************************************************/ + + + TTFFont.prototype.parse = function () { + this.directory = new Directory(this.contents); + this.head = new HeadTable(this); + this.name = new NameTable(this); + this.cmap = new CmapTable(this); + this.toUnicode = new Map(); + this.hhea = new HheaTable(this); + this.maxp = new MaxpTable(this); + this.hmtx = new HmtxTable(this); + this.post = new PostTable(this); + this.os2 = new OS2Table(this); + this.loca = new LocaTable(this); + this.glyf = new GlyfTable(this); + this.ascender = this.os2.exists && this.os2.ascender || this.hhea.ascender; + this.decender = this.os2.exists && this.os2.decender || this.hhea.decender; + this.lineGap = this.os2.exists && this.os2.lineGap || this.hhea.lineGap; + return this.bbox = [this.head.xMin, this.head.yMin, this.head.xMax, this.head.yMax]; + }; + /***************************************************************/ + + /* function : registerTTF */ + + /* comment : Get the value to assign pdf font descriptors. */ + + /***************************************************************/ + + + TTFFont.prototype.registerTTF = function () { + var e, hi, low, raw, _ref; + + this.scaleFactor = 1000.0 / this.head.unitsPerEm; + + this.bbox = function () { + var _i, _len, _ref, _results; + + _ref = this.bbox; + _results = []; + + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + e = _ref[_i]; + + _results.push(Math.round(e * this.scaleFactor)); + } + + return _results; + }.call(this); + + this.stemV = 0; + + if (this.post.exists) { + raw = this.post.italic_angle; + hi = raw >> 16; + low = raw & 0xff; + + if (hi & 0x8000 !== 0) { + hi = -((hi ^ 0xffff) + 1); + } + + this.italicAngle = +("" + hi + "." + low); + } else { + this.italicAngle = 0; + } + + this.ascender = Math.round(this.ascender * this.scaleFactor); + this.decender = Math.round(this.decender * this.scaleFactor); + this.lineGap = Math.round(this.lineGap * this.scaleFactor); + this.capHeight = this.os2.exists && this.os2.capHeight || this.ascender; + this.xHeight = this.os2.exists && this.os2.xHeight || 0; + this.familyClass = (this.os2.exists && this.os2.familyClass || 0) >> 8; + this.isSerif = (_ref = this.familyClass) === 1 || _ref === 2 || _ref === 3 || _ref === 4 || _ref === 5 || _ref === 7; + this.isScript = this.familyClass === 10; + this.flags = 0; + + if (this.post.isFixedPitch) { + this.flags |= 1 << 0; + } + + if (this.isSerif) { + this.flags |= 1 << 1; + } + + if (this.isScript) { + this.flags |= 1 << 3; + } + + if (this.italicAngle !== 0) { + this.flags |= 1 << 6; + } + + this.flags |= 1 << 5; + + if (!this.cmap.unicode) { + throw new Error("No unicode cmap for font"); + } + }; + + TTFFont.prototype.characterToGlyph = function (character) { + var _ref; + + return ((_ref = this.cmap.unicode) != null ? _ref.codeMap[character] : void 0) || 0; + }; + + TTFFont.prototype.widthOfGlyph = function (glyph) { + var scale; + scale = 1000.0 / this.head.unitsPerEm; + return this.hmtx.forGlyph(glyph).advance * scale; + }; + + TTFFont.prototype.widthOfString = function (string, size, charSpace) { + var charCode, i, scale, width, _i, _ref, charSpace; + + string = "" + string; + width = 0; + + for (i = _i = 0, _ref = string.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + charCode = string.charCodeAt(i); + width += this.widthOfGlyph(this.characterToGlyph(charCode)) + charSpace * (1000 / size) || 0; + } + + scale = size / 1000; + return width * scale; + }; + + TTFFont.prototype.lineHeight = function (size, includeGap) { + var gap; + + if (includeGap == null) { + includeGap = false; + } + + gap = includeGap ? this.lineGap : 0; + return (this.ascender + gap - this.decender) / 1000 * size; + }; + + return TTFFont; + }(); + /************************************************************************************************/ + + /* function : Data */ + + /* comment : The ttf data decoded and stored in an array is read and written to the Data object.*/ + + /************************************************************************************************/ + + + var Data = function () { + function Data(data) { + this.data = data != null ? data : []; + this.pos = 0; + this.length = this.data.length; + } + + Data.prototype.readByte = function () { + return this.data[this.pos++]; + }; + + Data.prototype.writeByte = function (byte) { + return this.data[this.pos++] = byte; + }; + + Data.prototype.readUInt32 = function () { + var b1, b2, b3, b4; + b1 = this.readByte() * 0x1000000; + b2 = this.readByte() << 16; + b3 = this.readByte() << 8; + b4 = this.readByte(); + return b1 + b2 + b3 + b4; + }; + + Data.prototype.writeUInt32 = function (val) { + this.writeByte(val >>> 24 & 0xff); + this.writeByte(val >> 16 & 0xff); + this.writeByte(val >> 8 & 0xff); + return this.writeByte(val & 0xff); + }; + + Data.prototype.readInt32 = function () { + var int; + int = this.readUInt32(); + + if (int >= 0x80000000) { + return int - 0x100000000; + } else { + return int; + } + }; + + Data.prototype.writeInt32 = function (val) { + if (val < 0) { + val += 0x100000000; + } + + return this.writeUInt32(val); + }; + + Data.prototype.readUInt16 = function () { + var b1, b2; + b1 = this.readByte() << 8; + b2 = this.readByte(); + return b1 | b2; + }; + + Data.prototype.writeUInt16 = function (val) { + this.writeByte(val >> 8 & 0xff); + return this.writeByte(val & 0xff); + }; + + Data.prototype.readInt16 = function () { + var int; + int = this.readUInt16(); + + if (int >= 0x8000) { + return int - 0x10000; + } else { + return int; + } + }; + + Data.prototype.writeInt16 = function (val) { + if (val < 0) { + val += 0x10000; + } + + return this.writeUInt16(val); + }; + + Data.prototype.readString = function (length) { + var i, ret, _i; + + ret = []; + + for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) { + ret[i] = String.fromCharCode(this.readByte()); + } + + return ret.join(""); + }; + + Data.prototype.writeString = function (val) { + var i, _i, _ref, _results; + + _results = []; + + for (i = _i = 0, _ref = val.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + _results.push(this.writeByte(val.charCodeAt(i))); + } + + return _results; + }; + /*Data.prototype.stringAt = function (pos, length) { + this.pos = pos; + return this.readString(length); + };*/ + + + Data.prototype.readShort = function () { + return this.readInt16(); + }; + + Data.prototype.writeShort = function (val) { + return this.writeInt16(val); + }; + + Data.prototype.readLongLong = function () { + var b1, b2, b3, b4, b5, b6, b7, b8; + b1 = this.readByte(); + b2 = this.readByte(); + b3 = this.readByte(); + b4 = this.readByte(); + b5 = this.readByte(); + b6 = this.readByte(); + b7 = this.readByte(); + b8 = this.readByte(); + + if (b1 & 0x80) { + return ((b1 ^ 0xff) * 0x100000000000000 + (b2 ^ 0xff) * 0x1000000000000 + (b3 ^ 0xff) * 0x10000000000 + (b4 ^ 0xff) * 0x100000000 + (b5 ^ 0xff) * 0x1000000 + (b6 ^ 0xff) * 0x10000 + (b7 ^ 0xff) * 0x100 + (b8 ^ 0xff) + 1) * -1; + } + + return b1 * 0x100000000000000 + b2 * 0x1000000000000 + b3 * 0x10000000000 + b4 * 0x100000000 + b5 * 0x1000000 + b6 * 0x10000 + b7 * 0x100 + b8; + }; + + Data.prototype.writeLongLong = function (val) { + var high, low; + high = Math.floor(val / 0x100000000); + low = val & 0xffffffff; + this.writeByte(high >> 24 & 0xff); + this.writeByte(high >> 16 & 0xff); + this.writeByte(high >> 8 & 0xff); + this.writeByte(high & 0xff); + this.writeByte(low >> 24 & 0xff); + this.writeByte(low >> 16 & 0xff); + this.writeByte(low >> 8 & 0xff); + return this.writeByte(low & 0xff); + }; + + Data.prototype.readInt = function () { + return this.readInt32(); + }; + + Data.prototype.writeInt = function (val) { + return this.writeInt32(val); + }; + /*Data.prototype.slice = function (start, end) { + return this.data.slice(start, end); + };*/ + + + Data.prototype.read = function (bytes) { + var buf, i, _i; + + buf = []; + + for (i = _i = 0; 0 <= bytes ? _i < bytes : _i > bytes; i = 0 <= bytes ? ++_i : --_i) { + buf.push(this.readByte()); + } + + return buf; + }; + + Data.prototype.write = function (bytes) { + var byte, _i, _len, _results; + + _results = []; + + for (_i = 0, _len = bytes.length; _i < _len; _i++) { + byte = bytes[_i]; + + _results.push(this.writeByte(byte)); + } + + return _results; + }; + + return Data; + }(); + + var Directory = function () { + var checksum; + /*****************************************************************************************************/ + + /* function : Directory generator */ + + /* comment : Initialize the offset, tag, length, and checksum for each table for the font to be used.*/ + + /*****************************************************************************************************/ + + function Directory(data) { + var entry, i, _i, _ref; + + this.scalarType = data.readInt(); + this.tableCount = data.readShort(); + this.searchRange = data.readShort(); + this.entrySelector = data.readShort(); + this.rangeShift = data.readShort(); + this.tables = {}; + + for (i = _i = 0, _ref = this.tableCount; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + entry = { + tag: data.readString(4), + checksum: data.readInt(), + offset: data.readInt(), + length: data.readInt() + }; + this.tables[entry.tag] = entry; + } + } + /********************************************************************************************************/ + + /* function : encode */ + + /* comment : It encodes and stores the font table object and information used for the directory object. */ + + /********************************************************************************************************/ + + + Directory.prototype.encode = function (tables) { + var adjustment, directory, directoryLength, entrySelector, headOffset, log2, offset, rangeShift, searchRange, sum, table, tableCount, tableData, tag; + tableCount = Object.keys(tables).length; + log2 = Math.log(2); + searchRange = Math.floor(Math.log(tableCount) / log2) * 16; + entrySelector = Math.floor(searchRange / log2); + rangeShift = tableCount * 16 - searchRange; + directory = new Data(); + directory.writeInt(this.scalarType); + directory.writeShort(tableCount); + directory.writeShort(searchRange); + directory.writeShort(entrySelector); + directory.writeShort(rangeShift); + directoryLength = tableCount * 16; + offset = directory.pos + directoryLength; + headOffset = null; + tableData = []; + + for (tag in tables) { + table = tables[tag]; + directory.writeString(tag); + directory.writeInt(checksum(table)); + directory.writeInt(offset); + directory.writeInt(table.length); + tableData = tableData.concat(table); + + if (tag === "head") { + headOffset = offset; + } + + offset += table.length; + + while (offset % 4) { + tableData.push(0); + offset++; + } + } + + directory.write(tableData); + sum = checksum(directory.data); + adjustment = 0xb1b0afba - sum; + directory.pos = headOffset + 8; + directory.writeUInt32(adjustment); + return directory.data; + }; + /***************************************************************/ + + /* function : checksum */ + + /* comment : Duplicate the table for the tag. */ + + /***************************************************************/ + + + checksum = function (data) { + var i, sum, tmp, _i, _ref; + + data = __slice.call(data); + + while (data.length % 4) { + data.push(0); + } + + tmp = new Data(data); + sum = 0; + + for (i = _i = 0, _ref = data.length; _i < _ref; i = _i += 4) { + sum += tmp.readUInt32(); + } + + return sum & 0xffffffff; + }; + + return Directory; + }(); + + var Table, + __hasProp = {}.hasOwnProperty, + __extends = function (child, parent) { + for (var key in parent) { + if (__hasProp.call(parent, key)) child[key] = parent[key]; + } + + function ctor() { + this.constructor = child; + } + + ctor.prototype = parent.prototype; + child.prototype = new ctor(); + child.__super__ = parent.prototype; + return child; + }; + /***************************************************************/ + + /* function : Table */ + + /* comment : Save info for each table, and parse the table. */ + + /***************************************************************/ + + + Table = function () { + function Table(file) { + var info; + this.file = file; + info = this.file.directory.tables[this.tag]; + this.exists = !!info; + + if (info) { + this.offset = info.offset, this.length = info.length; + this.parse(this.file.contents); + } + } + + Table.prototype.parse = function () {}; + + Table.prototype.encode = function () {}; + + Table.prototype.raw = function () { + if (!this.exists) { + return null; + } + + this.file.contents.pos = this.offset; + return this.file.contents.read(this.length); + }; + + return Table; + }(); + + var HeadTable = function (_super) { + __extends(HeadTable, _super); + + function HeadTable() { + return HeadTable.__super__.constructor.apply(this, arguments); + } + + HeadTable.prototype.tag = "head"; + + HeadTable.prototype.parse = function (data) { + data.pos = this.offset; + this.version = data.readInt(); + this.revision = data.readInt(); + this.checkSumAdjustment = data.readInt(); + this.magicNumber = data.readInt(); + this.flags = data.readShort(); + this.unitsPerEm = data.readShort(); + this.created = data.readLongLong(); + this.modified = data.readLongLong(); + this.xMin = data.readShort(); + this.yMin = data.readShort(); + this.xMax = data.readShort(); + this.yMax = data.readShort(); + this.macStyle = data.readShort(); + this.lowestRecPPEM = data.readShort(); + this.fontDirectionHint = data.readShort(); + this.indexToLocFormat = data.readShort(); + return this.glyphDataFormat = data.readShort(); + }; + + HeadTable.prototype.encode = function (indexToLocFormat) { + var table; + table = new Data(); + table.writeInt(this.version); + table.writeInt(this.revision); + table.writeInt(this.checkSumAdjustment); + table.writeInt(this.magicNumber); + table.writeShort(this.flags); + table.writeShort(this.unitsPerEm); + table.writeLongLong(this.created); + table.writeLongLong(this.modified); + table.writeShort(this.xMin); + table.writeShort(this.yMin); + table.writeShort(this.xMax); + table.writeShort(this.yMax); + table.writeShort(this.macStyle); + table.writeShort(this.lowestRecPPEM); + table.writeShort(this.fontDirectionHint); + table.writeShort(indexToLocFormat); + table.writeShort(this.glyphDataFormat); + return table.data; + }; + + return HeadTable; + }(Table); + /************************************************************************************/ + + /* function : CmapEntry */ + + /* comment : Cmap Initializes and encodes object information (required by pdf spec).*/ + + /************************************************************************************/ + + + var CmapEntry = function () { + function CmapEntry(data, offset) { + var code, count, endCode, glyphId, glyphIds, i, idDelta, idRangeOffset, index, saveOffset, segCount, segCountX2, start, startCode, tail, _i, _j, _k, _len; + + this.platformID = data.readUInt16(); + this.encodingID = data.readShort(); + this.offset = offset + data.readInt(); + saveOffset = data.pos; + data.pos = this.offset; + this.format = data.readUInt16(); + this.length = data.readUInt16(); + this.language = data.readUInt16(); + this.isUnicode = this.platformID === 3 && this.encodingID === 1 && this.format === 4 || this.platformID === 0 && this.format === 4; + this.codeMap = {}; + + switch (this.format) { + case 0: + for (i = _i = 0; _i < 256; i = ++_i) { + this.codeMap[i] = data.readByte(); + } + + break; + + case 4: + segCountX2 = data.readUInt16(); + segCount = segCountX2 / 2; + data.pos += 6; + + endCode = function () { + var _j, _results; + + _results = []; + + for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) { + _results.push(data.readUInt16()); + } + + return _results; + }(); + + data.pos += 2; + + startCode = function () { + var _j, _results; + + _results = []; + + for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) { + _results.push(data.readUInt16()); + } + + return _results; + }(); + + idDelta = function () { + var _j, _results; + + _results = []; + + for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) { + _results.push(data.readUInt16()); + } + + return _results; + }(); + + idRangeOffset = function () { + var _j, _results; + + _results = []; + + for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) { + _results.push(data.readUInt16()); + } + + return _results; + }(); + + count = (this.length - data.pos + this.offset) / 2; + + glyphIds = function () { + var _j, _results; + + _results = []; + + for (i = _j = 0; 0 <= count ? _j < count : _j > count; i = 0 <= count ? ++_j : --_j) { + _results.push(data.readUInt16()); + } + + return _results; + }(); + + for (i = _j = 0, _len = endCode.length; _j < _len; i = ++_j) { + tail = endCode[i]; + start = startCode[i]; + + for (code = _k = start; start <= tail ? _k <= tail : _k >= tail; code = start <= tail ? ++_k : --_k) { + if (idRangeOffset[i] === 0) { + glyphId = code + idDelta[i]; + } else { + index = idRangeOffset[i] / 2 + (code - start) - (segCount - i); + glyphId = glyphIds[index] || 0; + + if (glyphId !== 0) { + glyphId += idDelta[i]; + } + } + + this.codeMap[code] = glyphId & 0xffff; + } + } + + } + + data.pos = saveOffset; + } + + CmapEntry.encode = function (charmap, encoding) { + var charMap, code, codeMap, codes, delta, deltas, diff, endCode, endCodes, entrySelector, glyphIDs, i, id, indexes, last, map, nextID, offset, old, rangeOffsets, rangeShift, result, searchRange, segCount, segCountX2, startCode, startCodes, startGlyph, subtable, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _len6, _len7, _m, _n, _name, _o, _p, _q; + + subtable = new Data(); + codes = Object.keys(charmap).sort(function (a, b) { + return a - b; + }); + + switch (encoding) { + case "macroman": + id = 0; + + indexes = function () { + var _i, _results; + + _results = []; + + for (i = _i = 0; _i < 256; i = ++_i) { + _results.push(0); + } + + return _results; + }(); + + map = { + 0: 0 + }; + codeMap = {}; + + for (_i = 0, _len = codes.length; _i < _len; _i++) { + code = codes[_i]; + + if (map[_name = charmap[code]] == null) { + map[_name] = ++id; + } + + codeMap[code] = { + old: charmap[code], + new: map[charmap[code]] + }; + indexes[code] = map[charmap[code]]; + } + + subtable.writeUInt16(1); + subtable.writeUInt16(0); + subtable.writeUInt32(12); + subtable.writeUInt16(0); + subtable.writeUInt16(262); + subtable.writeUInt16(0); + subtable.write(indexes); + return result = { + charMap: codeMap, + subtable: subtable.data, + maxGlyphID: id + 1 + }; + + case "unicode": + startCodes = []; + endCodes = []; + nextID = 0; + map = {}; + charMap = {}; + last = diff = null; + + for (_j = 0, _len1 = codes.length; _j < _len1; _j++) { + code = codes[_j]; + old = charmap[code]; + + if (map[old] == null) { + map[old] = ++nextID; + } + + charMap[code] = { + old: old, + new: map[old] + }; + delta = map[old] - code; + + if (last == null || delta !== diff) { + if (last) { + endCodes.push(last); + } + + startCodes.push(code); + diff = delta; + } + + last = code; + } + + if (last) { + endCodes.push(last); + } + + endCodes.push(0xffff); + startCodes.push(0xffff); + segCount = startCodes.length; + segCountX2 = segCount * 2; + searchRange = 2 * Math.pow(Math.log(segCount) / Math.LN2, 2); + entrySelector = Math.log(searchRange / 2) / Math.LN2; + rangeShift = 2 * segCount - searchRange; + deltas = []; + rangeOffsets = []; + glyphIDs = []; + + for (i = _k = 0, _len2 = startCodes.length; _k < _len2; i = ++_k) { + startCode = startCodes[i]; + endCode = endCodes[i]; + + if (startCode === 0xffff) { + deltas.push(0); + rangeOffsets.push(0); + break; + } + + startGlyph = charMap[startCode]["new"]; + + if (startCode - startGlyph >= 0x8000) { + deltas.push(0); + rangeOffsets.push(2 * (glyphIDs.length + segCount - i)); + + for (code = _l = startCode; startCode <= endCode ? _l <= endCode : _l >= endCode; code = startCode <= endCode ? ++_l : --_l) { + glyphIDs.push(charMap[code]["new"]); + } + } else { + deltas.push(startGlyph - startCode); + rangeOffsets.push(0); + } + } + + subtable.writeUInt16(3); + subtable.writeUInt16(1); + subtable.writeUInt32(12); + subtable.writeUInt16(4); + subtable.writeUInt16(16 + segCount * 8 + glyphIDs.length * 2); + subtable.writeUInt16(0); + subtable.writeUInt16(segCountX2); + subtable.writeUInt16(searchRange); + subtable.writeUInt16(entrySelector); + subtable.writeUInt16(rangeShift); + + for (_m = 0, _len3 = endCodes.length; _m < _len3; _m++) { + code = endCodes[_m]; + subtable.writeUInt16(code); + } + + subtable.writeUInt16(0); + + for (_n = 0, _len4 = startCodes.length; _n < _len4; _n++) { + code = startCodes[_n]; + subtable.writeUInt16(code); + } + + for (_o = 0, _len5 = deltas.length; _o < _len5; _o++) { + delta = deltas[_o]; + subtable.writeUInt16(delta); + } + + for (_p = 0, _len6 = rangeOffsets.length; _p < _len6; _p++) { + offset = rangeOffsets[_p]; + subtable.writeUInt16(offset); + } + + for (_q = 0, _len7 = glyphIDs.length; _q < _len7; _q++) { + id = glyphIDs[_q]; + subtable.writeUInt16(id); + } + + return result = { + charMap: charMap, + subtable: subtable.data, + maxGlyphID: nextID + 1 + }; + } + }; + + return CmapEntry; + }(); + + var CmapTable = function (_super) { + __extends(CmapTable, _super); + + function CmapTable() { + return CmapTable.__super__.constructor.apply(this, arguments); + } + + CmapTable.prototype.tag = "cmap"; + + CmapTable.prototype.parse = function (data) { + var entry, i, tableCount, _i; + + data.pos = this.offset; + this.version = data.readUInt16(); + tableCount = data.readUInt16(); + this.tables = []; + this.unicode = null; + + for (i = _i = 0; 0 <= tableCount ? _i < tableCount : _i > tableCount; i = 0 <= tableCount ? ++_i : --_i) { + entry = new CmapEntry(data, this.offset); + this.tables.push(entry); + + if (entry.isUnicode) { + if (this.unicode == null) { + this.unicode = entry; + } + } + } + + return true; + }; + /*************************************************************************/ + + /* function : encode */ + + /* comment : Encode the cmap table corresponding to the input character. */ + + /*************************************************************************/ + + + CmapTable.encode = function (charmap, encoding) { + var result, table; + + if (encoding == null) { + encoding = "macroman"; + } + + result = CmapEntry.encode(charmap, encoding); + table = new Data(); + table.writeUInt16(0); + table.writeUInt16(1); + result.table = table.data.concat(result.subtable); + return result; + }; + + return CmapTable; + }(Table); + + var HheaTable = function (_super) { + __extends(HheaTable, _super); + + function HheaTable() { + return HheaTable.__super__.constructor.apply(this, arguments); + } + + HheaTable.prototype.tag = "hhea"; + + HheaTable.prototype.parse = function (data) { + data.pos = this.offset; + this.version = data.readInt(); + this.ascender = data.readShort(); + this.decender = data.readShort(); + this.lineGap = data.readShort(); + this.advanceWidthMax = data.readShort(); + this.minLeftSideBearing = data.readShort(); + this.minRightSideBearing = data.readShort(); + this.xMaxExtent = data.readShort(); + this.caretSlopeRise = data.readShort(); + this.caretSlopeRun = data.readShort(); + this.caretOffset = data.readShort(); + data.pos += 4 * 2; + this.metricDataFormat = data.readShort(); + return this.numberOfMetrics = data.readUInt16(); + }; + /*HheaTable.prototype.encode = function (ids) { + var i, table, _i, _ref; + table = new Data; + table.writeInt(this.version); + table.writeShort(this.ascender); + table.writeShort(this.decender); + table.writeShort(this.lineGap); + table.writeShort(this.advanceWidthMax); + table.writeShort(this.minLeftSideBearing); + table.writeShort(this.minRightSideBearing); + table.writeShort(this.xMaxExtent); + table.writeShort(this.caretSlopeRise); + table.writeShort(this.caretSlopeRun); + table.writeShort(this.caretOffset); + for (i = _i = 0, _ref = 4 * 2; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + table.writeByte(0); + } + table.writeShort(this.metricDataFormat); + table.writeUInt16(ids.length); + return table.data; + };*/ + + + return HheaTable; + }(Table); + + var OS2Table = function (_super) { + __extends(OS2Table, _super); + + function OS2Table() { + return OS2Table.__super__.constructor.apply(this, arguments); + } + + OS2Table.prototype.tag = "OS/2"; + + OS2Table.prototype.parse = function (data) { + var i; + data.pos = this.offset; + this.version = data.readUInt16(); + this.averageCharWidth = data.readShort(); + this.weightClass = data.readUInt16(); + this.widthClass = data.readUInt16(); + this.type = data.readShort(); + this.ySubscriptXSize = data.readShort(); + this.ySubscriptYSize = data.readShort(); + this.ySubscriptXOffset = data.readShort(); + this.ySubscriptYOffset = data.readShort(); + this.ySuperscriptXSize = data.readShort(); + this.ySuperscriptYSize = data.readShort(); + this.ySuperscriptXOffset = data.readShort(); + this.ySuperscriptYOffset = data.readShort(); + this.yStrikeoutSize = data.readShort(); + this.yStrikeoutPosition = data.readShort(); + this.familyClass = data.readShort(); + + this.panose = function () { + var _i, _results; + + _results = []; + + for (i = _i = 0; _i < 10; i = ++_i) { + _results.push(data.readByte()); + } + + return _results; + }(); + + this.charRange = function () { + var _i, _results; + + _results = []; + + for (i = _i = 0; _i < 4; i = ++_i) { + _results.push(data.readInt()); + } + + return _results; + }(); + + this.vendorID = data.readString(4); + this.selection = data.readShort(); + this.firstCharIndex = data.readShort(); + this.lastCharIndex = data.readShort(); + + if (this.version > 0) { + this.ascent = data.readShort(); + this.descent = data.readShort(); + this.lineGap = data.readShort(); + this.winAscent = data.readShort(); + this.winDescent = data.readShort(); + + this.codePageRange = function () { + var _i, _results; + + _results = []; + + for (i = _i = 0; _i < 2; i = ++_i) { + _results.push(data.readInt()); + } + + return _results; + }(); + + if (this.version > 1) { + this.xHeight = data.readShort(); + this.capHeight = data.readShort(); + this.defaultChar = data.readShort(); + this.breakChar = data.readShort(); + return this.maxContext = data.readShort(); + } + } + }; + /*OS2Table.prototype.encode = function () { + return this.raw(); + };*/ + + + return OS2Table; + }(Table); + + var PostTable = function (_super) { + + __extends(PostTable, _super); + + function PostTable() { + return PostTable.__super__.constructor.apply(this, arguments); + } + + PostTable.prototype.tag = "post"; + + PostTable.prototype.parse = function (data) { + var i, length, numberOfGlyphs, _i, _results; + + data.pos = this.offset; + this.format = data.readInt(); + this.italicAngle = data.readInt(); + this.underlinePosition = data.readShort(); + this.underlineThickness = data.readShort(); + this.isFixedPitch = data.readInt(); + this.minMemType42 = data.readInt(); + this.maxMemType42 = data.readInt(); + this.minMemType1 = data.readInt(); + this.maxMemType1 = data.readInt(); + + switch (this.format) { + case 0x00010000: + break; + + case 0x00020000: + numberOfGlyphs = data.readUInt16(); + this.glyphNameIndex = []; + + for (i = _i = 0; 0 <= numberOfGlyphs ? _i < numberOfGlyphs : _i > numberOfGlyphs; i = 0 <= numberOfGlyphs ? ++_i : --_i) { + this.glyphNameIndex.push(data.readUInt16()); + } + + this.names = []; + _results = []; + + while (data.pos < this.offset + this.length) { + length = data.readByte(); + + _results.push(this.names.push(data.readString(length))); + } + + return _results; + break; + + case 0x00025000: + numberOfGlyphs = data.readUInt16(); + return this.offsets = data.read(numberOfGlyphs); + + case 0x00030000: + break; + + case 0x00040000: + return this.map = function () { + var _j, _ref, _results1; + + _results1 = []; + + for (i = _j = 0, _ref = this.file.maxp.numGlyphs; 0 <= _ref ? _j < _ref : _j > _ref; i = 0 <= _ref ? ++_j : --_j) { + _results1.push(data.readUInt32()); + } + + return _results1; + }.call(this); + } + }; + return PostTable; + }(Table); + /*********************************************************************************************************/ + + /* function : NameEntry */ + + /* comment : Store copyright information, platformID, encodingID, and languageID in the NameEntry object.*/ + + /*********************************************************************************************************/ + + + var NameEntry = function () { + function NameEntry(raw, entry) { + this.raw = raw; + this.length = raw.length; + this.platformID = entry.platformID; + this.encodingID = entry.encodingID; + this.languageID = entry.languageID; + } + + return NameEntry; + }(); + + var NameTable = function (_super) { + + __extends(NameTable, _super); + + function NameTable() { + return NameTable.__super__.constructor.apply(this, arguments); + } + + NameTable.prototype.tag = "name"; + + NameTable.prototype.parse = function (data) { + var count, entries, entry, format, i, name, stringOffset, strings, text, _i, _j, _len, _name; + + data.pos = this.offset; + format = data.readShort(); + count = data.readShort(); + stringOffset = data.readShort(); + entries = []; + + for (i = _i = 0; 0 <= count ? _i < count : _i > count; i = 0 <= count ? ++_i : --_i) { + entries.push({ + platformID: data.readShort(), + encodingID: data.readShort(), + languageID: data.readShort(), + nameID: data.readShort(), + length: data.readShort(), + offset: this.offset + stringOffset + data.readShort() + }); + } + + strings = {}; + + for (i = _j = 0, _len = entries.length; _j < _len; i = ++_j) { + entry = entries[i]; + data.pos = entry.offset; + text = data.readString(entry.length); + name = new NameEntry(text, entry); + + if (strings[_name = entry.nameID] == null) { + strings[_name] = []; + } + + strings[entry.nameID].push(name); + } + + this.strings = strings; + this.copyright = strings[0]; + this.fontFamily = strings[1]; + this.fontSubfamily = strings[2]; + this.uniqueSubfamily = strings[3]; + this.fontName = strings[4]; + this.version = strings[5]; + + try { + this.postscriptName = strings[6][0].raw.replace(/[\x00-\x19\x80-\xff]/g, ""); + } catch (e) { + this.postscriptName = strings[4][0].raw.replace(/[\x00-\x19\x80-\xff]/g, ""); + } + + this.trademark = strings[7]; + this.manufacturer = strings[8]; + this.designer = strings[9]; + this.description = strings[10]; + this.vendorUrl = strings[11]; + this.designerUrl = strings[12]; + this.license = strings[13]; + this.licenseUrl = strings[14]; + this.preferredFamily = strings[15]; + this.preferredSubfamily = strings[17]; + this.compatibleFull = strings[18]; + return this.sampleText = strings[19]; + }; + /*NameTable.prototype.encode = function () { + var id, list, nameID, nameTable, postscriptName, strCount, strTable, string, strings, table, val, _i, _len, _ref; + strings = {}; + _ref = this.strings; + for (id in _ref) { + val = _ref[id]; + strings[id] = val; + } + postscriptName = new NameEntry("" + subsetTag + "+" + this.postscriptName, { + platformID: 1 + , encodingID: 0 + , languageID: 0 + }); + strings[6] = [postscriptName]; + subsetTag = successorOf(subsetTag); + strCount = 0; + for (id in strings) { + list = strings[id]; + if (list != null) { + strCount += list.length; + } + } + table = new Data; + strTable = new Data; + table.writeShort(0); + table.writeShort(strCount); + table.writeShort(6 + 12 * strCount); + for (nameID in strings) { + list = strings[nameID]; + if (list != null) { + for (_i = 0, _len = list.length; _i < _len; _i++) { + string = list[_i]; + table.writeShort(string.platformID); + table.writeShort(string.encodingID); + table.writeShort(string.languageID); + table.writeShort(nameID); + table.writeShort(string.length); + table.writeShort(strTable.pos); + strTable.writeString(string.raw); + } + } + } + return nameTable = { + postscriptName: postscriptName.raw + , table: table.data.concat(strTable.data) + }; + };*/ + + return NameTable; + }(Table); + + var MaxpTable = function (_super) { + __extends(MaxpTable, _super); + + function MaxpTable() { + return MaxpTable.__super__.constructor.apply(this, arguments); + } + + MaxpTable.prototype.tag = "maxp"; + + MaxpTable.prototype.parse = function (data) { + data.pos = this.offset; + this.version = data.readInt(); + this.numGlyphs = data.readUInt16(); + this.maxPoints = data.readUInt16(); + this.maxContours = data.readUInt16(); + this.maxCompositePoints = data.readUInt16(); + this.maxComponentContours = data.readUInt16(); + this.maxZones = data.readUInt16(); + this.maxTwilightPoints = data.readUInt16(); + this.maxStorage = data.readUInt16(); + this.maxFunctionDefs = data.readUInt16(); + this.maxInstructionDefs = data.readUInt16(); + this.maxStackElements = data.readUInt16(); + this.maxSizeOfInstructions = data.readUInt16(); + this.maxComponentElements = data.readUInt16(); + return this.maxComponentDepth = data.readUInt16(); + }; + /*MaxpTable.prototype.encode = function (ids) { + var table; + table = new Data; + table.writeInt(this.version); + table.writeUInt16(ids.length); + table.writeUInt16(this.maxPoints); + table.writeUInt16(this.maxContours); + table.writeUInt16(this.maxCompositePoints); + table.writeUInt16(this.maxComponentContours); + table.writeUInt16(this.maxZones); + table.writeUInt16(this.maxTwilightPoints); + table.writeUInt16(this.maxStorage); + table.writeUInt16(this.maxFunctionDefs); + table.writeUInt16(this.maxInstructionDefs); + table.writeUInt16(this.maxStackElements); + table.writeUInt16(this.maxSizeOfInstructions); + table.writeUInt16(this.maxComponentElements); + table.writeUInt16(this.maxComponentDepth); + return table.data; + };*/ + + + return MaxpTable; + }(Table); + + var HmtxTable = function (_super) { + __extends(HmtxTable, _super); + + function HmtxTable() { + return HmtxTable.__super__.constructor.apply(this, arguments); + } + + HmtxTable.prototype.tag = "hmtx"; + + HmtxTable.prototype.parse = function (data) { + var i, last, lsbCount, m, _i, _j, _ref, _results; + + data.pos = this.offset; + this.metrics = []; + + for (i = _i = 0, _ref = this.file.hhea.numberOfMetrics; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + this.metrics.push({ + advance: data.readUInt16(), + lsb: data.readInt16() + }); + } + + lsbCount = this.file.maxp.numGlyphs - this.file.hhea.numberOfMetrics; + + this.leftSideBearings = function () { + var _j, _results; + + _results = []; + + for (i = _j = 0; 0 <= lsbCount ? _j < lsbCount : _j > lsbCount; i = 0 <= lsbCount ? ++_j : --_j) { + _results.push(data.readInt16()); + } + + return _results; + }(); + + this.widths = function () { + var _j, _len, _ref1, _results; + + _ref1 = this.metrics; + _results = []; + + for (_j = 0, _len = _ref1.length; _j < _len; _j++) { + m = _ref1[_j]; + + _results.push(m.advance); + } + + return _results; + }.call(this); + + last = this.widths[this.widths.length - 1]; + _results = []; + + for (i = _j = 0; 0 <= lsbCount ? _j < lsbCount : _j > lsbCount; i = 0 <= lsbCount ? ++_j : --_j) { + _results.push(this.widths.push(last)); + } + + return _results; + }; + /***************************************************************/ + + /* function : forGlyph */ + + /* comment : Returns the advance width and lsb for this glyph. */ + + /***************************************************************/ + + + HmtxTable.prototype.forGlyph = function (id) { + var metrics; + + if (id in this.metrics) { + return this.metrics[id]; + } + + return metrics = { + advance: this.metrics[this.metrics.length - 1].advance, + lsb: this.leftSideBearings[id - this.metrics.length] + }; + }; + /*HmtxTable.prototype.encode = function (mapping) { + var id, metric, table, _i, _len; + table = new Data; + for (_i = 0, _len = mapping.length; _i < _len; _i++) { + id = mapping[_i]; + metric = this.forGlyph(id); + table.writeUInt16(metric.advance); + table.writeUInt16(metric.lsb); + } + return table.data; + };*/ + + + return HmtxTable; + }(Table); + + var __slice = [].slice; + + var GlyfTable = function (_super) { + __extends(GlyfTable, _super); + + function GlyfTable() { + return GlyfTable.__super__.constructor.apply(this, arguments); + } + + GlyfTable.prototype.tag = "glyf"; + + GlyfTable.prototype.parse = function (data) { + return this.cache = {}; + }; + + GlyfTable.prototype.glyphFor = function (id) { + id = id; + var data, index, length, loca, numberOfContours, raw, xMax, xMin, yMax, yMin; + + if (id in this.cache) { + return this.cache[id]; + } + + loca = this.file.loca; + data = this.file.contents; + index = loca.indexOf(id); + length = loca.lengthOf(id); + + if (length === 0) { + return this.cache[id] = null; + } + + data.pos = this.offset + index; + raw = new Data(data.read(length)); + numberOfContours = raw.readShort(); + xMin = raw.readShort(); + yMin = raw.readShort(); + xMax = raw.readShort(); + yMax = raw.readShort(); + + if (numberOfContours === -1) { + this.cache[id] = new CompoundGlyph(raw, xMin, yMin, xMax, yMax); + } else { + this.cache[id] = new SimpleGlyph(raw, numberOfContours, xMin, yMin, xMax, yMax); + } + + return this.cache[id]; + }; + + GlyfTable.prototype.encode = function (glyphs, mapping, old2new) { + var glyph, id, offsets, table, _i, _len; + + table = []; + offsets = []; + + for (_i = 0, _len = mapping.length; _i < _len; _i++) { + id = mapping[_i]; + glyph = glyphs[id]; + offsets.push(table.length); + + if (glyph) { + table = table.concat(glyph.encode(old2new)); + } + } + + offsets.push(table.length); + return { + table: table, + offsets: offsets + }; + }; + + return GlyfTable; + }(Table); + + var SimpleGlyph = function () { + /**************************************************************************/ + + /* function : SimpleGlyph */ + + /* comment : Stores raw, xMin, yMin, xMax, and yMax values for this glyph.*/ + + /**************************************************************************/ + function SimpleGlyph(raw, numberOfContours, xMin, yMin, xMax, yMax) { + this.raw = raw; + this.numberOfContours = numberOfContours; + this.xMin = xMin; + this.yMin = yMin; + this.xMax = xMax; + this.yMax = yMax; + this.compound = false; + } + + SimpleGlyph.prototype.encode = function () { + return this.raw.data; + }; + + return SimpleGlyph; + }(); + + var CompoundGlyph = function () { + var ARG_1_AND_2_ARE_WORDS, MORE_COMPONENTS, WE_HAVE_AN_X_AND_Y_SCALE, WE_HAVE_A_SCALE, WE_HAVE_A_TWO_BY_TWO; + ARG_1_AND_2_ARE_WORDS = 0x0001; + WE_HAVE_A_SCALE = 0x0008; + MORE_COMPONENTS = 0x0020; + WE_HAVE_AN_X_AND_Y_SCALE = 0x0040; + WE_HAVE_A_TWO_BY_TWO = 0x0080; + /********************************************************************************************************************/ + + /* function : CompoundGlypg generator */ + + /* comment : It stores raw, xMin, yMin, xMax, yMax, glyph id, and glyph offset for the corresponding compound glyph.*/ + + /********************************************************************************************************************/ + + function CompoundGlyph(raw, xMin, yMin, xMax, yMax) { + var data, flags; + this.raw = raw; + this.xMin = xMin; + this.yMin = yMin; + this.xMax = xMax; + this.yMax = yMax; + this.compound = true; + this.glyphIDs = []; + this.glyphOffsets = []; + data = this.raw; + + while (true) { + flags = data.readShort(); + this.glyphOffsets.push(data.pos); + this.glyphIDs.push(data.readShort()); + + if (!(flags & MORE_COMPONENTS)) { + break; + } + + if (flags & ARG_1_AND_2_ARE_WORDS) { + data.pos += 4; + } else { + data.pos += 2; + } + + if (flags & WE_HAVE_A_TWO_BY_TWO) { + data.pos += 8; + } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { + data.pos += 4; + } else if (flags & WE_HAVE_A_SCALE) { + data.pos += 2; + } + } + } + /****************************************************************************************************************/ + + /* function : CompoundGlypg encode */ + + /* comment : After creating a table for the characters you typed, you call directory.encode to encode the table.*/ + + /****************************************************************************************************************/ + + + CompoundGlyph.prototype.encode = function (mapping) { + var i, id, result, _i, _len, _ref; + + result = new Data(__slice.call(this.raw.data)); + _ref = this.glyphIDs; + + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + id = _ref[i]; + result.pos = this.glyphOffsets[i]; + } + + return result.data; + }; + + return CompoundGlyph; + }(); + + var LocaTable = function (_super) { + __extends(LocaTable, _super); + + function LocaTable() { + return LocaTable.__super__.constructor.apply(this, arguments); + } + + LocaTable.prototype.tag = "loca"; + + LocaTable.prototype.parse = function (data) { + var format, i; + data.pos = this.offset; + format = this.file.head.indexToLocFormat; + + if (format === 0) { + return this.offsets = function () { + var _i, _ref, _results; + + _results = []; + + for (i = _i = 0, _ref = this.length; _i < _ref; i = _i += 2) { + _results.push(data.readUInt16() * 2); + } + + return _results; + }.call(this); + } else { + return this.offsets = function () { + var _i, _ref, _results; + + _results = []; + + for (i = _i = 0, _ref = this.length; _i < _ref; i = _i += 4) { + _results.push(data.readUInt32()); + } + + return _results; + }.call(this); + } + }; + + LocaTable.prototype.indexOf = function (id) { + return this.offsets[id]; + }; + + LocaTable.prototype.lengthOf = function (id) { + return this.offsets[id + 1] - this.offsets[id]; + }; + + LocaTable.prototype.encode = function (offsets, activeGlyphs) { + var LocaTable = new Uint32Array(this.offsets.length); + var glyfPtr = 0; + var listGlyf = 0; + + for (var k = 0; k < LocaTable.length; ++k) { + LocaTable[k] = glyfPtr; + + if (listGlyf < activeGlyphs.length && activeGlyphs[listGlyf] == k) { + ++listGlyf; + LocaTable[k] = glyfPtr; + var start = this.offsets[k]; + var len = this.offsets[k + 1] - start; + + if (len > 0) { + glyfPtr += len; + } + } + } + + var newLocaTable = new Array(LocaTable.length * 4); + + for (var j = 0; j < LocaTable.length; ++j) { + newLocaTable[4 * j + 3] = LocaTable[j] & 0x000000ff; + newLocaTable[4 * j + 2] = (LocaTable[j] & 0x0000ff00) >> 8; + newLocaTable[4 * j + 1] = (LocaTable[j] & 0x00ff0000) >> 16; + newLocaTable[4 * j] = (LocaTable[j] & 0xff000000) >> 24; + } + + return newLocaTable; + }; + + return LocaTable; + }(Table); + /************************************************************************************/ + + /* function : invert */ + + /* comment : Change the object's (key: value) to create an object with (value: key).*/ + + /************************************************************************************/ + + + var invert = function (object) { + var key, ret, val; + ret = {}; + + for (key in object) { + val = object[key]; + ret[val] = key; + } + + return ret; + }; + /*var successorOf = function (input) { + var added, alphabet, carry, i, index, isUpperCase, last, length, next, result; + alphabet = 'abcdefghijklmnopqrstuvwxyz'; + length = alphabet.length; + result = input; + i = input.length; + while (i >= 0) { + last = input.charAt(--i); + if (isNaN(last)) { + index = alphabet.indexOf(last.toLowerCase()); + if (index === -1) { + next = last; + carry = true; + } + else { + next = alphabet.charAt((index + 1) % length); + isUpperCase = last === last.toUpperCase(); + if (isUpperCase) { + next = next.toUpperCase(); + } + carry = index + 1 >= length; + if (carry && i === 0) { + added = isUpperCase ? 'A' : 'a'; + result = added + next + result.slice(1); + break; + } + } + } + else { + next = +last + 1; + carry = next > 9; + if (carry) { + next = 0; + } + if (carry && i === 0) { + result = '1' + next + result.slice(1); + break; + } + } + result = result.slice(0, i) + next + result.slice(i + 1); + if (!carry) { + break; + } + } + return result; + };*/ + + + var Subset = function () { + function Subset(font) { + this.font = font; + this.subset = {}; + this.unicodes = {}; + this.next = 33; + } + /*Subset.prototype.use = function (character) { + var i, _i, _ref; + if (typeof character === 'string') { + for (i = _i = 0, _ref = character.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + this.use(character.charCodeAt(i)); + } + return; + } + if (!this.unicodes[character]) { + this.subset[this.next] = character; + return this.unicodes[character] = this.next++; + } + };*/ + + /*Subset.prototype.encodeText = function (text) { + var char, i, string, _i, _ref; + string = ''; + for (i = _i = 0, _ref = text.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + char = this.unicodes[text.charCodeAt(i)]; + string += String.fromCharCode(char); + } + return string; + };*/ + + /***************************************************************/ + + /* function : generateCmap */ + + /* comment : Returns the unicode cmap for this font. */ + + /***************************************************************/ + + + Subset.prototype.generateCmap = function () { + var mapping, roman, unicode, unicodeCmap, _ref; + + unicodeCmap = this.font.cmap.tables[0].codeMap; + mapping = {}; + _ref = this.subset; + + for (roman in _ref) { + unicode = _ref[roman]; + mapping[roman] = unicodeCmap[unicode]; + } + + return mapping; + }; + /*Subset.prototype.glyphIDs = function () { + var ret, roman, unicode, unicodeCmap, val, _ref; + unicodeCmap = this.font.cmap.tables[0].codeMap; + ret = [0]; + _ref = this.subset; + for (roman in _ref) { + unicode = _ref[roman]; + val = unicodeCmap[unicode]; + if ((val != null) && __indexOf.call(ret, val) < 0) { + ret.push(val); + } + } + return ret.sort(); + };*/ + + /******************************************************************/ + + /* function : glyphsFor */ + + /* comment : Returns simple glyph objects for the input character.*/ + + /******************************************************************/ + + + Subset.prototype.glyphsFor = function (glyphIDs) { + var additionalIDs, glyph, glyphs, id, _i, _len, _ref; + + glyphs = {}; + + for (_i = 0, _len = glyphIDs.length; _i < _len; _i++) { + id = glyphIDs[_i]; + glyphs[id] = this.font.glyf.glyphFor(id); + } + + additionalIDs = []; + + for (id in glyphs) { + glyph = glyphs[id]; + + if (glyph != null ? glyph.compound : void 0) { + additionalIDs.push.apply(additionalIDs, glyph.glyphIDs); + } + } + + if (additionalIDs.length > 0) { + _ref = this.glyphsFor(additionalIDs); + + for (id in _ref) { + glyph = _ref[id]; + glyphs[id] = glyph; + } + } + + return glyphs; + }; + /***************************************************************/ + + /* function : encode */ + + /* comment : Encode various tables for the characters you use. */ + + /***************************************************************/ + + + Subset.prototype.encode = function (glyID, indexToLocFormat) { + var cmap, code, glyf, glyphs, id, ids, loca, new2old, newIDs, nextGlyphID, old2new, oldID, oldIDs, tables, _ref; + + cmap = CmapTable.encode(this.generateCmap(), "unicode"); + glyphs = this.glyphsFor(glyID); + old2new = { + 0: 0 + }; + _ref = cmap.charMap; + + for (code in _ref) { + ids = _ref[code]; + old2new[ids.old] = ids["new"]; + } + + nextGlyphID = cmap.maxGlyphID; + + for (oldID in glyphs) { + if (!(oldID in old2new)) { + old2new[oldID] = nextGlyphID++; + } + } + + new2old = invert(old2new); + newIDs = Object.keys(new2old).sort(function (a, b) { + return a - b; + }); + + oldIDs = function () { + var _i, _len, _results; + + _results = []; + + for (_i = 0, _len = newIDs.length; _i < _len; _i++) { + id = newIDs[_i]; + + _results.push(new2old[id]); + } + + return _results; + }(); + + glyf = this.font.glyf.encode(glyphs, oldIDs, old2new); + loca = this.font.loca.encode(glyf.offsets, oldIDs); + tables = { + cmap: this.font.cmap.raw(), + glyf: glyf.table, + loca: loca, + hmtx: this.font.hmtx.raw(), + hhea: this.font.hhea.raw(), + maxp: this.font.maxp.raw(), + post: this.font.post.raw(), + name: this.font.name.raw(), + head: this.font.head.encode(indexToLocFormat) + }; + + if (this.font.os2.exists) { + tables["OS/2"] = this.font.os2.raw(); + } + + return this.font.directory.encode(tables); + }; + + return Subset; + }(); + + jsPDF.API.PDFObject = function () { + var pad; + + function PDFObject() {} + + pad = function (str, length) { + return (Array(length + 1).join("0") + str).slice(-length); + }; + /*****************************************************************************/ + + /* function : convert */ + + /* comment :Converts pdf tag's / FontBBox and array values in / W to strings */ + + /*****************************************************************************/ + + + PDFObject.convert = function (object) { + var e, items, key, out, val; + + if (Array.isArray(object)) { + items = function () { + var _i, _len, _results; + + _results = []; + + for (_i = 0, _len = object.length; _i < _len; _i++) { + e = object[_i]; + + _results.push(PDFObject.convert(e)); + } + + return _results; + }().join(" "); + + return "[" + items + "]"; + } else if (typeof object === "string") { + return "/" + object; + } else if (object != null ? object.isString : void 0) { + return "(" + object + ")"; + } else if (object instanceof Date) { + return "(D:" + pad(object.getUTCFullYear(), 4) + pad(object.getUTCMonth(), 2) + pad(object.getUTCDate(), 2) + pad(object.getUTCHours(), 2) + pad(object.getUTCMinutes(), 2) + pad(object.getUTCSeconds(), 2) + "Z)"; + } else if ({}.toString.call(object) === "[object Object]") { + out = ["<<"]; + + for (key in object) { + val = object[key]; + out.push("/" + key + " " + PDFObject.convert(val)); + } + + out.push(">>"); + return out.join("\n"); + } else { + return "" + object; + } + }; + + return PDFObject; + }(); + })(jsPDF); + + // Generated by CoffeeScript 1.4.0 + + /* + # PNG.js + # Copyright (c) 2011 Devon Govett + # MIT LICENSE + # + # + */ + (function (global) { + var PNG; + + PNG = function () { + var APNG_BLEND_OP_SOURCE, APNG_DISPOSE_OP_BACKGROUND, APNG_DISPOSE_OP_PREVIOUS, makeImage, scratchCanvas, scratchCtx; + + PNG.load = function (url, canvas, callback) { + var xhr; + + if (typeof canvas === "function") { + callback = canvas; + } + + xhr = new XMLHttpRequest(); + xhr.open("GET", url, true); + xhr.responseType = "arraybuffer"; + + xhr.onload = function () { + var data, png; + data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer); + png = new PNG(data); + + if (typeof (canvas != null ? canvas.getContext : void 0) === "function") { + png.render(canvas); + } + + return typeof callback === "function" ? callback(png) : void 0; + }; + + return xhr.send(null); + }; + APNG_DISPOSE_OP_BACKGROUND = 1; + APNG_DISPOSE_OP_PREVIOUS = 2; + APNG_BLEND_OP_SOURCE = 0; + + function PNG(data) { + var chunkSize, colors, palLen, delayDen, delayNum, frame, i, index, key, section, palShort, text, _i, _j, _ref; + + this.data = data; + this.pos = 8; + this.palette = []; + this.imgData = []; + this.transparency = {}; + this.animation = null; + this.text = {}; + frame = null; + + while (true) { + chunkSize = this.readUInt32(); + + section = function () { + var _i, _results; + + _results = []; + + for (i = _i = 0; _i < 4; i = ++_i) { + _results.push(String.fromCharCode(this.data[this.pos++])); + } + + return _results; + }.call(this).join(""); + + switch (section) { + case "IHDR": + this.width = this.readUInt32(); + this.height = this.readUInt32(); + this.bits = this.data[this.pos++]; + this.colorType = this.data[this.pos++]; + this.compressionMethod = this.data[this.pos++]; + this.filterMethod = this.data[this.pos++]; + this.interlaceMethod = this.data[this.pos++]; + break; + + case "acTL": + this.animation = { + numFrames: this.readUInt32(), + numPlays: this.readUInt32() || Infinity, + frames: [] + }; + break; + + case "PLTE": + this.palette = this.read(chunkSize); + break; + + case "fcTL": + if (frame) { + this.animation.frames.push(frame); + } + + this.pos += 4; + frame = { + width: this.readUInt32(), + height: this.readUInt32(), + xOffset: this.readUInt32(), + yOffset: this.readUInt32() + }; + delayNum = this.readUInt16(); + delayDen = this.readUInt16() || 100; + frame.delay = 1000 * delayNum / delayDen; + frame.disposeOp = this.data[this.pos++]; + frame.blendOp = this.data[this.pos++]; + frame.data = []; + break; + + case "IDAT": + case "fdAT": + if (section === "fdAT") { + this.pos += 4; + chunkSize -= 4; + } + + data = (frame != null ? frame.data : void 0) || this.imgData; + + for (i = _i = 0; 0 <= chunkSize ? _i < chunkSize : _i > chunkSize; i = 0 <= chunkSize ? ++_i : --_i) { + data.push(this.data[this.pos++]); + } + + break; + + case "tRNS": + this.transparency = {}; + + switch (this.colorType) { + case 3: + palLen = this.palette.length / 3; + this.transparency.indexed = this.read(chunkSize); + if (this.transparency.indexed.length > palLen) throw new Error("More transparent colors than palette size"); + /* + * According to the PNG spec trns should be increased to the same size as palette if shorter + */ + //palShort = 255 - this.transparency.indexed.length; + + palShort = palLen - this.transparency.indexed.length; + + if (palShort > 0) { + for (i = _j = 0; 0 <= palShort ? _j < palShort : _j > palShort; i = 0 <= palShort ? ++_j : --_j) { + this.transparency.indexed.push(255); + } + } + + break; + + case 0: + this.transparency.grayscale = this.read(chunkSize)[0]; + break; + + case 2: + this.transparency.rgb = this.read(chunkSize); + } + + break; + + case "tEXt": + text = this.read(chunkSize); + index = text.indexOf(0); + key = String.fromCharCode.apply(String, text.slice(0, index)); + this.text[key] = String.fromCharCode.apply(String, text.slice(index + 1)); + break; + + case "IEND": + if (frame) { + this.animation.frames.push(frame); + } + + this.colors = function () { + switch (this.colorType) { + case 0: + case 3: + case 4: + return 1; + + case 2: + case 6: + return 3; + } + }.call(this); + + this.hasAlphaChannel = (_ref = this.colorType) === 4 || _ref === 6; + colors = this.colors + (this.hasAlphaChannel ? 1 : 0); + this.pixelBitlength = this.bits * colors; + + this.colorSpace = function () { + switch (this.colors) { + case 1: + return "DeviceGray"; + + case 3: + return "DeviceRGB"; + } + }.call(this); + + this.imgData = new Uint8Array(this.imgData); + return; + + default: + this.pos += chunkSize; + } + + this.pos += 4; + + if (this.pos > this.data.length) { + throw new Error("Incomplete or corrupt PNG file"); + } + } + + return; + } + + PNG.prototype.read = function (bytes) { + var i, _i, _results; + + _results = []; + + for (i = _i = 0; 0 <= bytes ? _i < bytes : _i > bytes; i = 0 <= bytes ? ++_i : --_i) { + _results.push(this.data[this.pos++]); + } + + return _results; + }; + + PNG.prototype.readUInt32 = function () { + var b1, b2, b3, b4; + b1 = this.data[this.pos++] << 24; + b2 = this.data[this.pos++] << 16; + b3 = this.data[this.pos++] << 8; + b4 = this.data[this.pos++]; + return b1 | b2 | b3 | b4; + }; + + PNG.prototype.readUInt16 = function () { + var b1, b2; + b1 = this.data[this.pos++] << 8; + b2 = this.data[this.pos++]; + return b1 | b2; + }; + + PNG.prototype.decodePixels = function (data) { + var pixelBytes = this.pixelBitlength / 8; + var fullPixels = new Uint8Array(this.width * this.height * pixelBytes); + var pos = 0; + + var _this = this; + + if (data == null) { + data = this.imgData; + } + + if (data.length === 0) { + return new Uint8Array(0); + } + + data = new FlateStream(data); + data = data.getBytes(); + + function pass(x0, y0, dx, dy) { + var abyte, c, col, i, left, length, p, pa, paeth, pb, pc, pixels, row, scanlineLength, upper, upperLeft, _i, _j, _k, _l, _m; + + var w = Math.ceil((_this.width - x0) / dx), + h = Math.ceil((_this.height - y0) / dy); + var isFull = _this.width == w && _this.height == h; + scanlineLength = pixelBytes * w; + pixels = isFull ? fullPixels : new Uint8Array(scanlineLength * h); + length = data.length; + row = 0; + c = 0; + + while (row < h && pos < length) { + switch (data[pos++]) { + case 0: + for (i = _i = 0; _i < scanlineLength; i = _i += 1) { + pixels[c++] = data[pos++]; + } + + break; + + case 1: + for (i = _j = 0; _j < scanlineLength; i = _j += 1) { + abyte = data[pos++]; + left = i < pixelBytes ? 0 : pixels[c - pixelBytes]; + pixels[c++] = (abyte + left) % 256; + } + + break; + + case 2: + for (i = _k = 0; _k < scanlineLength; i = _k += 1) { + abyte = data[pos++]; + col = (i - i % pixelBytes) / pixelBytes; + upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + i % pixelBytes]; + pixels[c++] = (upper + abyte) % 256; + } + + break; + + case 3: + for (i = _l = 0; _l < scanlineLength; i = _l += 1) { + abyte = data[pos++]; + col = (i - i % pixelBytes) / pixelBytes; + left = i < pixelBytes ? 0 : pixels[c - pixelBytes]; + upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + i % pixelBytes]; + pixels[c++] = (abyte + Math.floor((left + upper) / 2)) % 256; + } + + break; + + case 4: + for (i = _m = 0; _m < scanlineLength; i = _m += 1) { + abyte = data[pos++]; + col = (i - i % pixelBytes) / pixelBytes; + left = i < pixelBytes ? 0 : pixels[c - pixelBytes]; + + if (row === 0) { + upper = upperLeft = 0; + } else { + upper = pixels[(row - 1) * scanlineLength + col * pixelBytes + i % pixelBytes]; + upperLeft = col && pixels[(row - 1) * scanlineLength + (col - 1) * pixelBytes + i % pixelBytes]; + } + + p = left + upper - upperLeft; + pa = Math.abs(p - left); + pb = Math.abs(p - upper); + pc = Math.abs(p - upperLeft); + + if (pa <= pb && pa <= pc) { + paeth = left; + } else if (pb <= pc) { + paeth = upper; + } else { + paeth = upperLeft; + } + + pixels[c++] = (abyte + paeth) % 256; + } + + break; + + default: + throw new Error("Invalid filter algorithm: " + data[pos - 1]); + } + + if (!isFull) { + var fullPos = ((y0 + row * dy) * _this.width + x0) * pixelBytes; + var partPos = row * scanlineLength; + + for (i = 0; i < w; i += 1) { + for (var j = 0; j < pixelBytes; j += 1) fullPixels[fullPos++] = pixels[partPos++]; + + fullPos += (dx - 1) * pixelBytes; + } + } + + row++; + } + } + + if (_this.interlaceMethod == 1) { + /* + 1 6 4 6 2 6 4 6 + 7 7 7 7 7 7 7 7 + 5 6 5 6 5 6 5 6 + 7 7 7 7 7 7 7 7 + 3 6 4 6 3 6 4 6 + 7 7 7 7 7 7 7 7 + 5 6 5 6 5 6 5 6 + 7 7 7 7 7 7 7 7 + */ + pass(0, 0, 8, 8); // 1 + + /* NOTE these seem to follow the pattern: + * pass(x, 0, 2*x, 2*x); + * pass(0, x, x, 2*x); + * with x being 4, 2, 1. + */ + + pass(4, 0, 8, 8); // 2 + + pass(0, 4, 4, 8); // 3 + + pass(2, 0, 4, 4); // 4 + + pass(0, 2, 2, 4); // 5 + + pass(1, 0, 2, 2); // 6 + + pass(0, 1, 1, 2); // 7 + } else { + pass(0, 0, 1, 1); + } + + return fullPixels; + }; + + PNG.prototype.decodePalette = function () { + var c, i, length, palette, pos, ret, transparency, _i, _ref, _ref1; + + palette = this.palette; + transparency = this.transparency.indexed || []; + ret = new Uint8Array((transparency.length || 0) + palette.length); + pos = 0; + length = palette.length; + c = 0; + + for (i = _i = 0, _ref = palette.length; _i < _ref; i = _i += 3) { + ret[pos++] = palette[i]; + ret[pos++] = palette[i + 1]; + ret[pos++] = palette[i + 2]; + ret[pos++] = (_ref1 = transparency[c++]) != null ? _ref1 : 255; + } + + return ret; + }; + + PNG.prototype.copyToImageData = function (imageData, pixels) { + var alpha, colors, data, i, input, j, k, length, palette, v, _ref; + + colors = this.colors; + palette = null; + alpha = this.hasAlphaChannel; + + if (this.palette.length) { + palette = (_ref = this._decodedPalette) != null ? _ref : this._decodedPalette = this.decodePalette(); + colors = 4; + alpha = true; + } + + data = imageData.data || imageData; + length = data.length; + input = palette || pixels; + i = j = 0; + + if (colors === 1) { + while (i < length) { + k = palette ? pixels[i / 4] * 4 : j; + v = input[k++]; + data[i++] = v; + data[i++] = v; + data[i++] = v; + data[i++] = alpha ? input[k++] : 255; + j = k; + } + } else { + while (i < length) { + k = palette ? pixels[i / 4] * 4 : j; + data[i++] = input[k++]; + data[i++] = input[k++]; + data[i++] = input[k++]; + data[i++] = alpha ? input[k++] : 255; + j = k; + } + } + }; + + PNG.prototype.decode = function () { + var ret; + ret = new Uint8Array(this.width * this.height * 4); + this.copyToImageData(ret, this.decodePixels()); + return ret; + }; + + try { + scratchCanvas = global.document.createElement("canvas"); + scratchCtx = scratchCanvas.getContext("2d"); + } catch (e) { + return -1; + } + + makeImage = function (imageData) { + var img; + scratchCtx.width = imageData.width; + scratchCtx.height = imageData.height; + scratchCtx.clearRect(0, 0, imageData.width, imageData.height); + scratchCtx.putImageData(imageData, 0, 0); + img = new Image(); + img.src = scratchCanvas.toDataURL(); + return img; + }; + + PNG.prototype.decodeFrames = function (ctx) { + var frame, i, imageData, pixels, _i, _len, _ref, _results; + + if (!this.animation) { + return; + } + + _ref = this.animation.frames; + _results = []; + + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + frame = _ref[i]; + imageData = ctx.createImageData(frame.width, frame.height); + pixels = this.decodePixels(new Uint8Array(frame.data)); + this.copyToImageData(imageData, pixels); + frame.imageData = imageData; + + _results.push(frame.image = makeImage(imageData)); + } + + return _results; + }; + + PNG.prototype.renderFrame = function (ctx, number) { + var frame, frames, prev; + frames = this.animation.frames; + frame = frames[number]; + prev = frames[number - 1]; + + if (number === 0) { + ctx.clearRect(0, 0, this.width, this.height); + } + + if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_BACKGROUND) { + ctx.clearRect(prev.xOffset, prev.yOffset, prev.width, prev.height); + } else if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_PREVIOUS) { + ctx.putImageData(prev.imageData, prev.xOffset, prev.yOffset); + } + + if (frame.blendOp === APNG_BLEND_OP_SOURCE) { + ctx.clearRect(frame.xOffset, frame.yOffset, frame.width, frame.height); + } + + return ctx.drawImage(frame.image, frame.xOffset, frame.yOffset); + }; + + PNG.prototype.animate = function (ctx) { + var doFrame, + frameNumber, + frames, + numFrames, + numPlays, + _ref, + _this = this; + + frameNumber = 0; + _ref = this.animation, numFrames = _ref.numFrames, frames = _ref.frames, numPlays = _ref.numPlays; + return (doFrame = function () { + var f, frame; + f = frameNumber++ % numFrames; + frame = frames[f]; + + _this.renderFrame(ctx, f); + + if (numFrames > 1 && frameNumber / numFrames < numPlays) { + return _this.animation._timeout = setTimeout(doFrame, frame.delay); + } + })(); + }; + + PNG.prototype.stopAnimation = function () { + var _ref; + + return clearTimeout((_ref = this.animation) != null ? _ref._timeout : void 0); + }; + + PNG.prototype.render = function (canvas) { + var ctx, data; + + if (canvas._png) { + canvas._png.stopAnimation(); + } + + canvas._png = this; + canvas.width = this.width; + canvas.height = this.height; + ctx = canvas.getContext("2d"); + + if (this.animation) { + this.decodeFrames(ctx); + return this.animate(ctx); + } else { + data = ctx.createImageData(this.width, this.height); + this.copyToImageData(data, this.decodePixels()); + return ctx.putImageData(data, 0, 0); + } + }; + + return PNG; + }(); + + global.PNG = PNG; + })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")()); // `self` is undefined in Firefox for Android content script context + // while `this` is nsIContentFrameMessageManager + // with an attribute `content` that corresponds to the window + + /* + * Extracted from pdf.js + * https://github.com/andreasgal/pdf.js + * + * Copyright (c) 2011 Mozilla Foundation + * + * Contributors: Andreas Gal + * Chris G Jones + * Shaon Barman + * Vivien Nicolas <21@vingtetun.org> + * Justin D'Arcangelo + * Yury Delendik + * + * + */ + var DecodeStream = function () { + function constructor() { + this.pos = 0; + this.bufferLength = 0; + this.eof = false; + this.buffer = null; + } + + constructor.prototype = { + ensureBuffer: function decodestream_ensureBuffer(requested) { + var buffer = this.buffer; + var current = buffer ? buffer.byteLength : 0; + if (requested < current) return buffer; + var size = 512; + + while (size < requested) size <<= 1; + + var buffer2 = new Uint8Array(size); + + for (var i = 0; i < current; ++i) buffer2[i] = buffer[i]; + + return this.buffer = buffer2; + }, + getByte: function decodestream_getByte() { + var pos = this.pos; + + while (this.bufferLength <= pos) { + if (this.eof) return null; + this.readBlock(); + } + + return this.buffer[this.pos++]; + }, + getBytes: function decodestream_getBytes(length) { + var pos = this.pos; + + if (length) { + this.ensureBuffer(pos + length); + var end = pos + length; + + while (!this.eof && this.bufferLength < end) this.readBlock(); + + var bufEnd = this.bufferLength; + if (end > bufEnd) end = bufEnd; + } else { + while (!this.eof) this.readBlock(); + + var end = this.bufferLength; + } + + this.pos = end; + return this.buffer.subarray(pos, end); + }, + lookChar: function decodestream_lookChar() { + var pos = this.pos; + + while (this.bufferLength <= pos) { + if (this.eof) return null; + this.readBlock(); + } + + return String.fromCharCode(this.buffer[this.pos]); + }, + getChar: function decodestream_getChar() { + var pos = this.pos; + + while (this.bufferLength <= pos) { + if (this.eof) return null; + this.readBlock(); + } + + return String.fromCharCode(this.buffer[this.pos++]); + }, + makeSubStream: function decodestream_makeSubstream(start, length, dict) { + var end = start + length; + + while (this.bufferLength <= end && !this.eof) this.readBlock(); + + return new Stream(this.buffer, start, length, dict); + }, + skip: function decodestream_skip(n) { + if (!n) n = 1; + this.pos += n; + }, + reset: function decodestream_reset() { + this.pos = 0; + } + }; + return constructor; + }(); + + var FlateStream = function () { + if (typeof Uint32Array === "undefined") { + return undefined; + } + + var codeLenCodeMap = new Uint32Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]); + var lengthDecode = new Uint32Array([0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073, 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102]); + var distDecode = new Uint32Array([0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01, 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001]); + var fixedLitCodeTab = [new Uint32Array([0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0, 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0, 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0, 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8, 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8, 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8, 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4, 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4, 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4, 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc, 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec, 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc, 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2, 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2, 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2, 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca, 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea, 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da, 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6, 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6, 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6, 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce, 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee, 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de, 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe, 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1, 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1, 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1, 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9, 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9, 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9, 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5, 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5, 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5, 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd, 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed, 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd, 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3, 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3, 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3, 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb, 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb, 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db, 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7, 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7, 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7, 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf, 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef, 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df, 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff]), 9]; + var fixedDistCodeTab = [new Uint32Array([0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c, 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000, 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d, 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000]), 5]; + + function error(e) { + throw new Error(e); + } + + function constructor(bytes) { + //var bytes = stream.getBytes(); + var bytesPos = 0; + var cmf = bytes[bytesPos++]; + var flg = bytes[bytesPos++]; + if (cmf == -1 || flg == -1) error("Invalid header in flate stream"); + if ((cmf & 0x0f) != 0x08) error("Unknown compression method in flate stream"); + if (((cmf << 8) + flg) % 31 != 0) error("Bad FCHECK in flate stream"); + if (flg & 0x20) error("FDICT bit set in flate stream"); + this.bytes = bytes; + this.bytesPos = bytesPos; + this.codeSize = 0; + this.codeBuf = 0; + DecodeStream.call(this); + } + + constructor.prototype = Object.create(DecodeStream.prototype); + + constructor.prototype.getBits = function (bits) { + var codeSize = this.codeSize; + var codeBuf = this.codeBuf; + var bytes = this.bytes; + var bytesPos = this.bytesPos; + var b; + + while (codeSize < bits) { + if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad encoding in flate stream"); + codeBuf |= b << codeSize; + codeSize += 8; + } + + b = codeBuf & (1 << bits) - 1; + this.codeBuf = codeBuf >> bits; + this.codeSize = codeSize -= bits; + this.bytesPos = bytesPos; + return b; + }; + + constructor.prototype.getCode = function (table) { + var codes = table[0]; + var maxLen = table[1]; + var codeSize = this.codeSize; + var codeBuf = this.codeBuf; + var bytes = this.bytes; + var bytesPos = this.bytesPos; + + while (codeSize < maxLen) { + var b; + if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad encoding in flate stream"); + codeBuf |= b << codeSize; + codeSize += 8; + } + + var code = codes[codeBuf & (1 << maxLen) - 1]; + var codeLen = code >> 16; + var codeVal = code & 0xffff; + if (codeSize == 0 || codeSize < codeLen || codeLen == 0) error("Bad encoding in flate stream"); + this.codeBuf = codeBuf >> codeLen; + this.codeSize = codeSize - codeLen; + this.bytesPos = bytesPos; + return codeVal; + }; + + constructor.prototype.generateHuffmanTable = function (lengths) { + var n = lengths.length; // find max code length + + var maxLen = 0; + + for (var i = 0; i < n; ++i) { + if (lengths[i] > maxLen) maxLen = lengths[i]; + } // build the table + + + var size = 1 << maxLen; + var codes = new Uint32Array(size); + + for (var len = 1, code = 0, skip = 2; len <= maxLen; ++len, code <<= 1, skip <<= 1) { + for (var val = 0; val < n; ++val) { + if (lengths[val] == len) { + // bit-reverse the code + var code2 = 0; + var t = code; + + for (var i = 0; i < len; ++i) { + code2 = code2 << 1 | t & 1; + t >>= 1; + } // fill the table entries + + + for (var i = code2; i < size; i += skip) codes[i] = len << 16 | val; + + ++code; + } + } + } + + return [codes, maxLen]; + }; + + constructor.prototype.readBlock = function () { + function repeat(stream, array, len, offset, what) { + var repeat = stream.getBits(len) + offset; + + while (repeat-- > 0) array[i++] = what; + } // read block header + + + var hdr = this.getBits(3); + if (hdr & 1) this.eof = true; + hdr >>= 1; + + if (hdr == 0) { + // uncompressed block + var bytes = this.bytes; + var bytesPos = this.bytesPos; + var b; + if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad block header in flate stream"); + var blockLen = b; + if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad block header in flate stream"); + blockLen |= b << 8; + if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad block header in flate stream"); + var check = b; + if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad block header in flate stream"); + check |= b << 8; + if (check != (~blockLen & 0xffff)) error("Bad uncompressed block length in flate stream"); + this.codeBuf = 0; + this.codeSize = 0; + var bufferLength = this.bufferLength; + var buffer = this.ensureBuffer(bufferLength + blockLen); + var end = bufferLength + blockLen; + this.bufferLength = end; + + for (var n = bufferLength; n < end; ++n) { + if (typeof (b = bytes[bytesPos++]) == "undefined") { + this.eof = true; + break; + } + + buffer[n] = b; + } + + this.bytesPos = bytesPos; + return; + } + + var litCodeTable; + var distCodeTable; + + if (hdr == 1) { + // compressed block, fixed codes + litCodeTable = fixedLitCodeTab; + distCodeTable = fixedDistCodeTab; + } else if (hdr == 2) { + // compressed block, dynamic codes + var numLitCodes = this.getBits(5) + 257; + var numDistCodes = this.getBits(5) + 1; + var numCodeLenCodes = this.getBits(4) + 4; // build the code lengths code table + + var codeLenCodeLengths = Array(codeLenCodeMap.length); + var i = 0; + + while (i < numCodeLenCodes) codeLenCodeLengths[codeLenCodeMap[i++]] = this.getBits(3); + + var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths); // build the literal and distance code tables + + var len = 0; + var i = 0; + var codes = numLitCodes + numDistCodes; + var codeLengths = new Array(codes); + + while (i < codes) { + var code = this.getCode(codeLenCodeTab); + + if (code == 16) { + repeat(this, codeLengths, 2, 3, len); + } else if (code == 17) { + repeat(this, codeLengths, 3, 3, len = 0); + } else if (code == 18) { + repeat(this, codeLengths, 7, 11, len = 0); + } else { + codeLengths[i++] = len = code; + } + } + + litCodeTable = this.generateHuffmanTable(codeLengths.slice(0, numLitCodes)); + distCodeTable = this.generateHuffmanTable(codeLengths.slice(numLitCodes, codes)); + } else { + error("Unknown block type in flate stream"); + } + + var buffer = this.buffer; + var limit = buffer ? buffer.length : 0; + var pos = this.bufferLength; + + while (true) { + var code1 = this.getCode(litCodeTable); + + if (code1 < 256) { + if (pos + 1 >= limit) { + buffer = this.ensureBuffer(pos + 1); + limit = buffer.length; + } + + buffer[pos++] = code1; + continue; + } + + if (code1 == 256) { + this.bufferLength = pos; + return; + } + + code1 -= 257; + code1 = lengthDecode[code1]; + var code2 = code1 >> 16; + if (code2 > 0) code2 = this.getBits(code2); + var len = (code1 & 0xffff) + code2; + code1 = this.getCode(distCodeTable); + code1 = distDecode[code1]; + code2 = code1 >> 16; + if (code2 > 0) code2 = this.getBits(code2); + var dist = (code1 & 0xffff) + code2; + + if (pos + len >= limit) { + buffer = this.ensureBuffer(pos + len); + limit = buffer.length; + } + + for (var k = 0; k < len; ++k, ++pos) buffer[pos] = buffer[pos - dist]; + } + }; + + return constructor; + }(); + + exports.default = jsPDF; + var _default2 = exports.default; + function rewire($stub) { + exports.default = $stub; + } + function restore() { + exports.default = _default2; + } + + exports.rewire = rewire; + exports.restore = restore; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/highcharts/lib/rgbcolor.js b/highcharts/lib/rgbcolor.js new file mode 100644 index 0000000..6ed15cb --- /dev/null +++ b/highcharts/lib/rgbcolor.js @@ -0,0 +1,17 @@ +/* + + A class to parse color values + @author Stoyan Stefanov + @link http://www.phpied.com/rgb-color-parser-in-javascript/ + @license Use it if you like it +*/ +(function(f){function g(b){this.ok=!1;"#"==b.charAt(0)&&(b=b.substr(1,6));b=b.replace(/ /g,"");b=b.toLowerCase();var m={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",feldspar:"d19275",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", +lightslateblue:"8470ff",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",violetred:"d02090",wheat:"f5deb3",white:"ffffff",whitesmoke:"f5f5f5",yellow:"ffff00",yellowgreen:"9acd32"},e;for(e in m)b==e&&(b=m[e]);var h=[{re:/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,example:["rgb(123, 234, 45)","rgb(255,234,245)"],process:function(a){return[parseInt(a[1]),parseInt(a[2]),parseInt(a[3])]}},{re:/^(\w{2})(\w{2})(\w{2})$/, +example:["#00ff00","336699"],process:function(a){return[parseInt(a[1],16),parseInt(a[2],16),parseInt(a[3],16)]}},{re:/^(\w{1})(\w{1})(\w{1})$/,example:["#fb0","f0f"],process:function(a){return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)]}}];for(e=0;ethis.r||isNaN(this.r)?0:255this.g||isNaN(this.g)?0: +255this.b||isNaN(this.b)?0:255 "+l.toRGB()+" -> "+l.toHex());f.appendChild(n);f.appendChild(k);d.appendChild(f)}catch(p){}return d}}"function"===typeof define&&define.amd?define(function(){return g}): +"undefined"!==typeof module&&module.exports?module.exports=g:f.RGBColor=g;return g})("undefined"!==typeof self&&self||"undefined"!==typeof window&&window||this); \ No newline at end of file diff --git a/highcharts/lib/rgbcolor.src.js b/highcharts/lib/rgbcolor.src.js new file mode 100644 index 0000000..b2195eb --- /dev/null +++ b/highcharts/lib/rgbcolor.src.js @@ -0,0 +1,299 @@ +/** @preserve + * A class to parse color values + * @author Stoyan Stefanov + * @link http://www.phpied.com/rgb-color-parser-in-javascript/ + * @license Use it if you like it + */ +(function (global) { +function RGBColor(color_string) +{ + this.ok = false; + + // strip any leading # + if (color_string.charAt(0) == '#') { // remove # if any + color_string = color_string.substr(1,6); + } + + color_string = color_string.replace(/ /g,''); + color_string = color_string.toLowerCase(); + + // before getting into regexps, try simple matches + // and overwrite the input + var simple_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', + feldspar: 'd19275', + 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', + lightslateblue: '8470ff', + 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', + violetred: 'd02090', + wheat: 'f5deb3', + white: 'ffffff', + whitesmoke: 'f5f5f5', + yellow: 'ffff00', + yellowgreen: '9acd32' + }; + for (var key in simple_colors) { + if (color_string == key) { + color_string = simple_colors[key]; + } + } + // emd of simple type-in colors + + // array of color definition objects + var color_defs = [ + { + re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, + example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'], + process: function (bits){ + return [ + parseInt(bits[1]), + parseInt(bits[2]), + parseInt(bits[3]) + ]; + } + }, + { + re: /^(\w{2})(\w{2})(\w{2})$/, + example: ['#00ff00', '336699'], + process: function (bits){ + return [ + parseInt(bits[1], 16), + parseInt(bits[2], 16), + parseInt(bits[3], 16) + ]; + } + }, + { + re: /^(\w{1})(\w{1})(\w{1})$/, + example: ['#fb0', 'f0f'], + process: function (bits){ + return [ + parseInt(bits[1] + bits[1], 16), + parseInt(bits[2] + bits[2], 16), + parseInt(bits[3] + bits[3], 16) + ]; + } + } + ]; + + // search through the definitions to find a match + for (var i = 0; i < color_defs.length; i++) { + var re = color_defs[i].re; + var processor = color_defs[i].process; + var bits = re.exec(color_string); + if (bits) { + channels = processor(bits); + this.r = channels[0]; + this.g = channels[1]; + this.b = channels[2]; + this.ok = true; + } + + } + + // validate/cleanup values + this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r); + this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g); + this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b); + + // some getters + this.toRGB = function () { + return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')'; + } + this.toHex = function () { + var r = this.r.toString(16); + var g = this.g.toString(16); + var b = this.b.toString(16); + if (r.length == 1) r = '0' + r; + if (g.length == 1) g = '0' + g; + if (b.length == 1) b = '0' + b; + return '#' + r + g + b; + } + + // help + this.getHelpXML = function () { + + var examples = new Array(); + // add regexps + for (var i = 0; i < color_defs.length; i++) { + var example = color_defs[i].example; + for (var j = 0; j < example.length; j++) { + examples[examples.length] = example[j]; + } + } + // add type-in colors + for (var sc in simple_colors) { + examples[examples.length] = sc; + } + + var xml = document.createElement('ul'); + xml.setAttribute('id', 'rgbcolor-examples'); + for (var i = 0; i < examples.length; i++) { + try { + var list_item = document.createElement('li'); + var list_color = new RGBColor(examples[i]); + var example_div = document.createElement('div'); + example_div.style.cssText = + 'margin: 3px; ' + + 'border: 1px solid black; ' + + 'background:' + list_color.toHex() + '; ' + + 'color:' + list_color.toHex() + ; + example_div.appendChild(document.createTextNode('test')); + var list_item_value = document.createTextNode( + ' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex() + ); + list_item.appendChild(example_div); + list_item.appendChild(list_item_value); + xml.appendChild(list_item); + + } catch(e){} + } + return xml; + + } + +} +if (typeof define === "function" && define.amd) { + define(function () { + return RGBColor; + }); +} else if (typeof module !== "undefined" && module.exports) { + module.exports = RGBColor; +} else { + global.RGBColor = RGBColor; +} +return RGBColor; +})(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this); \ No newline at end of file diff --git a/highcharts/lib/svg2pdf.js b/highcharts/lib/svg2pdf.js new file mode 100644 index 0000000..53607af --- /dev/null +++ b/highcharts/lib/svg2pdf.js @@ -0,0 +1,38 @@ +/** + * Modules in this bundle + * @license + * + * svg2pdf.js: + * license: MIT (http://opensource.org/licenses/MIT) + * author: yFiles for HTML Support Team + * homepage: https://github.com/yWorks/svg2pdf.js#readme + * version: 1.3.1 + * + * cssesc: + * license: MIT (http://opensource.org/licenses/MIT) + * author: Mathias Bynens + * homepage: https://mths.be/cssesc + * version: 2.0.0 + * + * font-family: + * license: MIT (http://opensource.org/licenses/MIT) + * author: Taro Hanamura + * homepage: https://github.com/hanamura/font-family + * version: 0.2.0 + * + * svgpath: + * license: MIT (http://opensource.org/licenses/MIT) + * homepage: https://github.com/fontello/svgpath#readme + * version: 2.2.1 + * + * This header is generated by licensify (https://github.com/twada/licensify) + */ +!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).svg2pdf=t()}}(function(){return function n(s,o,h){function c(e,t){if(!o[e]){if(!s[e]){var r="function"==typeof require&&require;if(!t&&r)return r(e,!0);if(u)return u(e,!0);var a=new Error("Cannot find module '"+e+"'");throw a.code="MODULE_NOT_FOUND",a}var i=o[e]={exports:{}};s[e][0].call(i.exports,function(t){return c(s[e][1][t]||t)},i,i.exports,n,s,o,h)}return o[e].exports}for(var u="function"==typeof require&&require,t=0;tMath.abs(c-n)?(c-i)/h:h/(c-n))/Math.PI,0<=this.ax?(this.rx=Math.sqrt(c),this.ry=Math.sqrt(u)):(this.ax+=90,this.rx=Math.sqrt(u),this.ry=Math.sqrt(c)),this},a.prototype.isDegenerate=function(){return this.rx=s[r]&&(t.result.push([e].concat(a.splice(0,s[r]))),s[r]););}function n(t){var e,r,a,i=t.max;if(t.segmentStart=t.index,function(t){switch(32|t){case 109:case 122:case 108:case 104:case 118:case 99:case 115:case 113:case 116:case 97:case 114:return!0}return!1}(t.path.charCodeAt(t.index)))if(r=s[t.path[t.index].toLowerCase()],t.index++,o(t),t.data=[],r){for(e=!1;;){for(a=r;0=t.max)break;if(!(48<=(n=t.path.charCodeAt(t.index))&&n<=57||43===n||45===n||46===n))break}}var n;u(t)}else u(t);else t.err="SvgPath: bad command "+t.path[t.index]+" (at pos "+t.index+")"}e.exports=function(t){var e=new i(t),r=e.max;for(o(e);e.index + * @link http://www.phpied.com/rgb-color-parser-in-javascript/ + * @license Use it if you like it + */ +!function(t){function f(t){this.ok=!1,"#"==t.charAt(0)&&(t=t.substr(1,6)),t=(t=t.replace(/ /g,"")).toLowerCase();var u={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",feldspar:"d19275",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",lightslateblue:"8470ff",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",violetred:"d02090",wheat:"f5deb3",white:"ffffff",whitesmoke:"f5f5f5",yellow:"ffff00",yellowgreen:"9acd32"};for(var e in u)t==e&&(t=u[e]);for(var l=[{re:/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,example:["rgb(123, 234, 45)","rgb(255,234,245)"],process:function(t){return[parseInt(t[1]),parseInt(t[2]),parseInt(t[3])]}},{re:/^(\w{2})(\w{2})(\w{2})$/,example:["#00ff00","336699"],process:function(t){return[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)]}},{re:/^(\w{1})(\w{1})(\w{1})$/,example:["#fb0","f0f"],process:function(t){return[parseInt(t[1]+t[1],16),parseInt(t[2]+t[2],16),parseInt(t[3]+t[3],16)]}}],r=0;r "+o.toRGB()+" -> "+o.toHex());s.appendChild(h),s.appendChild(c),n.appendChild(s)}catch(t){}return n}}void 0!==e&&e.exports?e.exports=f:t.RGBColor=f}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this)},{}],11:[function(r,p,t){!function(t){var rt,u,c,i,at,it=/url\(["']?#([^"']+)["']?\)/,nt=/^\s*data:(([^/,;]+\/[^/,;]+)(?:;([^,;=]+=[^,;=]+))?)?(?:;(base64))?,(.*\s*)$/i,h="http://www.w3.org/2000/svg",st=function(t){var e=t.getAttribute("d");u&&(e=u(e).unshort().unarc().abs().toString(),t.setAttribute("d",e));var r=t.pathSegList;if(r)return r;r=[];for(var a,i=/([a-df-zA-DF-Z])([^a-df-zA-DF-Z]*)/g;a=i.exec(e);){var n=kt(a[2]),s=a[1],o=0<="zZ".indexOf(s)?0:0<="hHvV".indexOf(s)?1:0<="mMlLtT".indexOf(s)?2:0<="sSqQ".indexOf(s)?4:0<="aA".indexOf(s)?7:0<="cC".indexOf(s)?6:-1,h=0;do{var c={pathSegTypeAsLetter:s};switch(s){case"h":case"H":c.x=n[h];break;case"v":case"V":c.y=n[h];break;case"c":case"C":c.x1=n[h+o-6],c.y1=n[h+o-5];case"s":case"S":c.x2=n[h+o-4],c.y2=n[h+o-3];case"t":case"T":case"l":case"L":case"m":case"M":c.x=n[h+o-2],c.y=n[h+o-1];break;case"q":case"Q":c.x1=n[h],c.y1=n[h+1],c.x=n[h+2],c.y=n[h+3];break;case"a":case"A":throw new Error("Cannot convert Arcs without SvgPath package")}r.push(c),"m"===s?s="l":"M"===s&&(s="L"),h+=o}while(h",o={};return function(t){var e=o[t];if(!e){var r=i(s,t,"16px","normal","normal"),a=n(s,t,"16px","normal","normal");e=Math.abs(r-a)<.1?i:n,o[t]=e}return e}}();function N(t,e){if(0===t.length)return 0;var r=e.fontFamily;return a(r)(t,e.fontFamily,e.fontSize+"px",e.fontStyle,e.fontWeight)}function q(t,e,r){this.texts=[],this.textNodes=[],this.textAnchor=t,this.originX=e,this.originY=r}function P(t,e){var r;return(r=t&&t.toString().match(/^([\-0-9.]+)em$/))?parseFloat(r[1])*e:(r=t&&t.toString().match(/^([\-0-9.]+)(px|)$/))?parseFloat(r[1]):0}q.prototype.add=function(t,e){this.texts.push(e),this.textNodes.push(t)},q.prototype.put=function(t,e){var r,a,i,n=[],s=[],o=[],h=this.originX,c=this.originY,u=h,l=h;for(r=0;r + * homepage: https://github.com/yWorks/svg2pdf.js#readme + * version: 1.3.1 + * + * cssesc: + * license: MIT (http://opensource.org/licenses/MIT) + * author: Mathias Bynens + * homepage: https://mths.be/cssesc + * version: 2.0.0 + * + * font-family: + * license: MIT (http://opensource.org/licenses/MIT) + * author: Taro Hanamura + * homepage: https://github.com/hanamura/font-family + * version: 0.2.0 + * + * svgpath: + * license: MIT (http://opensource.org/licenses/MIT) + * homepage: https://github.com/fontello/svgpath#readme + * version: 2.2.1 + * + * This header is generated by licensify (https://github.com/twada/licensify) + */ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.svg2pdf = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 1.0) { div = 1.0; } + if (div < -1.0) { div = -1.0; } + + return sign * Math.acos(div); +} + + +// Convert from endpoint to center parameterization, +// see http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes +// +// Return [cx, cy, theta1, delta_theta] +// +function get_arc_center(x1, y1, x2, y2, fa, fs, rx, ry, sin_phi, cos_phi) { + // Step 1. + // + // Moving an ellipse so origin will be the middlepoint between our two + // points. After that, rotate it to line up ellipse axes with coordinate + // axes. + // + var x1p = cos_phi*(x1-x2)/2 + sin_phi*(y1-y2)/2; + var y1p = -sin_phi*(x1-x2)/2 + cos_phi*(y1-y2)/2; + + var rx_sq = rx * rx; + var ry_sq = ry * ry; + var x1p_sq = x1p * x1p; + var y1p_sq = y1p * y1p; + + // Step 2. + // + // Compute coordinates of the centre of this ellipse (cx', cy') + // in the new coordinate system. + // + var radicant = (rx_sq * ry_sq) - (rx_sq * y1p_sq) - (ry_sq * x1p_sq); + + if (radicant < 0) { + // due to rounding errors it might be e.g. -1.3877787807814457e-17 + radicant = 0; + } + + radicant /= (rx_sq * y1p_sq) + (ry_sq * x1p_sq); + radicant = Math.sqrt(radicant) * (fa === fs ? -1 : 1); + + var cxp = radicant * rx/ry * y1p; + var cyp = radicant * -ry/rx * x1p; + + // Step 3. + // + // Transform back to get centre coordinates (cx, cy) in the original + // coordinate system. + // + var cx = cos_phi*cxp - sin_phi*cyp + (x1+x2)/2; + var cy = sin_phi*cxp + cos_phi*cyp + (y1+y2)/2; + + // Step 4. + // + // Compute angles (theta1, delta_theta). + // + var v1x = (x1p - cxp) / rx; + var v1y = (y1p - cyp) / ry; + var v2x = (-x1p - cxp) / rx; + var v2y = (-y1p - cyp) / ry; + + var theta1 = vector_angle(1, 0, v1x, v1y); + var delta_theta = vector_angle(v1x, v1y, v2x, v2y); + + if (fs === 0 && delta_theta > 0) { + delta_theta -= TAU; + } + if (fs === 1 && delta_theta < 0) { + delta_theta += TAU; + } + + return [ cx, cy, theta1, delta_theta ]; +} + +// +// Approximate one unit arc segment with bézier curves, +// see http://math.stackexchange.com/questions/873224 +// +function approximate_unit_arc(theta1, delta_theta) { + var alpha = 4/3 * Math.tan(delta_theta/4); + + var x1 = Math.cos(theta1); + var y1 = Math.sin(theta1); + var x2 = Math.cos(theta1 + delta_theta); + var y2 = Math.sin(theta1 + delta_theta); + + return [ x1, y1, x1 - y1*alpha, y1 + x1*alpha, x2 + y2*alpha, y2 - x2*alpha, x2, y2 ]; +} + +module.exports = function a2c(x1, y1, x2, y2, fa, fs, rx, ry, phi) { + var sin_phi = Math.sin(phi * TAU / 360); + var cos_phi = Math.cos(phi * TAU / 360); + + // Make sure radii are valid + // + var x1p = cos_phi*(x1-x2)/2 + sin_phi*(y1-y2)/2; + var y1p = -sin_phi*(x1-x2)/2 + cos_phi*(y1-y2)/2; + + if (x1p === 0 && y1p === 0) { + // we're asked to draw line to itself + return []; + } + + if (rx === 0 || ry === 0) { + // one of the radii is zero + return []; + } + + + // Compensate out-of-range radii + // + rx = Math.abs(rx); + ry = Math.abs(ry); + + var lambda = (x1p * x1p) / (rx * rx) + (y1p * y1p) / (ry * ry); + if (lambda > 1) { + rx *= Math.sqrt(lambda); + ry *= Math.sqrt(lambda); + } + + + // Get center parameters (cx, cy, theta1, delta_theta) + // + var cc = get_arc_center(x1, y1, x2, y2, fa, fs, rx, ry, sin_phi, cos_phi); + + var result = []; + var theta1 = cc[2]; + var delta_theta = cc[3]; + + // Split an arc to multiple segments, so each segment + // will be less than τ/4 (= 90°) + // + var segments = Math.max(Math.ceil(Math.abs(delta_theta) / (TAU / 4)), 1); + delta_theta /= segments; + + for (var i = 0; i < segments; i++) { + result.push(approximate_unit_arc(theta1, delta_theta)); + theta1 += delta_theta; + } + + // We have a bezier approximation of a unit circle, + // now need to transform back to the original ellipse + // + return result.map(function (curve) { + for (var i = 0; i < curve.length; i += 2) { + var x = curve[i + 0]; + var y = curve[i + 1]; + + // scale + x *= rx; + y *= ry; + + // rotate + var xp = cos_phi*x - sin_phi*y; + var yp = sin_phi*x + cos_phi*y; + + // translate + curve[i + 0] = xp + cc[0]; + curve[i + 1] = yp + cc[1]; + } + + return curve; + }); +}; + +},{}],3:[function(require,module,exports){ +'use strict'; + +/* eslint-disable space-infix-ops */ + +// The precision used to consider an ellipse as a circle +// +var epsilon = 0.0000000001; + +// To convert degree in radians +// +var torad = Math.PI / 180; + +// Class constructor : +// an ellipse centred at 0 with radii rx,ry and x - axis - angle ax. +// +function Ellipse(rx, ry, ax) { + if (!(this instanceof Ellipse)) { return new Ellipse(rx, ry, ax); } + this.rx = rx; + this.ry = ry; + this.ax = ax; +} + +// Apply a linear transform m to the ellipse +// m is an array representing a matrix : +// - - +// | m[0] m[2] | +// | m[1] m[3] | +// - - +// +Ellipse.prototype.transform = function (m) { + // We consider the current ellipse as image of the unit circle + // by first scale(rx,ry) and then rotate(ax) ... + // So we apply ma = m x rotate(ax) x scale(rx,ry) to the unit circle. + var c = Math.cos(this.ax * torad), s = Math.sin(this.ax * torad); + var ma = [ + this.rx * (m[0]*c + m[2]*s), + this.rx * (m[1]*c + m[3]*s), + this.ry * (-m[0]*s + m[2]*c), + this.ry * (-m[1]*s + m[3]*c) + ]; + + // ma * transpose(ma) = [ J L ] + // [ L K ] + // L is calculated later (if the image is not a circle) + var J = ma[0]*ma[0] + ma[2]*ma[2], + K = ma[1]*ma[1] + ma[3]*ma[3]; + + // the discriminant of the characteristic polynomial of ma * transpose(ma) + var D = ((ma[0]-ma[3])*(ma[0]-ma[3]) + (ma[2]+ma[1])*(ma[2]+ma[1])) * + ((ma[0]+ma[3])*(ma[0]+ma[3]) + (ma[2]-ma[1])*(ma[2]-ma[1])); + + // the "mean eigenvalue" + var JK = (J + K) / 2; + + // check if the image is (almost) a circle + if (D < epsilon * JK) { + // if it is + this.rx = this.ry = Math.sqrt(JK); + this.ax = 0; + return this; + } + + // if it is not a circle + var L = ma[0]*ma[1] + ma[2]*ma[3]; + + D = Math.sqrt(D); + + // {l1,l2} = the two eigen values of ma * transpose(ma) + var l1 = JK + D/2, + l2 = JK - D/2; + // the x - axis - rotation angle is the argument of the l1 - eigenvector + this.ax = (Math.abs(L) < epsilon && Math.abs(l1 - K) < epsilon) ? + 90 + : + Math.atan(Math.abs(L) > Math.abs(l1 - K) ? + (l1 - J) / L + : + L / (l1 - K) + ) * 180 / Math.PI; + + // if ax > 0 => rx = sqrt(l1), ry = sqrt(l2), else exchange axes and ax += 90 + if (this.ax >= 0) { + // if ax in [0,90] + this.rx = Math.sqrt(l1); + this.ry = Math.sqrt(l2); + } else { + // if ax in ]-90,0[ => exchange axes + this.ax += 90; + this.rx = Math.sqrt(l2); + this.ry = Math.sqrt(l1); + } + + return this; +}; + +// Check if the ellipse is (almost) degenerate, i.e. rx = 0 or ry = 0 +// +Ellipse.prototype.isDegenerate = function () { + return (this.rx < epsilon * this.ry || this.ry < epsilon * this.rx); +}; + +module.exports = Ellipse; + +},{}],4:[function(require,module,exports){ +'use strict'; + +// combine 2 matrixes +// m1, m2 - [a, b, c, d, e, g] +// +function combine(m1, m2) { + return [ + m1[0] * m2[0] + m1[2] * m2[1], + m1[1] * m2[0] + m1[3] * m2[1], + m1[0] * m2[2] + m1[2] * m2[3], + m1[1] * m2[2] + m1[3] * m2[3], + m1[0] * m2[4] + m1[2] * m2[5] + m1[4], + m1[1] * m2[4] + m1[3] * m2[5] + m1[5] + ]; +} + + +function Matrix() { + if (!(this instanceof Matrix)) { return new Matrix(); } + this.queue = []; // list of matrixes to apply + this.cache = null; // combined matrix cache +} + + +Matrix.prototype.matrix = function (m) { + if (m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 1 && m[4] === 0 && m[5] === 0) { + return this; + } + this.cache = null; + this.queue.push(m); + return this; +}; + + +Matrix.prototype.translate = function (tx, ty) { + if (tx !== 0 || ty !== 0) { + this.cache = null; + this.queue.push([ 1, 0, 0, 1, tx, ty ]); + } + return this; +}; + + +Matrix.prototype.scale = function (sx, sy) { + if (sx !== 1 || sy !== 1) { + this.cache = null; + this.queue.push([ sx, 0, 0, sy, 0, 0 ]); + } + return this; +}; + + +Matrix.prototype.rotate = function (angle, rx, ry) { + var rad, cos, sin; + + if (angle !== 0) { + this.translate(rx, ry); + + rad = angle * Math.PI / 180; + cos = Math.cos(rad); + sin = Math.sin(rad); + + this.queue.push([ cos, sin, -sin, cos, 0, 0 ]); + this.cache = null; + + this.translate(-rx, -ry); + } + return this; +}; + + +Matrix.prototype.skewX = function (angle) { + if (angle !== 0) { + this.cache = null; + this.queue.push([ 1, 0, Math.tan(angle * Math.PI / 180), 1, 0, 0 ]); + } + return this; +}; + + +Matrix.prototype.skewY = function (angle) { + if (angle !== 0) { + this.cache = null; + this.queue.push([ 1, Math.tan(angle * Math.PI / 180), 0, 1, 0, 0 ]); + } + return this; +}; + + +// Flatten queue +// +Matrix.prototype.toArray = function () { + if (this.cache) { + return this.cache; + } + + if (!this.queue.length) { + this.cache = [ 1, 0, 0, 1, 0, 0 ]; + return this.cache; + } + + this.cache = this.queue[0]; + + if (this.queue.length === 1) { + return this.cache; + } + + for (var i = 1; i < this.queue.length; i++) { + this.cache = combine(this.cache, this.queue[i]); + } + + return this.cache; +}; + + +// Apply list of matrixes to (x,y) point. +// If `isRelative` set, `translate` component of matrix will be skipped +// +Matrix.prototype.calc = function (x, y, isRelative) { + var m; + + // Don't change point on empty transforms queue + if (!this.queue.length) { return [ x, y ]; } + + // Calculate final matrix, if not exists + // + // NB. if you deside to apply transforms to point one-by-one, + // they should be taken in reverse order + + if (!this.cache) { + this.cache = this.toArray(); + } + + m = this.cache; + + // Apply matrix to point + return [ + x * m[0] + y * m[2] + (isRelative ? 0 : m[4]), + x * m[1] + y * m[3] + (isRelative ? 0 : m[5]) + ]; +}; + + +module.exports = Matrix; + +},{}],5:[function(require,module,exports){ +'use strict'; + + +var paramCounts = { a: 7, c: 6, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, z: 0 }; + +var SPECIAL_SPACES = [ + 0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, + 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF +]; + +function isSpace(ch) { + return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029) || // Line terminators + // White spaces + (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) || + (ch >= 0x1680 && SPECIAL_SPACES.indexOf(ch) >= 0); +} + +function isCommand(code) { + /*eslint-disable no-bitwise*/ + switch (code | 0x20) { + case 0x6D/* m */: + case 0x7A/* z */: + case 0x6C/* l */: + case 0x68/* h */: + case 0x76/* v */: + case 0x63/* c */: + case 0x73/* s */: + case 0x71/* q */: + case 0x74/* t */: + case 0x61/* a */: + case 0x72/* r */: + return true; + } + return false; +} + +function isDigit(code) { + return (code >= 48 && code <= 57); // 0..9 +} + +function isDigitStart(code) { + return (code >= 48 && code <= 57) || /* 0..9 */ + code === 0x2B || /* + */ + code === 0x2D || /* - */ + code === 0x2E; /* . */ +} + + +function State(path) { + this.index = 0; + this.path = path; + this.max = path.length; + this.result = []; + this.param = 0.0; + this.err = ''; + this.segmentStart = 0; + this.data = []; +} + +function skipSpaces(state) { + while (state.index < state.max && isSpace(state.path.charCodeAt(state.index))) { + state.index++; + } +} + + +function scanParam(state) { + var start = state.index, + index = start, + max = state.max, + zeroFirst = false, + hasCeiling = false, + hasDecimal = false, + hasDot = false, + ch; + + if (index >= max) { + state.err = 'SvgPath: missed param (at pos ' + index + ')'; + return; + } + ch = state.path.charCodeAt(index); + + if (ch === 0x2B/* + */ || ch === 0x2D/* - */) { + index++; + ch = (index < max) ? state.path.charCodeAt(index) : 0; + } + + // This logic is shamelessly borrowed from Esprima + // https://github.com/ariya/esprimas + // + if (!isDigit(ch) && ch !== 0x2E/* . */) { + state.err = 'SvgPath: param should start with 0..9 or `.` (at pos ' + index + ')'; + return; + } + + if (ch !== 0x2E/* . */) { + zeroFirst = (ch === 0x30/* 0 */); + index++; + + ch = (index < max) ? state.path.charCodeAt(index) : 0; + + if (zeroFirst && index < max) { + // decimal number starts with '0' such as '09' is illegal. + if (ch && isDigit(ch)) { + state.err = 'SvgPath: numbers started with `0` such as `09` are ilegal (at pos ' + start + ')'; + return; + } + } + + while (index < max && isDigit(state.path.charCodeAt(index))) { + index++; + hasCeiling = true; + } + ch = (index < max) ? state.path.charCodeAt(index) : 0; + } + + if (ch === 0x2E/* . */) { + hasDot = true; + index++; + while (isDigit(state.path.charCodeAt(index))) { + index++; + hasDecimal = true; + } + ch = (index < max) ? state.path.charCodeAt(index) : 0; + } + + if (ch === 0x65/* e */ || ch === 0x45/* E */) { + if (hasDot && !hasCeiling && !hasDecimal) { + state.err = 'SvgPath: invalid float exponent (at pos ' + index + ')'; + return; + } + + index++; + + ch = (index < max) ? state.path.charCodeAt(index) : 0; + if (ch === 0x2B/* + */ || ch === 0x2D/* - */) { + index++; + } + if (index < max && isDigit(state.path.charCodeAt(index))) { + while (index < max && isDigit(state.path.charCodeAt(index))) { + index++; + } + } else { + state.err = 'SvgPath: invalid float exponent (at pos ' + index + ')'; + return; + } + } + + state.index = index; + state.param = parseFloat(state.path.slice(start, index)) + 0.0; +} + + +function finalizeSegment(state) { + var cmd, cmdLC; + + // Process duplicated commands (without comand name) + + // This logic is shamelessly borrowed from Raphael + // https://github.com/DmitryBaranovskiy/raphael/ + // + cmd = state.path[state.segmentStart]; + cmdLC = cmd.toLowerCase(); + + var params = state.data; + + if (cmdLC === 'm' && params.length > 2) { + state.result.push([ cmd, params[0], params[1] ]); + params = params.slice(2); + cmdLC = 'l'; + cmd = (cmd === 'm') ? 'l' : 'L'; + } + + if (cmdLC === 'r') { + state.result.push([ cmd ].concat(params)); + } else { + + while (params.length >= paramCounts[cmdLC]) { + state.result.push([ cmd ].concat(params.splice(0, paramCounts[cmdLC]))); + if (!paramCounts[cmdLC]) { + break; + } + } + } +} + + +function scanSegment(state) { + var max = state.max, + cmdCode, comma_found, need_params, i; + + state.segmentStart = state.index; + cmdCode = state.path.charCodeAt(state.index); + + if (!isCommand(cmdCode)) { + state.err = 'SvgPath: bad command ' + state.path[state.index] + ' (at pos ' + state.index + ')'; + return; + } + + need_params = paramCounts[state.path[state.index].toLowerCase()]; + + state.index++; + skipSpaces(state); + + state.data = []; + + if (!need_params) { + // Z + finalizeSegment(state); + return; + } + + comma_found = false; + + for (;;) { + for (i = need_params; i > 0; i--) { + scanParam(state); + if (state.err.length) { + return; + } + state.data.push(state.param); + + skipSpaces(state); + comma_found = false; + + if (state.index < max && state.path.charCodeAt(state.index) === 0x2C/* , */) { + state.index++; + skipSpaces(state); + comma_found = true; + } + } + + // after ',' param is mandatory + if (comma_found) { + continue; + } + + if (state.index >= state.max) { + break; + } + + // Stop on next segment + if (!isDigitStart(state.path.charCodeAt(state.index))) { + break; + } + } + + finalizeSegment(state); +} + + +/* Returns array of segments: + * + * [ + * [ command, coord1, coord2, ... ] + * ] + */ +module.exports = function pathParse(svgPath) { + var state = new State(svgPath); + var max = state.max; + + skipSpaces(state); + + while (state.index < max && !state.err.length) { + scanSegment(state); + } + + if (state.err.length) { + state.result = []; + + } else if (state.result.length) { + + if ('mM'.indexOf(state.result[0][0]) < 0) { + state.err = 'SvgPath: string should start with `M` or `m`'; + state.result = []; + } else { + state.result[0][0] = 'M'; + } + } + + return { + err: state.err, + segments: state.result + }; +}; + +},{}],6:[function(require,module,exports){ +// SVG Path transformations library +// +// Usage: +// +// SvgPath('...') +// .translate(-150, -100) +// .scale(0.5) +// .translate(-150, -100) +// .toFixed(1) +// .toString() +// + +'use strict'; + + +var pathParse = require('./path_parse'); +var transformParse = require('./transform_parse'); +var matrix = require('./matrix'); +var a2c = require('./a2c'); +var ellipse = require('./ellipse'); + + +// Class constructor +// +function SvgPath(path) { + if (!(this instanceof SvgPath)) { return new SvgPath(path); } + + var pstate = pathParse(path); + + // Array of path segments. + // Each segment is array [command, param1, param2, ...] + this.segments = pstate.segments; + + // Error message on parse error. + this.err = pstate.err; + + // Transforms stack for lazy evaluation + this.__stack = []; +} + + +SvgPath.prototype.__matrix = function (m) { + var self = this, i; + + // Quick leave for empty matrix + if (!m.queue.length) { return; } + + this.iterate(function (s, index, x, y) { + var p, result, name, isRelative; + + switch (s[0]) { + + // Process 'assymetric' commands separately + case 'v': + p = m.calc(0, s[1], true); + result = (p[0] === 0) ? [ 'v', p[1] ] : [ 'l', p[0], p[1] ]; + break; + + case 'V': + p = m.calc(x, s[1], false); + result = (p[0] === m.calc(x, y, false)[0]) ? [ 'V', p[1] ] : [ 'L', p[0], p[1] ]; + break; + + case 'h': + p = m.calc(s[1], 0, true); + result = (p[1] === 0) ? [ 'h', p[0] ] : [ 'l', p[0], p[1] ]; + break; + + case 'H': + p = m.calc(s[1], y, false); + result = (p[1] === m.calc(x, y, false)[1]) ? [ 'H', p[0] ] : [ 'L', p[0], p[1] ]; + break; + + case 'a': + case 'A': + // ARC is: ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] + + // Drop segment if arc is empty (end point === start point) + /*if ((s[0] === 'A' && s[6] === x && s[7] === y) || + (s[0] === 'a' && s[6] === 0 && s[7] === 0)) { + return []; + }*/ + + // Transform rx, ry and the x-axis-rotation + var ma = m.toArray(); + var e = ellipse(s[1], s[2], s[3]).transform(ma); + + // flip sweep-flag if matrix is not orientation-preserving + if (ma[0] * ma[3] - ma[1] * ma[2] < 0) { + s[5] = s[5] ? '0' : '1'; + } + + // Transform end point as usual (without translation for relative notation) + p = m.calc(s[6], s[7], s[0] === 'a'); + + // Empty arcs can be ignored by renderer, but should not be dropped + // to avoid collisions with `S A S` and so on. Replace with empty line. + if ((s[0] === 'A' && s[6] === x && s[7] === y) || + (s[0] === 'a' && s[6] === 0 && s[7] === 0)) { + result = [ s[0] === 'a' ? 'l' : 'L', p[0], p[1] ]; + break; + } + + // if the resulting ellipse is (almost) a segment ... + if (e.isDegenerate()) { + // replace the arc by a line + result = [ s[0] === 'a' ? 'l' : 'L', p[0], p[1] ]; + } else { + // if it is a real ellipse + // s[0], s[4] and s[5] are not modified + result = [ s[0], e.rx, e.ry, e.ax, s[4], s[5], p[0], p[1] ]; + } + + break; + + case 'm': + // Edge case. The very first `m` should be processed as absolute, if happens. + // Make sense for coord shift transforms. + isRelative = index > 0; + + p = m.calc(s[1], s[2], isRelative); + result = [ 'm', p[0], p[1] ]; + break; + + default: + name = s[0]; + result = [ name ]; + isRelative = (name.toLowerCase() === name); + + // Apply transformations to the segment + for (i = 1; i < s.length; i += 2) { + p = m.calc(s[i], s[i + 1], isRelative); + result.push(p[0], p[1]); + } + } + + self.segments[index] = result; + }, true); +}; + + +// Apply stacked commands +// +SvgPath.prototype.__evaluateStack = function () { + var m, i; + + if (!this.__stack.length) { return; } + + if (this.__stack.length === 1) { + this.__matrix(this.__stack[0]); + this.__stack = []; + return; + } + + m = matrix(); + i = this.__stack.length; + + while (--i >= 0) { + m.matrix(this.__stack[i].toArray()); + } + + this.__matrix(m); + this.__stack = []; +}; + + +// Convert processed SVG Path back to string +// +SvgPath.prototype.toString = function () { + var elements = [], skipCmd, cmd; + + this.__evaluateStack(); + + for (var i = 0; i < this.segments.length; i++) { + // remove repeating commands names + cmd = this.segments[i][0]; + skipCmd = i > 0 && cmd !== 'm' && cmd !== 'M' && cmd === this.segments[i - 1][0]; + elements = elements.concat(skipCmd ? this.segments[i].slice(1) : this.segments[i]); + } + + return elements.join(' ') + // Optimizations: remove spaces around commands & before `-` + // + // We could also remove leading zeros for `0.5`-like values, + // but their count is too small to spend time for. + .replace(/ ?([achlmqrstvz]) ?/gi, '$1') + .replace(/ \-/g, '-') + // workaround for FontForge SVG importing bug + .replace(/zm/g, 'z m'); +}; + + +// Translate path to (x [, y]) +// +SvgPath.prototype.translate = function (x, y) { + this.__stack.push(matrix().translate(x, y || 0)); + return this; +}; + + +// Scale path to (sx [, sy]) +// sy = sx if not defined +// +SvgPath.prototype.scale = function (sx, sy) { + this.__stack.push(matrix().scale(sx, (!sy && (sy !== 0)) ? sx : sy)); + return this; +}; + + +// Rotate path around point (sx [, sy]) +// sy = sx if not defined +// +SvgPath.prototype.rotate = function (angle, rx, ry) { + this.__stack.push(matrix().rotate(angle, rx || 0, ry || 0)); + return this; +}; + + +// Skew path along the X axis by `degrees` angle +// +SvgPath.prototype.skewX = function (degrees) { + this.__stack.push(matrix().skewX(degrees)); + return this; +}; + + +// Skew path along the Y axis by `degrees` angle +// +SvgPath.prototype.skewY = function (degrees) { + this.__stack.push(matrix().skewY(degrees)); + return this; +}; + + +// Apply matrix transform (array of 6 elements) +// +SvgPath.prototype.matrix = function (m) { + this.__stack.push(matrix().matrix(m)); + return this; +}; + + +// Transform path according to "transform" attr of SVG spec +// +SvgPath.prototype.transform = function (transformString) { + if (!transformString.trim()) { + return this; + } + this.__stack.push(transformParse(transformString)); + return this; +}; + + +// Round coords with given decimal precition. +// 0 by default (to integers) +// +SvgPath.prototype.round = function (d) { + var contourStartDeltaX = 0, contourStartDeltaY = 0, deltaX = 0, deltaY = 0, l; + + d = d || 0; + + this.__evaluateStack(); + + this.segments.forEach(function (s) { + var isRelative = (s[0].toLowerCase() === s[0]); + + switch (s[0]) { + case 'H': + case 'h': + if (isRelative) { s[1] += deltaX; } + deltaX = s[1] - s[1].toFixed(d); + s[1] = +s[1].toFixed(d); + return; + + case 'V': + case 'v': + if (isRelative) { s[1] += deltaY; } + deltaY = s[1] - s[1].toFixed(d); + s[1] = +s[1].toFixed(d); + return; + + case 'Z': + case 'z': + deltaX = contourStartDeltaX; + deltaY = contourStartDeltaY; + return; + + case 'M': + case 'm': + if (isRelative) { + s[1] += deltaX; + s[2] += deltaY; + } + + deltaX = s[1] - s[1].toFixed(d); + deltaY = s[2] - s[2].toFixed(d); + + contourStartDeltaX = deltaX; + contourStartDeltaY = deltaY; + + s[1] = +s[1].toFixed(d); + s[2] = +s[2].toFixed(d); + return; + + case 'A': + case 'a': + // [cmd, rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] + if (isRelative) { + s[6] += deltaX; + s[7] += deltaY; + } + + deltaX = s[6] - s[6].toFixed(d); + deltaY = s[7] - s[7].toFixed(d); + + s[1] = +s[1].toFixed(d); + s[2] = +s[2].toFixed(d); + s[3] = +s[3].toFixed(d + 2); // better precision for rotation + s[6] = +s[6].toFixed(d); + s[7] = +s[7].toFixed(d); + return; + + default: + // a c l q s t + l = s.length; + + if (isRelative) { + s[l - 2] += deltaX; + s[l - 1] += deltaY; + } + + deltaX = s[l - 2] - s[l - 2].toFixed(d); + deltaY = s[l - 1] - s[l - 1].toFixed(d); + + s.forEach(function (val, i) { + if (!i) { return; } + s[i] = +s[i].toFixed(d); + }); + return; + } + }); + + return this; +}; + + +// Apply iterator function to all segments. If function returns result, +// current segment will be replaced to array of returned segments. +// If empty array is returned, current regment will be deleted. +// +SvgPath.prototype.iterate = function (iterator, keepLazyStack) { + var segments = this.segments, + replacements = {}, + needReplace = false, + lastX = 0, + lastY = 0, + countourStartX = 0, + countourStartY = 0; + var i, j, newSegments; + + if (!keepLazyStack) { + this.__evaluateStack(); + } + + segments.forEach(function (s, index) { + + var res = iterator(s, index, lastX, lastY); + + if (Array.isArray(res)) { + replacements[index] = res; + needReplace = true; + } + + var isRelative = (s[0] === s[0].toLowerCase()); + + // calculate absolute X and Y + switch (s[0]) { + case 'm': + case 'M': + lastX = s[1] + (isRelative ? lastX : 0); + lastY = s[2] + (isRelative ? lastY : 0); + countourStartX = lastX; + countourStartY = lastY; + return; + + case 'h': + case 'H': + lastX = s[1] + (isRelative ? lastX : 0); + return; + + case 'v': + case 'V': + lastY = s[1] + (isRelative ? lastY : 0); + return; + + case 'z': + case 'Z': + // That make sence for multiple contours + lastX = countourStartX; + lastY = countourStartY; + return; + + default: + lastX = s[s.length - 2] + (isRelative ? lastX : 0); + lastY = s[s.length - 1] + (isRelative ? lastY : 0); + } + }); + + // Replace segments if iterator return results + + if (!needReplace) { return this; } + + newSegments = []; + + for (i = 0; i < segments.length; i++) { + if (typeof replacements[i] !== 'undefined') { + for (j = 0; j < replacements[i].length; j++) { + newSegments.push(replacements[i][j]); + } + } else { + newSegments.push(segments[i]); + } + } + + this.segments = newSegments; + + return this; +}; + + +// Converts segments from relative to absolute +// +SvgPath.prototype.abs = function () { + + this.iterate(function (s, index, x, y) { + var name = s[0], + nameUC = name.toUpperCase(), + i; + + // Skip absolute commands + if (name === nameUC) { return; } + + s[0] = nameUC; + + switch (name) { + case 'v': + // v has shifted coords parity + s[1] += y; + return; + + case 'a': + // ARC is: ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] + // touch x, y only + s[6] += x; + s[7] += y; + return; + + default: + for (i = 1; i < s.length; i++) { + s[i] += i % 2 ? x : y; // odd values are X, even - Y + } + } + }, true); + + return this; +}; + + +// Converts segments from absolute to relative +// +SvgPath.prototype.rel = function () { + + this.iterate(function (s, index, x, y) { + var name = s[0], + nameLC = name.toLowerCase(), + i; + + // Skip relative commands + if (name === nameLC) { return; } + + // Don't touch the first M to avoid potential confusions. + if (index === 0 && name === 'M') { return; } + + s[0] = nameLC; + + switch (name) { + case 'V': + // V has shifted coords parity + s[1] -= y; + return; + + case 'A': + // ARC is: ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] + // touch x, y only + s[6] -= x; + s[7] -= y; + return; + + default: + for (i = 1; i < s.length; i++) { + s[i] -= i % 2 ? x : y; // odd values are X, even - Y + } + } + }, true); + + return this; +}; + + +// Converts arcs to cubic bézier curves +// +SvgPath.prototype.unarc = function () { + this.iterate(function (s, index, x, y) { + var new_segments, nextX, nextY, result = [], name = s[0]; + + // Skip anything except arcs + if (name !== 'A' && name !== 'a') { return null; } + + if (name === 'a') { + // convert relative arc coordinates to absolute + nextX = x + s[6]; + nextY = y + s[7]; + } else { + nextX = s[6]; + nextY = s[7]; + } + + new_segments = a2c(x, y, nextX, nextY, s[4], s[5], s[1], s[2], s[3]); + + // Degenerated arcs can be ignored by renderer, but should not be dropped + // to avoid collisions with `S A S` and so on. Replace with empty line. + if (new_segments.length === 0) { + return [ [ s[0] === 'a' ? 'l' : 'L', s[6], s[7] ] ]; + } + + new_segments.forEach(function (s) { + result.push([ 'C', s[2], s[3], s[4], s[5], s[6], s[7] ]); + }); + + return result; + }); + + return this; +}; + + +// Converts smooth curves (with missed control point) to generic curves +// +SvgPath.prototype.unshort = function () { + var segments = this.segments; + var prevControlX, prevControlY, prevSegment; + var curControlX, curControlY; + + // TODO: add lazy evaluation flag when relative commands supported + + this.iterate(function (s, idx, x, y) { + var name = s[0], nameUC = name.toUpperCase(), isRelative; + + // First command MUST be M|m, it's safe to skip. + // Protect from access to [-1] for sure. + if (!idx) { return; } + + if (nameUC === 'T') { // quadratic curve + isRelative = (name === 't'); + + prevSegment = segments[idx - 1]; + + if (prevSegment[0] === 'Q') { + prevControlX = prevSegment[1] - x; + prevControlY = prevSegment[2] - y; + } else if (prevSegment[0] === 'q') { + prevControlX = prevSegment[1] - prevSegment[3]; + prevControlY = prevSegment[2] - prevSegment[4]; + } else { + prevControlX = 0; + prevControlY = 0; + } + + curControlX = -prevControlX; + curControlY = -prevControlY; + + if (!isRelative) { + curControlX += x; + curControlY += y; + } + + segments[idx] = [ + isRelative ? 'q' : 'Q', + curControlX, curControlY, + s[1], s[2] + ]; + + } else if (nameUC === 'S') { // cubic curve + isRelative = (name === 's'); + + prevSegment = segments[idx - 1]; + + if (prevSegment[0] === 'C') { + prevControlX = prevSegment[3] - x; + prevControlY = prevSegment[4] - y; + } else if (prevSegment[0] === 'c') { + prevControlX = prevSegment[3] - prevSegment[5]; + prevControlY = prevSegment[4] - prevSegment[6]; + } else { + prevControlX = 0; + prevControlY = 0; + } + + curControlX = -prevControlX; + curControlY = -prevControlY; + + if (!isRelative) { + curControlX += x; + curControlY += y; + } + + segments[idx] = [ + isRelative ? 'c' : 'C', + curControlX, curControlY, + s[1], s[2], s[3], s[4] + ]; + } + }); + + return this; +}; + + +module.exports = SvgPath; + +},{"./a2c":2,"./ellipse":3,"./matrix":4,"./path_parse":5,"./transform_parse":7}],7:[function(require,module,exports){ +'use strict'; + + +var Matrix = require('./matrix'); + +var operations = { + matrix: true, + scale: true, + rotate: true, + translate: true, + skewX: true, + skewY: true +}; + +var CMD_SPLIT_RE = /\s*(matrix|translate|scale|rotate|skewX|skewY)\s*\(\s*(.+?)\s*\)[\s,]*/; +var PARAMS_SPLIT_RE = /[\s,]+/; + + +module.exports = function transformParse(transformString) { + var matrix = new Matrix(); + var cmd, params; + + // Split value into ['', 'translate', '10 50', '', 'scale', '2', '', 'rotate', '-45', ''] + transformString.split(CMD_SPLIT_RE).forEach(function (item) { + + // Skip empty elements + if (!item.length) { return; } + + // remember operation + if (typeof operations[item] !== 'undefined') { + cmd = item; + return; + } + + // extract params & att operation to matrix + params = item.split(PARAMS_SPLIT_RE).map(function (i) { + return +i || 0; + }); + + // If params count is not correct - ignore command + switch (cmd) { + case 'matrix': + if (params.length === 6) { + matrix.matrix(params); + } + return; + + case 'scale': + if (params.length === 1) { + matrix.scale(params[0], params[0]); + } else if (params.length === 2) { + matrix.scale(params[0], params[1]); + } + return; + + case 'rotate': + if (params.length === 1) { + matrix.rotate(params[0], 0, 0); + } else if (params.length === 3) { + matrix.rotate(params[0], params[1], params[2]); + } + return; + + case 'translate': + if (params.length === 1) { + matrix.translate(params[0], 0); + } else if (params.length === 2) { + matrix.translate(params[0], params[1]); + } + return; + + case 'skewX': + if (params.length === 1) { + matrix.skewX(params[0]); + } + return; + + case 'skewY': + if (params.length === 1) { + matrix.skewY(params[0]); + } + return; + } + }); + + return matrix; +}; + +},{"./matrix":4}],8:[function(require,module,exports){ +/*! https://mths.be/cssesc v1.0.1 by @mathias */ +'use strict'; + +var object = {}; +var hasOwnProperty = object.hasOwnProperty; +var merge = function merge(options, defaults) { + if (!options) { + return defaults; + } + var result = {}; + for (var key in defaults) { + // `if (defaults.hasOwnProperty(key) { … }` is not needed here, since + // only recognized option names are used. + result[key] = hasOwnProperty.call(options, key) ? options[key] : defaults[key]; + } + return result; +}; + +var regexAnySingleEscape = /[ -,\.\/;-@\[-\^`\{-~]/; +var regexSingleEscape = /[ -,\.\/;-@\[\]\^`\{-~]/; +var regexAlwaysEscape = /['"\\]/; +var regexExcessiveSpaces = /(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g; + +// https://mathiasbynens.be/notes/css-escapes#css +var cssesc = function cssesc(string, options) { + options = merge(options, cssesc.options); + if (options.quotes != 'single' && options.quotes != 'double') { + options.quotes = 'single'; + } + var quote = options.quotes == 'double' ? '"' : '\''; + var isIdentifier = options.isIdentifier; + + var firstChar = string.charAt(0); + var output = ''; + var counter = 0; + var length = string.length; + while (counter < length) { + var character = string.charAt(counter++); + var codePoint = character.charCodeAt(); + var value = void 0; + // If it’s not a printable ASCII character… + if (codePoint < 0x20 || codePoint > 0x7E) { + if (codePoint >= 0xD800 && codePoint <= 0xDBFF && counter < length) { + // It’s a high surrogate, and there is a next character. + var extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { + // next character is low surrogate + codePoint = ((codePoint & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000; + } else { + // It’s an unmatched surrogate; only append this code unit, in case + // the next code unit is the high surrogate of a surrogate pair. + counter--; + } + } + value = '\\' + codePoint.toString(16).toUpperCase() + ' '; + } else { + if (options.escapeEverything) { + if (regexAnySingleEscape.test(character)) { + value = '\\' + character; + } else { + value = '\\' + codePoint.toString(16).toUpperCase() + ' '; + } + // Note: `:` could be escaped as `\:`, but that fails in IE < 8. + } else if (/[\t\n\f\r\x0B:]/.test(character)) { + if (!isIdentifier && character == ':') { + value = character; + } else { + value = '\\' + codePoint.toString(16).toUpperCase() + ' '; + } + } else if (character == '\\' || !isIdentifier && (character == '"' && quote == character || character == '\'' && quote == character) || isIdentifier && regexSingleEscape.test(character)) { + value = '\\' + character; + } else { + value = character; + } + } + output += value; + } + + if (isIdentifier) { + if (/^_/.test(output)) { + // Prevent IE6 from ignoring the rule altogether (in case this is for an + // identifier used as a selector) + output = '\\_' + output.slice(1); + } else if (/^-[-\d]/.test(output)) { + output = '\\-' + output.slice(1); + } else if (/\d/.test(firstChar)) { + output = '\\3' + firstChar + ' ' + output.slice(1); + } + } + + // Remove spaces after `\HEX` escapes that are not followed by a hex digit, + // since they’re redundant. Note that this is only possible if the escape + // sequence isn’t preceded by an odd number of backslashes. + output = output.replace(regexExcessiveSpaces, function ($0, $1, $2) { + if ($1 && $1.length % 2) { + // It’s not safe to remove the space, so don’t. + return $0; + } + // Strip the space. + return ($1 || '') + $2; + }); + + if (!isIdentifier && options.wrap) { + return quote + output + quote; + } + return output; +}; + +// Expose default options (so they can be overridden globally). +cssesc.options = { + 'escapeEverything': false, + 'isIdentifier': false, + 'quotes': 'single', + 'wrap': false +}; + +cssesc.version = '1.0.1'; + +module.exports = cssesc; + +},{}],9:[function(require,module,exports){ +// parse +// ===== + +// states +// ------ + +var PLAIN = 0; +var STRINGS = 1; +var ESCAPING = 2; +var IDENTIFIER = 3; +var SEPARATING = 4; + +// patterns +// -------- + +var identifierPattern = /[a-z0-9_-]/i; +var spacePattern = /[\s\t]/; + +// --- + +var parse = function(str) { + + // vars + // ---- + + var starting = true; + var state = PLAIN; + var buffer = ''; + var i = 0; + var quote; + var c; + + // result + // ------ + + var names = []; + + // parse + // ----- + + while (true) { + + c = str[i]; + + if (state === PLAIN) { + + if (!c && starting) { + + break; + + } else if (!c && !starting) { + + throw new Error('Parse error'); + + } else if (c === '"' || c === "'") { + + quote = c; + state = STRINGS; + starting = false; + + } else if (spacePattern.test(c)) { + } else if (identifierPattern.test(c)) { + + state = IDENTIFIER; + starting = false; + i--; + + } else { + + throw new Error('Parse error'); + + } + + } else if (state === STRINGS) { + + if (!c) { + + throw new Error('Parse Error'); + + } else if (c === "\\") { + + state = ESCAPING; + + } else if (c === quote) { + + names.push(buffer); + buffer = ''; + state = SEPARATING; + + } else { + + buffer += c; + + } + + } else if (state === ESCAPING) { + + if (c === quote || c === "\\") { + + buffer += c; + state = STRINGS; + + } else { + + throw new Error('Parse error'); + + } + + } else if (state === IDENTIFIER) { + + if (!c) { + + names.push(buffer); + break; + + } else if (identifierPattern.test(c)) { + + buffer += c; + + } else if (c === ',') { + + names.push(buffer); + buffer = ''; + state = PLAIN; + + } else if (spacePattern.test(c)) { + + names.push(buffer); + buffer = ''; + state = SEPARATING; + + } else { + + throw new Error('Parse error'); + + } + + } else if (state === SEPARATING) { + + if (!c) { + + break; + + } else if (c === ',') { + + state = PLAIN; + + } else if (spacePattern.test(c)) { + } else { + + throw new Error('Parse error'); + + } + + } + + i++; + + } + + // result + // ------ + + return names; + +}; + +// stringify +// ========= + +// pattern +// ------- + +var stringsPattern = /[^a-z0-9_-]/i; + +// --- + +var stringify = function(names, options) { + + // quote + // ----- + + var quote = options && options.quote || '"'; + if (quote !== '"' && quote !== "'") { + throw new Error('Quote must be `\'` or `"`'); + } + var quotePattern = new RegExp(quote, 'g'); + + // stringify + // --------- + + var safeNames = []; + + for (var i = 0; i < names.length; ++i) { + var name = names[i]; + + if (stringsPattern.test(name)) { + name = name + .replace(/\\/g, "\\\\") + .replace(quotePattern, "\\" + quote); + name = quote + name + quote; + } + safeNames.push(name); + } + + // result + // ------ + + return safeNames.join(', '); +}; + +// export +// ====== + +module.exports = { + parse: parse, + stringify: stringify, +}; + +},{}],10:[function(require,module,exports){ +/** + * A class to parse color values + * @author Stoyan Stefanov + * @link http://www.phpied.com/rgb-color-parser-in-javascript/ + * @license Use it if you like it + */ +(function (global) { +function RGBColor(color_string) +{ + this.ok = false; + + // strip any leading # + if (color_string.charAt(0) == '#') { // remove # if any + color_string = color_string.substr(1,6); + } + + color_string = color_string.replace(/ /g,''); + color_string = color_string.toLowerCase(); + + // before getting into regexps, try simple matches + // and overwrite the input + var simple_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', + feldspar: 'd19275', + 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', + lightslateblue: '8470ff', + 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', + violetred: 'd02090', + wheat: 'f5deb3', + white: 'ffffff', + whitesmoke: 'f5f5f5', + yellow: 'ffff00', + yellowgreen: '9acd32' + }; + for (var key in simple_colors) { + if (color_string == key) { + color_string = simple_colors[key]; + } + } + // emd of simple type-in colors + + // array of color definition objects + var color_defs = [ + { + re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, + example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'], + process: function (bits){ + return [ + parseInt(bits[1]), + parseInt(bits[2]), + parseInt(bits[3]) + ]; + } + }, + { + re: /^(\w{2})(\w{2})(\w{2})$/, + example: ['#00ff00', '336699'], + process: function (bits){ + return [ + parseInt(bits[1], 16), + parseInt(bits[2], 16), + parseInt(bits[3], 16) + ]; + } + }, + { + re: /^(\w{1})(\w{1})(\w{1})$/, + example: ['#fb0', 'f0f'], + process: function (bits){ + return [ + parseInt(bits[1] + bits[1], 16), + parseInt(bits[2] + bits[2], 16), + parseInt(bits[3] + bits[3], 16) + ]; + } + } + ]; + + // search through the definitions to find a match + for (var i = 0; i < color_defs.length; i++) { + var re = color_defs[i].re; + var processor = color_defs[i].process; + var bits = re.exec(color_string); + if (bits) { + var channels = processor(bits); + this.r = channels[0]; + this.g = channels[1]; + this.b = channels[2]; + this.ok = true; + } + + } + + // validate/cleanup values + this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r); + this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g); + this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b); + + // some getters + this.toRGB = function () { + return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')'; + } + this.toHex = function () { + var r = this.r.toString(16); + var g = this.g.toString(16); + var b = this.b.toString(16); + if (r.length == 1) r = '0' + r; + if (g.length == 1) g = '0' + g; + if (b.length == 1) b = '0' + b; + return '#' + r + g + b; + } + + // help + this.getHelpXML = function () { + + var examples = new Array(); + // add regexps + for (var i = 0; i < color_defs.length; i++) { + var example = color_defs[i].example; + for (var j = 0; j < example.length; j++) { + examples[examples.length] = example[j]; + } + } + // add type-in colors + for (var sc in simple_colors) { + examples[examples.length] = sc; + } + + var xml = document.createElement('ul'); + xml.setAttribute('id', 'rgbcolor-examples'); + for (var i = 0; i < examples.length; i++) { + try { + var list_item = document.createElement('li'); + var list_color = new RGBColor(examples[i]); + var example_div = document.createElement('div'); + example_div.style.cssText = + 'margin: 3px; ' + + 'border: 1px solid black; ' + + 'background:' + list_color.toHex() + '; ' + + 'color:' + list_color.toHex() + ; + example_div.appendChild(document.createTextNode('test')); + var list_item_value = document.createTextNode( + ' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex() + ); + list_item.appendChild(example_div); + list_item.appendChild(list_item_value); + xml.appendChild(list_item); + + } catch(e){} + } + return xml; + + } + +} +if (typeof define === "function" && define.amd) { + define(function () { + return RGBColor; + }); +} else if (typeof module !== "undefined" && module.exports) { + module.exports = RGBColor; +} else { + global.RGBColor = RGBColor; +} +return RGBColor; +})(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this); + +},{}],11:[function(require,module,exports){ +/* +The MIT License (MIT) + +Copyright (c) 2015-2017 yWorks GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * Renders an svg element to a jsPDF document. + * For accurate results a DOM document is required (mainly used for text size measurement and image format conversion) + * @param element {HTMLElement} The svg element, which will be cloned, so the original stays unchanged. + * @param pdf {jsPDF} The jsPDF object. + * @param options {object} An object that may contain render options. Currently supported are: + * scale: The global factor by which everything is scaled. + * xOffset, yOffset: Offsets that are added to every coordinate AFTER scaling (They are not + * influenced by the scale attribute). + */ +(function (global) { + var RGBColor; + var SvgPath; + var FontFamily; + var cssEsc; + + var _pdf; // jsPDF pdf-document + + var cToQ = 2 / 3; // ratio to convert quadratic bezier curves to cubic ones + + var iriReference = /url\(["']?#([^"']+)["']?\)/; + + // groups: 1: mime-type (+ charset), 2: mime-type (w/o charset), 3: charset, 4: base64?, 5: body + var dataUrlRegex = /^\s*data:(([^/,;]+\/[^/,;]+)(?:;([^,;=]+=[^,;=]+))?)?(?:;(base64))?,(.*\s*)$/i; + + var svgNamespaceURI = "http://www.w3.org/2000/svg"; + + + // pathSegList is marked deprecated in chrome, so parse the d attribute manually if necessary + var getPathSegList = function (node) { + var d = node.getAttribute("d"); + + // Replace arcs before path segment list is handled + if (SvgPath) { + d = SvgPath(d).unshort().unarc().abs().toString(); + node.setAttribute('d', d); + } + + var pathSegList = node.pathSegList; + + if (pathSegList) { + return pathSegList; + } + + pathSegList = []; + + var regex = /([a-df-zA-DF-Z])([^a-df-zA-DF-Z]*)/g, + match; + while (match = regex.exec(d)) { + var coords = parseFloats(match[2]); + + var type = match[1]; + var length = "zZ".indexOf(type) >= 0 ? 0 : + "hHvV".indexOf(type) >= 0 ? 1 : + "mMlLtT".indexOf(type) >= 0 ? 2 : + "sSqQ".indexOf(type) >= 0 ? 4 : + "aA".indexOf(type) >= 0 ? 7 : + "cC".indexOf(type) >= 0 ? 6 : -1; + + var i = 0; + do { + var pathSeg = {pathSegTypeAsLetter: type}; + switch (type) { + case "h": + case "H": + pathSeg.x = coords[i]; + break; + + case "v": + case "V": + pathSeg.y = coords[i]; + break; + + case "c": + case "C": + pathSeg.x1 = coords[i + length - 6]; + pathSeg.y1 = coords[i + length - 5]; + case "s": + case "S": + pathSeg.x2 = coords[i + length - 4]; + pathSeg.y2 = coords[i + length - 3]; + case "t": + case "T": + case "l": + case "L": + case "m": + case "M": + pathSeg.x = coords[i + length - 2]; + pathSeg.y = coords[i + length - 1]; + break; + + case "q": + case "Q": + pathSeg.x1 = coords[i]; + pathSeg.y1 = coords[i + 1]; + pathSeg.x = coords[i + 2]; + pathSeg.y = coords[i + 3]; + break; + case "a": + case "A": + throw new Error("Cannot convert Arcs without SvgPath package"); + } + + pathSegList.push(pathSeg); + + // "If a moveto is followed by multiple pairs of coordinates, the subsequent pairs are treated as implicit + // lineto commands" + if (type === "m") { + type = "l"; + } else if (type === "M") { + type = "L"; + } + + i += length; + } while(i < coords.length); + } + + pathSegList.getItem = function (i) { + return this[i] + }; + pathSegList.numberOfItems = pathSegList.length; + + return pathSegList; + }; + + // returns an attribute of a node, either from the node directly or from css + var getAttribute = function (node, propertyNode, propertyCss) { + propertyCss = propertyCss || propertyNode; + return node.getAttribute(propertyNode) || node.style && node.style[propertyCss]; + }; + + /** + * @param {Element} node + * @param {string} tagsString + * @return {boolean} + */ + var nodeIs = function (node, tagsString) { + return tagsString.split(",").indexOf(node.tagName.toLowerCase()) >= 0; + }; + + var forEachChild = function (node, fn) { + // copy list of children, as the original might be modified + var children = []; + for (var i = 0; i < node.childNodes.length; i++) { + var childNode = node.childNodes[i]; + if (childNode.nodeName.charAt(0) !== "#") + children.push(childNode); + } + for (i = 0; i < children.length; i++) { + fn(i, children[i]); + } + }; + + var getAngle = function (from, to) { + return Math.atan2(to[1] - from[1], to[0] - from[0]); + }; + + function normalize(v) { + var length = Math.sqrt(v[0] * v[0] + v[1] * v[1]); + return [v[0] / length, v[1] / length]; + } + + function getDirectionVector(from, to) { + var v = [to[0] - from[0], to[1] - from[1]]; + return normalize(v); + } + + function addVectors(v1, v2) { + return [v1[0] + v2[0], v1[1] + v2[1]]; + } + + // mirrors p1 at p2 + var mirrorPoint = function (p1, p2) { + var dx = p2[0] - p1[0]; + var dy = p2[1] - p1[1]; + + return [p1[0] + 2 * dx, p1[1] + 2 * dy]; + }; + + // transforms a cubic bezier control point to a quadratic one: returns from + (2/3) * (to - from) + var toCubic = function (from, to) { + return [cToQ * (to[0] - from[0]) + from[0], cToQ * (to[1] - from[1]) + from[1]]; + }; + + // extracts a control point from a previous path segment (for t,T,s,S segments) + var getControlPointFromPrevious = function (i, from, list, prevX, prevY) { + var prev = list.getItem(i - 1); + var p2; + if (i > 0 && (prev.pathSegTypeAsLetter === "C" || prev.pathSegTypeAsLetter === "S")) { + p2 = mirrorPoint([prev.x2, prev.y2], from); + } else if (i > 0 && (prev.pathSegTypeAsLetter === "c" || prev.pathSegTypeAsLetter === "s")) { + p2 = mirrorPoint([prev.x2 + prevX, prev.y2 + prevY], from); + } else { + p2 = [from[0], from[1]]; + } + return p2; + }; + + /** + * @param {Element} rootSvg + * @constructor + * @property {Object.} renderedElements + * @property {Element} rootSvg + */ + function ReferencesHandler(rootSvg) { + this.renderedElements = {}; + this.rootSvg = rootSvg; + } + + /** + * @param {string} id + * @return {*} + */ + ReferencesHandler.prototype.getRendered = function (id) { + if (this.renderedElements.hasOwnProperty(id)) { + return this.renderedElements[id]; + } + + var node = this.rootSvg.querySelector("#" + cssEsc(id, {isIdentifier: true})); + + if (nodeIs(node, "lineargradient")) { + putGradient(node, "axial", [ + node.getAttribute("x1") || 0, + node.getAttribute("y1") || 0, + node.getAttribute("x2") || 1, + node.getAttribute("y2") || 0 + ]); + } else if (nodeIs(node, "radialgradient")) { + putGradient(node, "radial", [ + node.getAttribute("fx") || node.getAttribute("cx") || 0.5, + node.getAttribute("fy") || node.getAttribute("cy") || 0.5, + 0, + node.getAttribute("cx") || 0.5, + node.getAttribute("cy") || 0.5, + node.getAttribute("r") || 0.5 + ]); + } else if (nodeIs(node, "pattern")) { + pattern(node, this, AttributeState.default()) + } else if (nodeIs(node, "marker")) { + // the transformations directly at the node are written to the pdf form object transformation matrix + var tfMatrix = computeNodeTransform(node); + var bBox = getUntransformedBBox(node); + + _pdf.beginFormObject(bBox[0], bBox[1], bBox[2], bBox[3], tfMatrix); + renderChildren(node, _pdf.unitMatrix, this, false, false, AttributeState.default()); + _pdf.endFormObject(node.getAttribute("id")); + } else if (!nodeIs(node, "clippath")) { + // all other nodes will be rendered as PDF form object + renderNode(node, _pdf.unitMatrix, this, true, false, AttributeState.default()); + } + + this.renderedElements[id] = node; + return node; + }; + + var AttributeState = function () { + this.xmlSpace = null; + this.color = null; + this.fill = null; + this.fillOpacity = 1.0; + // this.fillRule = null; + this.fontFamily = null; + this.fontSize = 16; + this.fontStyle = null; + // this.fontVariant = null; + this.fontWeight = null; + this.opacity = 1.0; + this.stroke = null; + this.strokeDasharray = null; + this.strokeDashoffset = null; + this.strokeLinecap = null; + this.strokeLinejoin = null; + this.strokeMiterlimit = 4.0; + this.strokeOpacity = 1.0; + this.strokeWidth = 1.0; + // this.textAlign = null; + this.textAnchor = null; + this.visibility = null; + }; + + AttributeState.default = function () { + var attributeState = new AttributeState(); + + attributeState.xmlSpace = "default"; + attributeState.fill = new RGBColor("rgb(0, 0, 0)"); + attributeState.fillOpacity = 1.0; + // attributeState.fillRule = "nonzero"; + attributeState.fontFamily = "times"; + attributeState.fontSize = 16; + attributeState.fontStyle = "normal"; + // attributeState.fontVariant = "normal"; + attributeState.fontWeight = "normal"; + attributeState.opacity = 1.0; + attributeState.stroke = null; + attributeState.strokeDasharray = null; + attributeState.strokeDashoffset = null; + attributeState.strokeLinecap = "butt"; + attributeState.strokeLinejoin = "miter"; + attributeState.strokeMiterlimit = 4.0; + attributeState.strokeOpacity = 1.0; + attributeState.strokeWidth = 1.0; + // attributeState.textAlign = "start"; + attributeState.textAnchor = "start"; + attributeState.visibility = "visible"; + + return attributeState; + }; + + AttributeState.prototype.clone = function () { + var clone = new AttributeState(); + + clone.xmlSpace = this.xmlSpace; + clone.fill = this.fill; + clone.fillOpacity = this.fillOpacity; + // clone.fillRule = this.fillRule; + clone.fontFamily = this.fontFamily; + clone.fontSize = this.fontSize; + clone.fontStyle = this.fontStyle; + // clone.fontVariant = this.fontVariant; + clone.fontWeight = this.fontWeight; + clone.opacity = this.opacity; + clone.stroke = this.stroke; + clone.strokeDasharray = this.strokeDasharray; + clone.strokeDashoffset = this.strokeDashoffset; + clone.strokeLinecap = this.strokeLinecap; + clone.strokeLinejoin = this.strokeLinejoin; + clone.strokeMiterlimit = this.strokeMiterlimit; + clone.strokeOpacity = this.strokeOpacity; + clone.strokeWidth = this.strokeWidth; + // clone.textAlign = this.textAlign; + clone.textAnchor = this.textAnchor; + clone.visibility = this.visibility; + + return clone; + }; + + /** + * @constructor + * @property {Marker[]} markers + */ + function MarkerList() { + this.markers = []; + } + + /** + * @param {Marker} marker + */ + MarkerList.prototype.addMarker = function addMarker(marker) { + this.markers.push(marker); + }; + + MarkerList.prototype.draw = function (tfMatrix, refsHandler, attributeState) { + for (var i = 0; i < this.markers.length; i++) { + var marker = this.markers[i]; + + var tf; + var angle = marker.angle, anchor = marker.anchor; + var cos = Math.cos(angle); + var sin = Math.sin(angle); + // position at and rotate around anchor + tf = new _pdf.Matrix(cos, sin, -sin, cos, anchor[0], anchor[1]); + // scale with stroke-width + tf = _pdf.matrixMult(new _pdf.Matrix(attributeState.strokeWidth, 0, 0, attributeState.strokeWidth, 0, 0), tf); + + tf = _pdf.matrixMult(tf, tfMatrix); + + // as the marker is already scaled by the current line width we must not apply the line width twice! + _pdf.saveGraphicsState(); + _pdf.setLineWidth(1.0); + refsHandler.getRendered(marker.id); + _pdf.doFormObject(marker.id, tf); + _pdf.restoreGraphicsState(); + } + }; + + /** + * @param {string} id + * @param {[number,number]} anchor + * @param {number} angle + */ + function Marker(id, anchor, angle) { + this.id = id; + this.anchor = anchor; + this.angle = angle; + } + + function removeNewlines(str) { + return str.replace(/[\n\r]/g, ""); + } + + function replaceTabsBySpace(str) { + return str.replace(/[\t]/g, " "); + } + + function consolidateSpaces(str) { + return str.replace(/ +/g, " "); + } + + function trimLeft(str) { + return str.replace(/^\s+/,""); + } + + function trimRight(str) { + return str.replace(/\s+$/,""); + } + + function computeViewBoxTransform(node, viewBox, eX, eY, eWidth, eHeight) { + var vbX = viewBox[0]; + var vbY = viewBox[1]; + var vbWidth = viewBox[2]; + var vbHeight = viewBox[3]; + + var scaleX = eWidth / vbWidth; + var scaleY = eHeight / vbHeight; + + var align, meetOrSlice; + var preserveAspectRatio = node.getAttribute("preserveAspectRatio"); + if (preserveAspectRatio) { + var alignAndMeetOrSlice = preserveAspectRatio.split(" "); + if (alignAndMeetOrSlice[0] === "defer") { + alignAndMeetOrSlice = alignAndMeetOrSlice.slice(1); + } + + align = alignAndMeetOrSlice[0]; + meetOrSlice = alignAndMeetOrSlice[1] || "meet"; + } else { + align = "xMidYMid"; + meetOrSlice = "meet" + } + + if (align !== "none") { + if (meetOrSlice === "meet") { + // uniform scaling with min scale + scaleX = scaleY = Math.min(scaleX, scaleY); + } else if (meetOrSlice === "slice") { + // uniform scaling with max scale + scaleX = scaleY = Math.max(scaleX, scaleY); + } + } + + var translateX = eX - (vbX * scaleX); + var translateY = eY - (vbY * scaleY); + + if (align.indexOf("xMid") >= 0) { + translateX += (eWidth - vbWidth * scaleX) / 2; + } else if (align.indexOf("xMax") >= 0) { + translateX += eWidth - vbWidth * scaleX; + } + + if (align.indexOf("yMid") >= 0) { + translateY += (eHeight - vbHeight * scaleY) / 2; + } else if (align.indexOf("yMax") >= 0) { + translateY += (eHeight - vbHeight * scaleY); + } + + var translate = new _pdf.Matrix(1, 0, 0, 1, translateX, translateY); + var scale = new _pdf.Matrix(scaleX, 0, 0, scaleY, 0, 0); + + return _pdf.matrixMult(scale, translate); + } + + // computes the transform directly applied at the node (such as viewbox scaling and the "transform" atrribute) + // x,y,cx,cy,r,... are omitted + var computeNodeTransform = function (node) { + var viewBox, x, y; + var nodeTransform = _pdf.unitMatrix; + if (nodeIs(node, "svg,g")) { + x = parseFloat(node.getAttribute("x")) || 0; + y = parseFloat(node.getAttribute("y")) || 0; + + viewBox = node.getAttribute("viewBox"); + if (viewBox) { + var box = parseFloats(viewBox); + var width = parseFloat(node.getAttribute("width")) || box[2]; + var height = parseFloat(node.getAttribute("height")) || box[3]; + nodeTransform = computeViewBoxTransform(node, box, x, y, width, height) + } else { + nodeTransform = new _pdf.Matrix(1, 0, 0, 1, x, y); + } + } else if (nodeIs(node, "marker")) { + x = parseFloat(node.getAttribute("refX")) || 0; + y = parseFloat(node.getAttribute("refY")) || 0; + + viewBox = node.getAttribute("viewBox"); + if (viewBox) { + var bounds = parseFloats(viewBox); + bounds[0] = bounds[1] = 0; // for some reason vbX anc vbY seem to be ignored for markers + nodeTransform = computeViewBoxTransform(node, + bounds, + 0, + 0, + parseFloat(node.getAttribute("markerWidth")) || 3, + parseFloat(node.getAttribute("markerHeight")) || 3 + ); + nodeTransform = _pdf.matrixMult(new _pdf.Matrix(1, 0, 0, 1, -x, -y), nodeTransform); + } else { + nodeTransform = new _pdf.Matrix(1, 0, 0, 1, -x, -y); + } + } + + var transformString = node.getAttribute("transform"); + if (!transformString) + return nodeTransform; + else + return _pdf.matrixMult(nodeTransform, parseTransform(transformString)); + }; + + // parses the "points" string used by polygons and returns an array of points + var parsePointsString = function (string) { + var floats = parseFloats(string); + var result = []; + for (var i = 0; i < floats.length - 1; i += 2) { + var x = floats[i]; + var y = floats[i + 1]; + result.push([x, y]); + } + return result; + }; + + // parses the "transform" string + var parseTransform = function (transformString) { + if (!transformString) + return _pdf.unitMatrix; + + var mRegex = /^\s*matrix\(([^\)]+)\)\s*/, + tRegex = /^\s*translate\(([^\)]+)\)\s*/, + rRegex = /^\s*rotate\(([^\)]+)\)\s*/, + sRegex = /^\s*scale\(([^\)]+)\)\s*/, + sXRegex = /^\s*skewX\(([^\)]+)\)\s*/, + sYRegex = /^\s*skewY\(([^\)]+)\)\s*/; + + var resultMatrix = _pdf.unitMatrix, m; + + while (transformString.length > 0) { + var match = mRegex.exec(transformString); + if (match) { + m = parseFloats(match[1]); + resultMatrix = _pdf.matrixMult(new _pdf.Matrix(m[0], m[1], m[2], m[3], m[4], m[5]), resultMatrix); + transformString = transformString.substr(match[0].length); + } + match = rRegex.exec(transformString); + if (match) { + m = parseFloats(match[1]); + var a = Math.PI * m[0] / 180; + resultMatrix = _pdf.matrixMult(new _pdf.Matrix(Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0), resultMatrix); + if (m[1] && m[2]) { + var t1 = new _pdf.Matrix(1, 0, 0, 1, m[1], m[2]); + var t2 = new _pdf.Matrix(1, 0, 0, 1, -m[1], -m[2]); + resultMatrix = _pdf.matrixMult(t2, _pdf.matrixMult(resultMatrix, t1)); + } + transformString = transformString.substr(match[0].length); + } + match = tRegex.exec(transformString); + if (match) { + m = parseFloats(match[1]); + resultMatrix = _pdf.matrixMult(new _pdf.Matrix(1, 0, 0, 1, m[0], m[1] || 0), resultMatrix); + transformString = transformString.substr(match[0].length); + } + match = sRegex.exec(transformString); + if (match) { + m = parseFloats(match[1]); + if (!m[1]) + m[1] = m[0]; + resultMatrix = _pdf.matrixMult(new _pdf.Matrix(m[0], 0, 0, m[1], 0, 0), resultMatrix); + transformString = transformString.substr(match[0].length); + } + match = sXRegex.exec(transformString); + if (match) { + m = parseFloat(match[1]); + resultMatrix = _pdf.matrixMult(new _pdf.Matrix(1, 0, Math.tan(m), 1, 0, 0), resultMatrix); + transformString = transformString.substr(match[0].length); + } + match = sYRegex.exec(transformString); + if (match) { + m = parseFloat(match[1]); + resultMatrix = _pdf.matrixMult(new _pdf.Matrix(1, Math.tan(m), 0, 1, 0, 0), resultMatrix); + transformString = transformString.substr(match[0].length); + } + } + return resultMatrix; + }; + + // parses a comma, sign and/or whitespace separated string of floats and returns the single floats in an array + var parseFloats = function (str) { + var floats = [], match, + regex = /[+-]?(?:(?:\d+\.?\d*)|(?:\d*\.?\d+))(?:[eE][+-]?\d+)?/g; + while(match = regex.exec(str)) { + floats.push(parseFloat(match[0])); + } + return floats; + }; + + // extends RGBColor by rgba colors as RGBColor is not capable of it + var parseColor = function (colorString) { + if (colorString === "transparent") { + var transparent = new RGBColor("rgb(0,0,0)"); + transparent.a = 0; + return transparent + } + + var match = /\s*rgba\(((?:[^,\)]*,){3}[^,\)]*)\)\s*/.exec(colorString); + if (match) { + var floats = parseFloats(match[1]); + var color = new RGBColor("rgb(" + floats.slice(0,3).join(",") + ")"); + color.a = floats[3]; + return color; + } else { + return new RGBColor(colorString); + } + }; + + // multiplies a vector with a matrix: vec' = vec * matrix + var multVecMatrix = function (vec, matrix) { + var x = vec[0]; + var y = vec[1]; + return [ + matrix.a * x + matrix.c * y + matrix.e, + matrix.b * x + matrix.d * y + matrix.f + ]; + }; + + // returns the untransformed bounding box [x, y, width, height] of an svg element (quite expensive for path and polygon objects, as + // the whole points/d-string has to be processed) + var getUntransformedBBox = function (node) { + if (getAttribute(node, "display") === "none") { + return [0, 0, 0, 0]; + } + + var i, minX, minY, maxX, maxY, viewBox, vb, boundingBox; + var pf = parseFloat; + + if (nodeIs(node, "polygon,polyline")) { + var points = parsePointsString(node.getAttribute("points")); + minX = Number.POSITIVE_INFINITY; + minY = Number.POSITIVE_INFINITY; + maxX = Number.NEGATIVE_INFINITY; + maxY = Number.NEGATIVE_INFINITY; + for (i = 0; i < points.length; i++) { + var point = points[i]; + minX = Math.min(minX, point[0]); + maxX = Math.max(maxX, point[0]); + minY = Math.min(minY, point[1]); + maxY = Math.max(maxY, point[1]); + } + boundingBox = [ + minX, + minY, + maxX - minX, + maxY - minY + ]; + } else if (nodeIs(node, "path")) { + var list = getPathSegList(node); + minX = Number.POSITIVE_INFINITY; + minY = Number.POSITIVE_INFINITY; + maxX = Number.NEGATIVE_INFINITY; + maxY = Number.NEGATIVE_INFINITY; + var x = 0, y = 0; + var prevX, prevY, newX, newY; + var p2, p3, to; + for (i = 0; i < list.numberOfItems; i++) { + var seg = list.getItem(i); + var cmd = seg.pathSegTypeAsLetter; + switch (cmd) { + case "H": + newX = seg.x; + newY = y; + break; + case "h": + newX = seg.x + x; + newY = y; + break; + case "V": + newX = x; + newY = seg.y; + break; + case "v": + newX = x; + newY = seg.y + y; + break; + case "C": + p2 = [seg.x1, seg.y1]; + p3 = [seg.x2, seg.y2]; + to = [seg.x, seg.y]; + break; + case "c": + p2 = [seg.x1 + x, seg.y1 + y]; + p3 = [seg.x2 + x, seg.y2 + y]; + to = [seg.x + x, seg.y + y]; + break; + case "S": + p2 = getControlPointFromPrevious(i, [x, y], list, prevX, prevY); + p3 = [seg.x2, seg.y2]; + to = [seg.x, seg.y]; + break; + case "s": + p2 = getControlPointFromPrevious(i, [x, y], list, prevX, prevY); + p3 = [seg.x2 + x, seg.y2 + y]; + to = [seg.x + x, seg.y + y]; + break; + case "Q": + pf = [seg.x1, seg.y1]; + p2 = toCubic([x, y], pf); + p3 = toCubic([seg.x, seg.y], pf); + to = [seg.x, seg.y]; + break; + case "q": + pf = [seg.x1 + x, seg.y1 + y]; + p2 = toCubic([x, y], pf); + p3 = toCubic([x + seg.x, y + seg.y], pf); + to = [seg.x + x, seg.y + y]; + break; + case "T": + p2 = getControlPointFromPrevious(i, [x, y], list, prevX, prevY); + p2 = toCubic([x, y], pf); + p3 = toCubic([seg.x, seg.y], pf); + to = [seg.x, seg.y]; + break; + case "t": + pf = getControlPointFromPrevious(i, [x, y], list, prevX, prevY); + p2 = toCubic([x, y], pf); + p3 = toCubic([x + seg.x, y + seg.y], pf); + to = [seg.x + x, seg.y + y]; + break; + // TODO: A,a + } + if ("sScCqQtT".indexOf(cmd) >= 0) { + prevX = x; + prevY = y; + } + if ("MLCSQT".indexOf(cmd) >= 0) { + x = seg.x; + y = seg.y; + } else if ("mlcsqt".indexOf(cmd) >= 0) { + x = seg.x + x; + y = seg.y + y; + } else if ("zZ".indexOf(cmd) < 0) { + x = newX; + y = newY; + } + if ("CSQTcsqt".indexOf(cmd) >= 0) { + minX = Math.min(minX, x, p2[0], p3[0], to[0]); + maxX = Math.max(maxX, x, p2[0], p3[0], to[0]); + minY = Math.min(minY, y, p2[1], p3[1], to[1]); + maxY = Math.max(maxY, y, p2[1], p3[1], to[1]); + } else { + minX = Math.min(minX, x); + maxX = Math.max(maxX, x); + minY = Math.min(minY, y); + maxY = Math.max(maxY, y); + } + } + boundingBox = [ + minX, + minY, + maxX - minX, + maxY - minY + ]; + } else if (nodeIs(node, "svg")) { + viewBox = node.getAttribute("viewBox"); + if (viewBox) { + vb = parseFloats(viewBox); + } + return [ + pf(node.getAttribute("x")) || (vb && vb[0]) || 0, + pf(node.getAttribute("y")) || (vb && vb[1]) || 0, + pf(node.getAttribute("width")) || (vb && vb[2]) || 0, + pf(node.getAttribute("height")) || (vb && vb[3]) || 0 + ]; + } else if (nodeIs(node, "g,clippath")) { + boundingBox = [0, 0, 0, 0]; + forEachChild(node, function (i, node) { + var nodeBox = getUntransformedBBox(node); + boundingBox = [ + Math.min(boundingBox[0], nodeBox[0]), + Math.min(boundingBox[1], nodeBox[1]), + Math.max(boundingBox[0] + boundingBox[2], nodeBox[0] + nodeBox[2]) - Math.min(boundingBox[0], nodeBox[0]), + Math.max(boundingBox[1] + boundingBox[3], nodeBox[1] + nodeBox[3]) - Math.min(boundingBox[1], nodeBox[1]) + ]; + }); + } else if (nodeIs(node, "marker")) { + viewBox = node.getAttribute("viewBox"); + if (viewBox) { + vb = parseFloats(viewBox); + } + return [ + (vb && vb[0]) || 0, + (vb && vb[1]) || 0, + (vb && vb[2]) || pf(node.getAttribute("marker-width")) || 0, + (vb && vb[3]) || pf(node.getAttribute("marker-height")) || 0 + ]; + } else if (nodeIs(node, "pattern")) { + return [ + pf(node.getAttribute("x")) || 0, + pf(node.getAttribute("y")) || 0, + pf(node.getAttribute("width")) || 0, + pf(node.getAttribute("height")) || 0 + ] + } else { + // TODO: check if there are other possible coordinate attributes + var x1 = pf(node.getAttribute("x1")) || pf(node.getAttribute("x")) || pf((node.getAttribute("cx")) - pf(node.getAttribute("r"))) || 0; + var x2 = pf(node.getAttribute("x2")) || (x1 + pf(node.getAttribute("width"))) || (pf(node.getAttribute("cx")) + pf(node.getAttribute("r"))) || 0; + var y1 = pf(node.getAttribute("y1")) || pf(node.getAttribute("y")) || (pf(node.getAttribute("cy")) - pf(node.getAttribute("r"))) || 0; + var y2 = pf(node.getAttribute("y2")) || (y1 + pf(node.getAttribute("height"))) || (pf(node.getAttribute("cy")) + pf(node.getAttribute("r"))) || 0; + boundingBox = [ + Math.min(x1, x2), + Math.min(y1, y2), + Math.max(x1, x2) - Math.min(x1, x2), + Math.max(y1, y2) - Math.min(y1, y2) + ]; + } + + if (!nodeIs(node, "marker,svg,g")) { + // add line-width + var lineWidth = getAttribute(node, "stroke-width") || 1; + var miterLimit = getAttribute(node, "stroke-miterlimit"); + // miterLength / lineWidth = 1 / sin(phi / 2) + miterLimit && (lineWidth *= 0.5 / (Math.sin(Math.PI / 12))); + return [ + boundingBox[0] - lineWidth, + boundingBox[1] - lineWidth, + boundingBox[2] + 2 * lineWidth, + boundingBox[3] + 2 * lineWidth + ]; + } + + return boundingBox; + }; + + // transforms a bounding box and returns a new rect that contains it + var transformBBox = function (box, matrix) { + var bl = multVecMatrix([box[0], box[1]], matrix); + var br = multVecMatrix([box[0] + box[2], box[1]], matrix); + var tl = multVecMatrix([box[0], box[1] + box[3]], matrix); + var tr = multVecMatrix([box[0] + box[2], box[1] + box[3]], matrix); + + var bottom = Math.min(bl[1], br[1], tl[1], tr[1]); + var left = Math.min(bl[0], br[0], tl[0], tr[0]); + var top = Math.max(bl[1], br[1], tl[1], tr[1]); + var right = Math.max(bl[0], br[0], tl[0], tr[0]); + + return [ + left, + bottom, + right - left, + top - bottom + ] + }; + + // draws a polygon + var polygon = function (node, refsHandler, attributeState, closed) { + if (!node.hasAttribute("points") || node.getAttribute("points") === "") { + return; + } + + var points = parsePointsString(node.getAttribute("points")); + var lines = [{op: "m", c: points[0]}]; + var i, angle; + for (i = 1; i < points.length; i++) { + lines.push({op: "l", c: points[i]}); + } + + if (closed) { + lines.push({op: "h"}); + } + + _pdf.path(lines); + + var markerEnd = node.getAttribute("marker-end"), + markerStart = node.getAttribute("marker-start"), + markerMid = node.getAttribute("marker-mid"); + + if (markerStart || markerMid || markerEnd) { + var length = lines.length; + var markers = new MarkerList(); + if (markerStart) { + markerStart = iriReference.exec(markerStart)[1]; + angle = addVectors(getDirectionVector(lines[0].c, lines[1].c), getDirectionVector(lines[length - 2].c, lines[0].c)); + markers.addMarker(new Marker(markerStart, lines[0].c, Math.atan2(angle[1], angle[0]))); + } + + if (markerMid) { + markerMid = iriReference.exec(markerMid)[1]; + var prevAngle = getDirectionVector(lines[0].c, lines[1].c), curAngle; + for (i = 1; i < lines.length - 2; i++) { + curAngle = getDirectionVector(lines[i].c, lines[i + 1].c); + angle = addVectors(prevAngle, curAngle); + markers.addMarker(new Marker(markerMid, lines[i].c, Math.atan2(angle[1], angle[0]))); + prevAngle = curAngle; + } + + curAngle = getDirectionVector(lines[length - 2].c, lines[0].c); + angle = addVectors(prevAngle, curAngle); + markers.addMarker(new Marker(markerMid, lines[length - 2].c, Math.atan2(angle[1], angle[0]))); + } + + if (markerEnd) { + markerEnd = iriReference.exec(markerEnd)[1]; + angle = addVectors(getDirectionVector(lines[0].c, lines[1].c), getDirectionVector(lines[length - 2].c, lines[0].c)); + markers.addMarker(new Marker(markerEnd, lines[0].c, Math.atan2(angle[1], angle[0]))); + } + + markers.draw(_pdf.unitMatrix, refsHandler, attributeState); + } + }; + + // draws an image + var image = function (node) { + var width = parseFloat(node.getAttribute("width")), + height = parseFloat(node.getAttribute("height")), + x = parseFloat(node.getAttribute("x") || 0), + y = parseFloat(node.getAttribute("y") || 0); + + + var imageUrl = node.getAttribute("xlink:href") || node.getAttribute("href"); + + var dataUrl = imageUrl.match(dataUrlRegex); + if (dataUrl && dataUrl[2] === "image/svg+xml") { + var svgText = dataUrl[5]; + if (dataUrl[4] === "base64") { + svgText = atob(svgText); + } else { + svgText = decodeURIComponent(svgText); + } + + var parser = new DOMParser(); + var svgElement = parser.parseFromString(svgText, "image/svg+xml").firstElementChild; + + // unless preserveAspectRatio starts with "defer", the preserveAspectRatio attribute of the svg is ignored + var preserveAspectRatio = node.getAttribute("preserveAspectRatio"); + if (!preserveAspectRatio + || preserveAspectRatio.indexOf("defer") < 0 + || !svgElement.getAttribute("preserveAspectRatio")) { + svgElement.setAttribute("preserveAspectRatio", preserveAspectRatio); + } + + svgElement.setAttribute("x", String(x)); + svgElement.setAttribute("y", String(y)); + svgElement.setAttribute("width", String(width)); + svgElement.setAttribute("height", String(height)); + + renderNode(svgElement, _pdf.unitMatrix, {}, false, false, AttributeState.default()); + return; + } + + try { + _pdf.addImage( + imageUrl, + "", // will be ignored anyways if imageUrl is a data url + x, + y, + width, + height + ); + } catch (e) { + (typeof console === "object" + && console.warn + && console.warn('svg2pdfjs: Images with external resource link are not supported! ("' + imageUrl + '")')); + } + }; + + // draws a path + var path = function (node, tfMatrix, refsHandler, withinClipPath, attributeState) { + var list = getPathSegList(node); + var markerEnd = node.getAttribute("marker-end"), + markerStart = node.getAttribute("marker-start"), + markerMid = node.getAttribute("marker-mid"); + + markerEnd && (markerEnd = iriReference.exec(markerEnd)[1]); + markerStart && (markerStart = iriReference.exec(markerStart)[1]); + markerMid && (markerMid = iriReference.exec(markerMid)[1]); + + var getLinesFromPath = function () { + var x = 0, y = 0; + var x0 = x, y0 = y; + var prevX, prevY, newX, newY; + var to, p, p2, p3; + var lines = []; + var markers = new MarkerList(); + var op; + var prevAngle = [0, 0], curAngle; + + for (var i = 0; i < list.numberOfItems; i++) { + var seg = list.getItem(i); + var cmd = seg.pathSegTypeAsLetter; + switch (cmd) { + case "M": + x0 = x; + y0 = y; + to = [seg.x, seg.y]; + op = "m"; + break; + case "m": + x0 = x; + y0 = y; + to = [seg.x + x, seg.y + y]; + op = "m"; + break; + case "L": + to = [seg.x, seg.y]; + op = "l"; + break; + case "l": + to = [seg.x + x, seg.y + y]; + op = "l"; + break; + case "H": + to = [seg.x, y]; + op = "l"; + newX = seg.x; + newY = y; + break; + case "h": + to = [seg.x + x, y]; + op = "l"; + newX = seg.x + x; + newY = y; + break; + case "V": + to = [x, seg.y]; + op = "l"; + newX = x; + newY = seg.y; + break; + case "v": + to = [x, seg.y + y]; + op = "l"; + newX = x; + newY = seg.y + y; + break; + case "C": + p2 = [seg.x1, seg.y1]; + p3 = [seg.x2, seg.y2]; + to = [seg.x, seg.y]; + break; + case "c": + p2 = [seg.x1 + x, seg.y1 + y]; + p3 = [seg.x2 + x, seg.y2 + y]; + to = [seg.x + x, seg.y + y]; + break; + case "S": + p2 = getControlPointFromPrevious(i, [x, y], list, prevX, prevY); + p3 = [seg.x2, seg.y2]; + to = [seg.x, seg.y]; + break; + case "s": + p2 = getControlPointFromPrevious(i, [x, y], list, prevX, prevY); + p3 = [seg.x2 + x, seg.y2 + y]; + to = [seg.x + x, seg.y + y]; + break; + case "Q": + p = [seg.x1, seg.y1]; + p2 = toCubic([x, y], p); + p3 = toCubic([seg.x, seg.y], p); + to = [seg.x, seg.y]; + break; + case "q": + p = [seg.x1 + x, seg.y1 + y]; + p2 = toCubic([x, y], p); + p3 = toCubic([x + seg.x, y + seg.y], p); + to = [seg.x + x, seg.y + y]; + break; + case "T": + p = getControlPointFromPrevious(i, [x, y], list, prevX, prevY); + p2 = toCubic([x, y], p); + p3 = toCubic([seg.x, seg.y], p); + to = [seg.x, seg.y]; + break; + case "t": + p = getControlPointFromPrevious(i, [x, y], list, prevX, prevY); + p2 = toCubic([x, y], p); + p3 = toCubic([x + seg.x, y + seg.y], p); + to = [seg.x + x, seg.y + y]; + break; + // TODO: A,a + case "Z": + case "z": + x = x0; + y = y0; + lines.push({op: "h"}); + break; + } + + var hasStartMarker = markerStart + && (i === 1 + || ("mM".indexOf(cmd) < 0 && "mM".indexOf(list.getItem(i - 1).pathSegTypeAsLetter) >= 0)); + var hasEndMarker = markerEnd + && (i === list.numberOfItems - 1 + || ("mM".indexOf(cmd) < 0 && "mM".indexOf(list.getItem(i + 1).pathSegTypeAsLetter) >= 0)); + var hasMidMarker = markerMid + && i > 0 + && !(i === 1 && "mM".indexOf(list.getItem(i - 1).pathSegTypeAsLetter) >= 0); + + if ("sScCqQtT".indexOf(cmd) >= 0) { + hasStartMarker && markers.addMarker(new Marker(markerStart, [x, y], getAngle([x, y], p2))); + hasEndMarker && markers.addMarker(new Marker(markerEnd, to, getAngle(p3, to))); + if (hasMidMarker) { + curAngle = getDirectionVector([x, y], p2); + curAngle = "mM".indexOf(list.getItem(i - 1).pathSegTypeAsLetter) >= 0 ? + curAngle : normalize(addVectors(prevAngle, curAngle)); + markers.addMarker(new Marker(markerMid, [x, y], Math.atan2(curAngle[1], curAngle[0]))); + } + + prevAngle = getDirectionVector(p3, to); + + prevX = x; + prevY = y; + + if (withinClipPath) { + p2 = multVecMatrix(p2, tfMatrix); + p3 = multVecMatrix(p3, tfMatrix); + to = multVecMatrix(to, tfMatrix); + } + + lines.push({ + op: "c", c: [ + p2[0], p2[1], + p3[0], p3[1], + to[0], to[1] + ] + }); + } else if ("lLhHvVmM".indexOf(cmd) >= 0) { + curAngle = getDirectionVector([x, y], to); + hasStartMarker && markers.addMarker(new Marker(markerStart, [x, y], Math.atan2(curAngle[1], curAngle[0]))); + hasEndMarker && markers.addMarker(new Marker(markerEnd, to, Math.atan2(curAngle[1], curAngle[0]))); + if (hasMidMarker) { + var angle = "mM".indexOf(cmd) >= 0 ? + prevAngle : "mM".indexOf(list.getItem(i - 1).pathSegTypeAsLetter) >= 0 ? + curAngle : normalize(addVectors(prevAngle, curAngle)); + markers.addMarker(new Marker(markerMid, [x, y], Math.atan2(angle[1], angle[0]))); + } + prevAngle = curAngle; + + if (withinClipPath) { + to = multVecMatrix(to, tfMatrix); + } + + lines.push({op: op, c: to}); + } + + if ("MLCSQT".indexOf(cmd) >= 0) { + x = seg.x; + y = seg.y; + } else if ("mlcsqt".indexOf(cmd) >= 0) { + x = seg.x + x; + y = seg.y + y; + } else if ("zZ".indexOf(cmd) < 0) { + x = newX; + y = newY; + } + } + + return {lines: lines, markers: markers}; + }; + var lines = getLinesFromPath(); + + if (lines.lines.length > 0) { + _pdf.path(lines.lines); + } + + if (markerEnd || markerStart || markerMid) { + lines.markers.draw(_pdf.unitMatrix, refsHandler, attributeState); + } + }; + + // draws the element referenced by a use node, makes use of pdf's XObjects/FormObjects so nodes are only written once + // to the pdf document. This highly reduces the file size and computation time. + var use = function (node, tfMatrix, refsHandler) { + var url = (node.getAttribute("href") || node.getAttribute("xlink:href")); + // just in case someone has the idea to use empty use-tags, wtf??? + if (!url) + return; + + // get the size of the referenced form object (to apply the correct scaling) + var id = url.substring(1); + refsHandler.getRendered(id); + var formObject = _pdf.getFormObject(id); + + // scale and position it right + var x = node.getAttribute("x") || 0; + var y = node.getAttribute("y") || 0; + var width = node.getAttribute("width") || formObject.width; + var height = node.getAttribute("height") || formObject.height; + var t = new _pdf.Matrix(width / formObject.width || 0, 0, 0, height / formObject.height || 0, x, y); + t = _pdf.matrixMult(t, tfMatrix); + _pdf.doFormObject(id, t); + }; + + // draws a line + var line = function (node, refsHandler, attributeState) { + var p1 = [parseFloat(node.getAttribute('x1') || 0), parseFloat(node.getAttribute('y1') || 0)]; + var p2 = [parseFloat(node.getAttribute('x2') || 0), parseFloat(node.getAttribute('y2') || 0)]; + + if (attributeState.stroke !== null){ + _pdf.line(p1[0], p1[1], p2[0], p2[1]); + } + + var markerStart = node.getAttribute("marker-start"), + markerEnd = node.getAttribute("marker-end"); + + if (markerStart || markerEnd) { + var markers = new MarkerList(); + var angle = getAngle(p1, p2); + if (markerStart) { + markers.addMarker(new Marker(iriReference.exec(markerStart)[1], p1, angle)); + } + if (markerEnd) { + markers.addMarker(new Marker(iriReference.exec(markerEnd)[1], p2, angle)); + } + markers.draw(_pdf.unitMatrix, refsHandler, attributeState); + } + }; + + // draws a rect + var rect = function (node) { + _pdf.roundedRect( + parseFloat(node.getAttribute('x')) || 0, + parseFloat(node.getAttribute('y')) || 0, + parseFloat(node.getAttribute('width')), + parseFloat(node.getAttribute('height')), + parseFloat(node.getAttribute('rx')) || 0, + parseFloat(node.getAttribute('ry')) || 0 + ); + }; + + // draws an ellipse + var ellipse = function (node) { + _pdf.ellipse( + parseFloat(node.getAttribute('cx')) || 0, + parseFloat(node.getAttribute('cy')) || 0, + parseFloat(node.getAttribute('rx')), + parseFloat(node.getAttribute('ry')) + ); + }; + + // draws a circle + var circle = function (node) { + var radius = parseFloat(node.getAttribute('r')) || 0; + _pdf.ellipse( + parseFloat(node.getAttribute('cx')) || 0, + parseFloat(node.getAttribute('cy')) || 0, + radius, + radius + ); + }; + + // applies text transformations to a text node + var transformText = function (node, text) { + var textTransform = getAttribute(node, "text-transform"); + switch (textTransform) { + case "uppercase": return text.toUpperCase(); + case "lowercase": return text.toLowerCase(); + default: return text; + // TODO: capitalize, full-width + } + }; + + /** + * Canvas text measuring is a lot faster than svg measuring. However, it is inaccurate for some fonts. So test each + * font once and decide if canvas is accurate enough. + * @param {string} text + * @param {string} fontFamily + * @returns {function(string, string, string, string, string)} + */ + var getMeasureFunction = (function getMeasureFunction() { + /** + * @param {string} text + * @param {string} fontFamily + * @param {string} fontSize + * @param {string} fontStyle + * @param {string} fontWeight + */ + function canvasTextMeasure(text, fontFamily, fontSize, fontStyle, fontWeight) { + var canvas = document.createElement("canvas"); + var context = canvas.getContext("2d"); + + context.font = [fontStyle, fontWeight, fontSize, fontFamily].join(" "); + return context.measureText(text).width; + } + + /** + * @param {string} text + * @param {string} fontFamily + * @param {string} fontSize + * @param {string} fontStyle + * @param {string} fontWeight + */ + function svgTextMeasure(text, fontFamily, fontSize, fontStyle, fontWeight) { + var textNode = document.createElementNS(svgNamespaceURI, "text"); + textNode.setAttribute("font-family", fontFamily); + textNode.setAttribute("font-size", fontSize); + textNode.setAttribute("font-style", fontStyle); + textNode.setAttribute("font-weight", fontWeight); + textNode.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:space", "preserve"); + textNode.appendChild(document.createTextNode(text)); + + var svg = document.createElementNS(svgNamespaceURI, "svg"); + svg.appendChild(textNode); + svg.setAttribute("visibility", "hidden"); + document.body.appendChild(svg); + + var width = textNode.getBBox().width; + + document.body.removeChild(svg); + + return width; + } + + var testString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789!\"$%&/()=?'\\+*-_.:,;^}][{#~|<>"; + var epsilon = 0.1; + var measureMethods = {}; + + return function getMeasureFunction(fontFamily) { + var method = measureMethods[fontFamily]; + if (!method) { + var fontSize = "16px"; + var fontStyle = "normal"; + var fontWeight = "normal"; + var canvasWidth = canvasTextMeasure(testString, fontFamily, fontSize, fontStyle, fontWeight); + var svgWidth = svgTextMeasure(testString, fontFamily, fontSize, fontStyle, fontWeight); + + method = Math.abs(canvasWidth - svgWidth) < epsilon ? canvasTextMeasure : svgTextMeasure; + + measureMethods[fontFamily] = method; + } + + return method; + } + })(); + + /** + * @param {string} text + * @param {AttributeState} attributeState + * @returns {number} + */ + function measureTextWidth(text, attributeState) { + if (text.length === 0) { + return 0; + } + + var fontFamily = attributeState.fontFamily; + var measure = getMeasureFunction(fontFamily); + + return measure(text, attributeState.fontFamily, attributeState.fontSize + "px", attributeState.fontStyle, attributeState.fontWeight); + } + + /** + * @param {string} text + * @param {AttributeState} attributeState + * @returns {number} + */ + function getTextOffset(text, attributeState) { + var textAnchor = attributeState.textAnchor; + if (textAnchor === "start") { + return 0; + } + + var width = measureTextWidth(text, attributeState); + + var xOffset = 0; + switch (textAnchor) { + case "end": + xOffset = width; + break; + case "middle": + xOffset = width / 2; + break; + } + + return xOffset; + } + + /** + * @param {string} textAnchor + * @param {number} originX + * @param {number} originY + * @constructor + */ + function TextChunk(textAnchor, originX, originY) { + this.texts = []; + this.textNodes = []; + this.textAnchor = textAnchor; + this.originX = originX; + this.originY = originY; + } + + /** + * @param {SVGElement} tSpan + * @param {string} text + */ + TextChunk.prototype.add = function(tSpan, text) { + this.texts.push(text); + this.textNodes.push(tSpan); + }; + /** + * Outputs the chunk to pdf. + * @param {jsPDF.Matrix} transform + * @param {AttributeState} attributeState + * @returns {[number, number]} The last current text position. + */ + TextChunk.prototype.put = function (transform, attributeState) { + var i, textNode; + + var xs = [], ys = [], attributeStates = []; + var currentTextX = this.originX, currentTextY = this.originY; + var minX = currentTextX, maxX = currentTextX; + for (i = 0; i < this.textNodes.length; i++) { + textNode = this.textNodes[i]; + + var x = currentTextX; + var y = currentTextY; + + if (textNode.nodeName === "#text") { + textNodeAttributeState = attributeState + } else { + var textNodeAttributeState = attributeState.clone(); + var tSpanColor = getAttribute(textNode, "fill"); + setTextProperties(textNode, tSpanColor && new RGBColor(tSpanColor), textNodeAttributeState); + + var tSpanDx = textNode.getAttribute("dx"); + if (tSpanDx !== null) { + x += toPixels(tSpanDx, textNodeAttributeState.fontSize); + } + + var tSpanDy = textNode.getAttribute("dy"); + if (tSpanDy !== null) { + y += toPixels(tSpanDy, textNodeAttributeState.fontSize); + } + } + + attributeStates[i] = textNodeAttributeState; + + xs[i] = x; + ys[i] = y; + + currentTextX = x + measureTextWidth(this.texts[i], textNodeAttributeState); + + currentTextY = y; + + minX = Math.min(minX, x); + maxX = Math.max(maxX, currentTextX); + } + + var textOffset; + switch (this.textAnchor) { + case "start": textOffset = 0; break; + case "middle": textOffset = (maxX - minX) / 2; break; + case "end": textOffset = maxX - minX; break; + } + + for (i = 0; i < this.textNodes.length; i++) { + textNode = this.textNodes[i]; + + if (textNode.nodeName !== "#text") { + var tSpanVisibility = getAttribute(textNode, "visibility") || attributeState.visibility; + if (tSpanVisibility === "hidden") { + continue; + } + } + + _pdf.saveGraphicsState(); + putTextProperties(attributeStates[i], attributeState); + + _pdf.text(xs[i] - textOffset, ys[i], this.texts[i], void 0, transform); + + _pdf.restoreGraphicsState(); + } + + return [currentTextX, currentTextY]; + }; + + /** + * Convert em, px and bare number attributes to pixel values + * @param {string} value + * @param {number} pdfFontSize + */ + function toPixels(value, pdfFontSize) { + var match; + + // em + match = value && value.toString().match(/^([\-0-9.]+)em$/); + if (match) { + return parseFloat(match[1]) * pdfFontSize; + } + + // pixels + match = value && value.toString().match(/^([\-0-9.]+)(px|)$/); + if (match) { + return parseFloat(match[1]); + } + return 0; + } + + + function transformXmlSpace(trimmedText, attributeState) { + trimmedText = removeNewlines(trimmedText); + trimmedText = replaceTabsBySpace(trimmedText); + + if (attributeState.xmlSpace === "default") { + trimmedText = trimmedText.trim(); + trimmedText = consolidateSpaces(trimmedText); + } + + return trimmedText; + } + + /** + * Draws a text element and its tspan children. + * @param {SVGElement} node + * @param {jsPDF.Matrix} tfMatrix + * @param {boolean} hasFillColor + * @param {RGBColor} fillRGB + * @param {AttributeState} attributeState + */ + var text = function (node, tfMatrix, hasFillColor, fillRGB, attributeState) { + _pdf.saveGraphicsState(); + + var dx, dy, xOffset = 0; + + var pdfFontSize = _pdf.getFontSize(); + var textX = toPixels(node.getAttribute('x'), pdfFontSize); + var textY = toPixels(node.getAttribute('y'), pdfFontSize); + + dx = toPixels(node.getAttribute("dx"), pdfFontSize); + dy = toPixels(node.getAttribute("dy"), pdfFontSize); + + var visibility = attributeState.visibility; + // when there are no tspans draw the text directly + var tSpanCount = node.childElementCount; + if (tSpanCount === 0) { + var trimmedText = transformXmlSpace(node.textContent, attributeState); + var transformedText = transformText(node, trimmedText); + xOffset = getTextOffset(transformedText, attributeState); + + if (visibility === "visible") { + _pdf.text( + textX + dx - xOffset, + textY + dy, + transformedText, + void 0, + tfMatrix + ); + } + } else { + // otherwise loop over tspans and position each relative to the previous one + var currentTextSegment = new TextChunk(attributeState.textAnchor, textX + dx, textY + dy); + + for (var i = 0; i < node.childNodes.length; i++) { + var textNode = node.childNodes[i]; + if (!textNode.textContent) { + continue; + } + + var xmlSpace = attributeState.xmlSpace; + + if (textNode.nodeName === "#text") { + + } else if (nodeIs(textNode, "tspan")) { + var tSpan = textNode; + + var lastPositions; + + var tSpanAbsX = tSpan.getAttribute("x"); + if (tSpanAbsX !== null) { + var x = toPixels(tSpanAbsX, pdfFontSize); + + lastPositions = currentTextSegment.put(tfMatrix, attributeState); + currentTextSegment = new TextChunk(tSpan.getAttribute("text-anchor") || attributeState.textAnchor, x, lastPositions[1]); + } + + var tSpanAbsY = tSpan.getAttribute("y"); + if (tSpanAbsY !== null) { + var y = toPixels(tSpanAbsY, pdfFontSize); + + lastPositions = currentTextSegment.put(tfMatrix, attributeState); + currentTextSegment = new TextChunk(tSpan.getAttribute("text-anchor") || attributeState.textAnchor, lastPositions[0], y); + } + + var tSpanXmlSpace = tSpan.getAttribute("xml:space"); + if (tSpanXmlSpace) { + xmlSpace = tSpanXmlSpace; + } + } + + trimmedText = textNode.textContent; + trimmedText = removeNewlines(trimmedText); + trimmedText = replaceTabsBySpace(trimmedText); + + if (xmlSpace === "default") { + if (i === 0) { + trimmedText = trimLeft(trimmedText); + } + if (i === tSpanCount - 1) { + trimmedText = trimRight(trimmedText); + } + + trimmedText = consolidateSpaces(trimmedText); + } + + transformedText = transformText(node, trimmedText); + currentTextSegment.add(textNode, transformedText); + } + + currentTextSegment.put(tfMatrix, attributeState); + } + + _pdf.restoreGraphicsState(); + }; + + // renders all children of a node + var renderChildren = function (node, tfMatrix, refsHandler, withinDefs, withinClipPath, attributeState) { + forEachChild(node, function (i, node) { + renderNode(node, tfMatrix, refsHandler, withinDefs, withinClipPath, attributeState); + }); + }; + + // adds a gradient to defs and the pdf document for later use, type is either "axial" or "radial" + // opacity is only supported rudimentary by averaging over all stops + // transforms are applied on use + var putGradient = function (node, type, coords) { + var colors = []; + var opacitySum = 0; + var hasOpacity = false; + var gState; + forEachChild(node, function (i, element) { + // since opacity gradients are hard to realize, average the opacity over the control points + if (element.tagName.toLowerCase() === "stop") { + var color = new RGBColor(getAttribute(element, "stop-color")); + colors.push({ + offset: parseFloat(element.getAttribute("offset")), + color: [color.r, color.g, color.b] + }); + var opacity = getAttribute(element, "stop-opacity"); + if (opacity && opacity != 1) { + opacitySum += parseFloat(opacity); + hasOpacity = true; + } + } + }); + + if (hasOpacity) { + gState = new _pdf.GState({opacity: opacitySum / colors.length}); + } + + var pattern = new _pdf.ShadingPattern(type, coords, colors, gState); + var id = node.getAttribute("id"); + _pdf.addShadingPattern(id, pattern); + }; + + var pattern = function (node, refsHandler, attributeState) { + var id = node.getAttribute("id"); + + // the transformations directly at the node are written to the pattern transformation matrix + var bBox = getUntransformedBBox(node); + var pattern = new _pdf.TilingPattern([bBox[0], bBox[1], bBox[0] + bBox[2], bBox[1] + bBox[3]], bBox[2], bBox[3], + null, _pdf.unitMatrix /* this parameter is ignored !*/); + + _pdf.beginTilingPattern(pattern); + // continue without transformation + renderChildren(node, _pdf.unitMatrix, refsHandler, false, false, attributeState); + _pdf.endTilingPattern(id, pattern); + }; + + var fontAliases = { + "sans-serif": "helvetica", + "verdana": "helvetica", + "arial": "helvetica", + + "fixed": "courier", + "monospace": "courier", + "terminal": "courier", + + "serif": "times", + "cursive": "times", + "fantasy": "times" + }; + + /** + * @param {AttributeState} attributeState + * @param {string[]} fontFamilies + * @return {string} + */ + function findFirstAvailableFontFamily(attributeState, fontFamilies) { + var fontType = ""; + if (attributeState.fontWeight === "bold") { + fontType = "bold"; + } + if (attributeState.fontStyle === "italic") { + fontType += "italic"; + } + if (fontType === "") { + fontType = "normal"; + } + + var availableFonts = _pdf.getFontList(); + var firstAvailable = ""; + var fontIsAvailable = fontFamilies.some(function (font) { + var availableStyles = availableFonts[font]; + if (availableStyles && availableStyles.indexOf(fontType) >= 0) { + firstAvailable = font; + return true; + } + + font = font.toLowerCase(); + if (fontAliases.hasOwnProperty(font)) { + firstAvailable = font; + return true; + } + + return false; + }); + + if (!fontIsAvailable) { + firstAvailable = "times"; + } + + return firstAvailable; + } + + function setTextProperties(node, fillRGB, attributeState) { + if (fillRGB && fillRGB.ok) { + attributeState.fill = fillRGB; + } + + var fontWeight = getAttribute(node, "font-weight"); + if (fontWeight) { + attributeState.fontWeight = fontWeight; + } + + var fontStyle = getAttribute(node, "font-style"); + if (fontStyle) { + attributeState.fontStyle = fontStyle; + } + + var fontFamily = getAttribute(node, "font-family"); + if (fontFamily) { + var fontFamilies = FontFamily.parse(fontFamily); + attributeState.fontFamily = findFirstAvailableFontFamily(attributeState, fontFamilies); + } + + var fontSize = getAttribute(node, "font-size"); + if (fontSize) { + attributeState.fontSize = parseFloat(fontSize); + } + + var textAnchor = getAttribute(node, "text-anchor"); + if (textAnchor) { + attributeState.textAnchor = textAnchor; + } + } + + /** + * @param {AttributeState} attributeState + * @param {AttributeState} parentAttributeState + */ + function putTextProperties(attributeState, parentAttributeState) { + if (attributeState.fontFamily !== parentAttributeState.fontFamily) { + if (fontAliases.hasOwnProperty(attributeState.fontFamily)) { + _pdf.setFont(fontAliases[attributeState.fontFamily]); + } else { + _pdf.setFont(attributeState.fontFamily); + } + } + + if (attributeState.fill !== parentAttributeState.fill && attributeState.fill.ok) { + var fillRGB = attributeState.fill; + _pdf.setTextColor(fillRGB.r, fillRGB.g, fillRGB.b); + } + + if (attributeState.fontWeight !== parentAttributeState.fontWeight + || attributeState.fontStyle !== parentAttributeState.fontStyle) { + var fontType = ""; + if (attributeState.fontWeight === "bold") { + fontType = "bold"; + } + if (attributeState.fontStyle === "italic") { + fontType += "italic"; + } + + if (fontType === "") { + fontType = "normal"; + } + + _pdf.setFontType(fontType); + } + + if (attributeState.fontSize !== parentAttributeState.fontSize) { + _pdf.setFontSize(attributeState.fontSize); + } + } + + + /** + * Renders a svg node. + * @param node The svg element + * @param contextTransform The current transformation matrix + * @param refsHandler The handler that will render references on demand + * @param withinDefs True iff we are top-level within a defs node, so the target can be switched to an pdf form object + * @param {boolean} withinClipPath + * @param {AttributeState} attributeState Keeps track of parent attributes that are inherited automatically + */ + var renderNode = function (node, contextTransform, refsHandler, withinDefs, withinClipPath, attributeState) { + var parentAttributeState = attributeState; + attributeState = attributeState.clone(); + + if (nodeIs(node, "defs,clippath,pattern,lineargradient,radialgradient,marker")) { + // we will only render them on demand + return; + } + + if (getAttribute(node, "display") === "none") { + return; + } + + var visibility = attributeState.visibility = getAttribute(node, "visibility") || attributeState.visibility; + if (visibility === "hidden" && !nodeIs(node, "svg,g,marker,a,pattern,defs,text")) { + return; + } + + var tfMatrix, + hasFillColor = false, + fillRGB = null, + fill = "inherit", + stroke = "inherit", + patternOrGradient = undefined, + bBox; + + // + // Decide about the render target and set the correct transformation + // + + // if we are within a defs node, start a new pdf form object and draw this node and all children on that instead + // of the top-level page + var targetIsFormObject = withinDefs && !nodeIs(node, "lineargradient,radialgradient,pattern,clippath"); + if (targetIsFormObject) { + + // the transformations directly at the node are written to the pdf form object transformation matrix + tfMatrix = computeNodeTransform(node); + bBox = getUntransformedBBox(node); + + _pdf.beginFormObject(bBox[0], bBox[1], bBox[2], bBox[3], tfMatrix); + + // continue without transformation and set withinDefs to false to prevent child nodes from starting new form objects + tfMatrix = _pdf.unitMatrix; + withinDefs = false; + + } else { + tfMatrix = _pdf.matrixMult(computeNodeTransform(node), contextTransform); + + if (!withinClipPath) { + _pdf.saveGraphicsState(); + } + } + + var hasClipPath = node.hasAttribute("clip-path") && node.getAttribute("clip-path") !== "none"; + if (hasClipPath) { + var clipPathId = iriReference.exec(node.getAttribute("clip-path")); + var clipPathNode = refsHandler.getRendered(clipPathId[1]); + + var clipPathMatrix = tfMatrix; + if (clipPathNode.hasAttribute("clipPathUnits") + && clipPathNode.getAttribute("clipPathUnits").toLowerCase() === "objectboundingbox") { + bBox = getUntransformedBBox(node); + clipPathMatrix = _pdf.matrixMult(new _pdf.Matrix(bBox[2], 0, 0, bBox[3], bBox[0], bBox[1]), clipPathMatrix); + } + + // here, browsers show different results for a "transform" attribute on the clipPath element itself: + // IE/Edge considers it, Chrome and Firefox ignore it. However, the specification lists "transform" as a valid + // attribute for clipPath elements, although not explicitly explaining its behavior. This implementation follows + // IE/Edge and considers the "transform" attribute as additional transformation within the coordinate system + // established by the "clipPathUnits" attribute. + clipPathMatrix = _pdf.matrixMult(computeNodeTransform(clipPathNode), clipPathMatrix); + + _pdf.saveGraphicsState(); + _pdf.setCurrentTransformationMatrix(clipPathMatrix); + + renderChildren(clipPathNode, _pdf.unitMatrix, refsHandler, false, true, attributeState); + _pdf.clip().discardPath(); + + // as we cannot use restoreGraphicsState() to reset the transform (this would reset the clipping path, as well), + // we must append the inverse instead + _pdf.setCurrentTransformationMatrix(clipPathMatrix.inversed()); + } + + // + // extract fill and stroke mode + // + + // fill mode + if (nodeIs(node, "g,path,rect,text,ellipse,line,circle,polygon,polyline")) { + function setDefaultColor() { + fillRGB = new RGBColor("rgb(0, 0, 0)"); + hasFillColor = true; + fill = true; + } + + var fillColor = getAttribute(node, "fill"); + if (fillColor) { + var url = iriReference.exec(fillColor); + if (url) { + // probably a gradient or pattern (or something unsupported) + var fillUrl = url[1]; + var fillNode = refsHandler.getRendered(fillUrl); + if (fillNode && nodeIs(fillNode, "lineargradient,radialgradient")) { + + // matrix to convert between gradient space and user space + // for "userSpaceOnUse" this is the current transformation: tfMatrix + // for "objectBoundingBox" or default, the gradient gets scaled and transformed to the bounding box + var gradientUnitsMatrix; + if (!fillNode.hasAttribute("gradientUnits") + || fillNode.getAttribute("gradientUnits").toLowerCase() === "objectboundingbox") { + bBox || (bBox = getUntransformedBBox(node)); + gradientUnitsMatrix = new _pdf.Matrix(bBox[2], 0, 0, bBox[3], bBox[0], bBox[1]); + } else { + gradientUnitsMatrix = _pdf.unitMatrix; + } + + // matrix that is applied to the gradient before any other transformations + var gradientTransform = parseTransform(fillNode.getAttribute("gradientTransform")); + + patternOrGradient = { + key: fillUrl, + matrix: _pdf.matrixMult(gradientTransform, gradientUnitsMatrix) + }; + + fill = true; + } else if (fillNode && nodeIs(fillNode, "pattern")) { + var fillBBox, y, width, height, x; + patternOrGradient = { key: fillUrl }; + + var patternUnitsMatrix = _pdf.unitMatrix; + if (!fillNode.hasAttribute("patternUnits") + || fillNode.getAttribute("patternUnits").toLowerCase() === "objectboundingbox") { + bBox || (bBox = getUntransformedBBox(node)); + patternUnitsMatrix = new _pdf.Matrix(1, 0, 0, 1, bBox[0], bBox[1]); + + // TODO: slightly inaccurate (rounding errors? line width bBoxes?) + fillBBox = getUntransformedBBox(fillNode); + x = fillBBox[0] * bBox[0]; + y = fillBBox[1] * bBox[1]; + width = fillBBox[2] * bBox[2]; + height = fillBBox[3] * bBox[3]; + patternOrGradient.boundingBox = [x, y, x + width, y + height]; + patternOrGradient.xStep = width; + patternOrGradient.yStep = height; + } + + var patternContentUnitsMatrix = _pdf.unitMatrix; + if (fillNode.hasAttribute("patternContentUnits") + && fillNode.getAttribute("patternContentUnits").toLowerCase() === "objectboundingbox") { + bBox || (bBox = getUntransformedBBox(node)); + patternContentUnitsMatrix = new _pdf.Matrix(bBox[2], 0, 0, bBox[3], 0, 0); + + fillBBox = patternOrGradient.boundingBox || getUntransformedBBox(fillNode); + x = fillBBox[0] / bBox[0]; + y = fillBBox[1] / bBox[1]; + width = fillBBox[2] / bBox[2]; + height = fillBBox[3] / bBox[3]; + patternOrGradient.boundingBox = [x, y, x + width, y + height]; + patternOrGradient.xStep = width; + patternOrGradient.yStep = height; + } + + var patternTransformMatrix = _pdf.unitMatrix; + if (fillNode.hasAttribute("patternTransform")) { + patternTransformMatrix = parseTransform(fillNode.getAttribute("patternTransform")); + } + + var matrix = patternContentUnitsMatrix; + matrix = _pdf.matrixMult(matrix, patternUnitsMatrix); + matrix = _pdf.matrixMult(matrix, patternTransformMatrix); + matrix = _pdf.matrixMult(matrix, tfMatrix); + + patternOrGradient.matrix = matrix; + + fill = true; + } else { + // unsupported fill argument -> fill black + setDefaultColor(); + } + } else { + // plain color + fillRGB = parseColor(fillColor); + if (fillRGB.ok) { + hasFillColor = true; + fill = true; + } else { + fill = false; + } + } + } + + // opacity is realized via a pdf graphics state + var fillOpacity = 1.0, strokeOpacity = 1.0; + var nodeFillOpacity = getAttribute(node, "fill-opacity"); + if (nodeFillOpacity) { + fillOpacity *= parseFloat(nodeFillOpacity); + } + if (fillRGB && typeof fillRGB.a === "number") { + fillOpacity *= fillRGB.a; + } + + var nodeStrokeOpacity = getAttribute(node, "stroke-opacity"); + if (nodeStrokeOpacity) { + strokeOpacity *= parseFloat(nodeStrokeOpacity); + } + if (strokeRGB && typeof strokeRGB.a === "number") { + strokeOpacity *= strokeRGB.a; + } + + var nodeOpacity = getAttribute(node, "opacity"); + if (nodeOpacity) { + var opacity = parseFloat(nodeOpacity); + strokeOpacity *= opacity; + fillOpacity *= opacity; + } + + var hasFillOpacity = fillOpacity < 1.0; + var hasStrokeOpacity = strokeOpacity < 1.0; + if (hasFillOpacity || hasStrokeOpacity) { + var gState = {}; + hasFillOpacity && (gState["opacity"] = fillOpacity); + hasStrokeOpacity && (gState["stroke-opacity"] = strokeOpacity); + _pdf.setGState(new _pdf.GState(gState)); + } + + } + + if (nodeIs(node, "g,path,rect,ellipse,line,circle,polygon,polyline")) { + // text has no fill color, so don't apply it until here + if (hasFillColor) { + attributeState.fill = fillRGB; + _pdf.setFillColor(fillRGB.r, fillRGB.g, fillRGB.b); + } + + // stroke mode + var strokeColor = getAttribute(node, "stroke"); + if (strokeColor) { + var strokeWidth = getAttribute(node, "stroke-width"); + if (strokeWidth !== void 0 && strokeWidth !== "") { + strokeWidth = Math.abs(parseFloat(strokeWidth)); + attributeState.strokeWidth = strokeWidth; + _pdf.setLineWidth(strokeWidth); + } else { + // needed for inherited zero width strokes + strokeWidth = attributeState.strokeWidth + } + var strokeRGB = new RGBColor(strokeColor); + if (strokeRGB.ok) { + attributeState.stroke = strokeRGB; + _pdf.setDrawColor(strokeRGB.r, strokeRGB.g, strokeRGB.b); + + // pdf spec states: "A line width of 0 denotes the thinnest line that can be rendered at device resolution: + // 1 device pixel wide". SVG, however, does not draw zero width lines. + stroke = strokeWidth !== 0; + } + var lineCap = getAttribute(node, "stroke-linecap"); + if (lineCap) { + _pdf.setLineCap(attributeState.strokeLinecap = lineCap); + } + var lineJoin = getAttribute(node, "stroke-linejoin"); + if (lineJoin) { + _pdf.setLineJoin(attributeState.strokeLinejoin = lineJoin); + } + var dashArray = getAttribute(node, "stroke-dasharray"); + if (dashArray) { + dashArray = parseFloats(dashArray); + var dashOffset = parseInt(getAttribute(node, "stroke-dashoffset")) || 0; + attributeState.strokeDasharray = dashArray; + attributeState.strokeDashoffset = dashOffset; + _pdf.setLineDashPattern(dashArray, dashOffset); + } + var miterLimit = getAttribute(node, "stroke-miterlimit"); + if (miterLimit !== void 0 && miterLimit !== "") { + _pdf.setLineMiterLimit(attributeState.strokeMiterlimit = parseFloat(miterLimit)); + } + } + } + + // inherit fill and stroke mode if not specified at this node + if (fill === "inherit") { + fill = attributeState.fill !== null; + } + if (stroke === "inherit") { + stroke = attributeState.stroke !== null; + } + + var xmlSpace = node.getAttribute("xml:space"); + if (xmlSpace) { + attributeState.xmlSpace = xmlSpace; + } + + setTextProperties(node, fillRGB, attributeState); + putTextProperties(attributeState, parentAttributeState); + + // do the actual drawing + switch (node.tagName.toLowerCase()) { + case 'svg': + case 'g': + case 'a': + renderChildren(node, tfMatrix, refsHandler, withinDefs, false, attributeState); + break; + + case 'use': + use(node, tfMatrix, refsHandler); + break; + + case 'line': + if (!withinClipPath) { + _pdf.setCurrentTransformationMatrix(tfMatrix); + line(node, refsHandler, attributeState); + } + break; + + case 'rect': + if (!withinClipPath) { + _pdf.setCurrentTransformationMatrix(tfMatrix); + } + rect(node); + break; + + case 'ellipse': + if (!withinClipPath) { + _pdf.setCurrentTransformationMatrix(tfMatrix); + } + ellipse(node); + break; + + case 'circle': + if (!withinClipPath) { + _pdf.setCurrentTransformationMatrix(tfMatrix); + } + circle(node); + break; + case 'text': + text(node, tfMatrix, hasFillColor, fillRGB, attributeState); + break; + + case 'path': + if (!withinClipPath) { + _pdf.setCurrentTransformationMatrix(tfMatrix); + } + path(node, tfMatrix, refsHandler, withinClipPath, attributeState); + break; + + case 'polygon': + case 'polyline': + if (!withinClipPath) { + _pdf.setCurrentTransformationMatrix(tfMatrix); + } + polygon(node, refsHandler, attributeState, node.tagName.toLowerCase() === "polygon"); + break; + + case 'image': + _pdf.setCurrentTransformationMatrix(tfMatrix); + image(node); + break; + } + + if (nodeIs(node, "path,rect,ellipse,circle,polygon,polyline") && !withinClipPath) { + if (fill && stroke) { + _pdf.fillStroke(patternOrGradient); + } else if (fill) { + _pdf.fill(patternOrGradient); + } else if (stroke) { + _pdf.stroke(); + } else { + _pdf.discardPath(); + } + } + + // close either the formObject or the graphics context + if (targetIsFormObject) { + _pdf.endFormObject(node.getAttribute("id")); + } else if (!withinClipPath) { + _pdf.restoreGraphicsState(); + } + + if (hasClipPath) { + _pdf.restoreGraphicsState(); + } + }; + + // the actual svgToPdf function (see above) + var svg2pdf = function (element, pdf, options) { + _pdf = pdf; + + var k = options.scale || 1.0, + xOffset = options.xOffset || 0.0, + yOffset = options.yOffset || 0.0; + + + _pdf.advancedAPI(function () { + + // set offsets and scale everything by k + _pdf.saveGraphicsState(); + _pdf.setCurrentTransformationMatrix(new _pdf.Matrix(k, 0, 0, k, xOffset, yOffset)); + + // set default values that differ from pdf defaults + var attributeState = AttributeState.default(); + _pdf.setLineWidth(attributeState.strokeWidth); + var fill = attributeState.fill; + _pdf.setFillColor(fill.r, fill.g, fill.b); + _pdf.setFont(attributeState.fontFamily); + _pdf.setFontSize(attributeState.fontSize); + + + var refsHandler = new ReferencesHandler(element); + renderNode(element.cloneNode(true), _pdf.unitMatrix, refsHandler, false, false, attributeState); + + _pdf.restoreGraphicsState(); + + }); + + return _pdf; + }; + + if (typeof define === "function" && define.amd) { + define(["./rgbcolor", "SvgPath", "font-family", "cssesc"], function (rgbcolor, svgpath, fontFamily, cssesc) { + RGBColor = rgbcolor; + SvgPath = svgpath; + FontFamily = fontFamily; + cssEsc = cssesc; + return svg2pdf; + }); + } else if (typeof module !== "undefined" && module.exports) { + RGBColor = require("./rgbcolor.js"); + SvgPath = require("SvgPath"); + FontFamily = require("font-family"); + cssEsc = require("cssesc"); + module.exports = svg2pdf; + } else { + SvgPath = global.SvgPath; + RGBColor = global.RGBColor; + FontFamily = global.FontFamily; + cssEsc = global.cssesc; + global.svg2pdf = svg2pdf; + // for compatibility reasons + global.svgElementToPdf = svg2pdf; + } + return svg2pdf; +}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this)); + +},{"./rgbcolor.js":10,"SvgPath":1,"cssesc":8,"font-family":9}]},{},[11])(11) +}); +//# sourceMappingURL=svg2pdf.js.map diff --git a/highcharts/modules/accessibility.js b/highcharts/modules/accessibility.js new file mode 100644 index 0000000..2563bdc --- /dev/null +++ b/highcharts/modules/accessibility.js @@ -0,0 +1,180 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Accessibility module + + (c) 2010-2019 Highsoft AS + Author: Oystein Moseng + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/accessibility",["highcharts"],function(r){a(r);a.Highcharts=r;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function r(a,h,q,n){a.hasOwnProperty(h)||(a[h]=n.apply(null,q))}a=a?a._modules:{};r(a,"Accessibility/Utils/HTMLUtilities.js",[a["Core/Utilities.js"],a["Core/Globals.js"]],function(a,h){function m(a){return a.replace(/&/g, +"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")}var n=a.merge,p=h.win,l=p.document;return{addClass:function(a,l){a.classList?a.classList.add(l):0>a.className.indexOf(l)&&(a.className+=l)},escapeStringForHTML:m,getElement:function(a){return l.getElementById(a)},getFakeMouseEvent:function(a){if("function"===typeof p.MouseEvent)return new p.MouseEvent(a);if(l.createEvent){var g=l.createEvent("MouseEvent");if(g.initMouseEvent)return g.initMouseEvent(a, +!0,!0,p,"click"===a?1:0,0,0,0,0,!1,!1,!1,!1,0,null),g}return{type:a}},removeElement:function(a){a&&a.parentNode&&a.parentNode.removeChild(a)},reverseChildNodes:function(a){for(var l=a.childNodes.length;l--;)a.appendChild(a.childNodes[l])},setElAttrs:function(a,l){Object.keys(l).forEach(function(k){var e=l[k];null===e?a.removeAttribute(k):(e=m(""+e),a.setAttribute(k,e))})},stripHTMLTagsFromString:function(a){return"string"===typeof a?a.replace(/<\/?[^>]+(>|$)/g,""):a},visuallyHideElement:function(a){n(!0, +a.style,{position:"absolute",width:"1px",height:"1px",overflow:"hidden",whiteSpace:"nowrap",clip:"rect(1px, 1px, 1px, 1px)",marginTop:"-3px","-ms-filter":"progid:DXImageTransform.Microsoft.Alpha(Opacity=1)",filter:"alpha(opacity=1)",opacity:"0.01"})}}});r(a,"Accessibility/Utils/ChartUtilities.js",[a["Accessibility/Utils/HTMLUtilities.js"],a["Core/Utilities.js"]],function(a,h){function m(e){if(e.points&&e.points.length&&e.points[0].graphic)return e.points[0].graphic.element}function n(e){var d=m(e); +return d&&d.parentNode||e.graph&&e.graph.element||e.group&&e.group.element}function p(e,d){d.setAttribute("aria-hidden",!1);d!==e.renderTo&&d.parentNode&&(Array.prototype.forEach.call(d.parentNode.childNodes,function(b){b.hasAttribute("aria-hidden")||b.setAttribute("aria-hidden",!0)}),p(e,d.parentNode))}var l=a.stripHTMLTagsFromString,g=h.defined,x=h.find,k=h.fireEvent;return{getChartTitle:function(e){return l(e.options.title.text||e.langFormat("accessibility.defaultChartTitle",{chart:e}))},getAxisDescription:function(e){return l(e&& +(e.userOptions&&e.userOptions.accessibility&&e.userOptions.accessibility.description||e.axisTitle&&e.axisTitle.textStr||e.options.id||e.categories&&"categories"||e.dateTime&&"Time"||"values"))},getPointFromXY:function(e,d,b){for(var f=e.length,c;f--;)if(c=x(e[f].points||[],function(c){return c.x===d&&c.y===b}))return c},getSeriesFirstPointElement:m,getSeriesFromName:function(e,d){return d?(e.series||[]).filter(function(b){return b.name===d}):e.series},getSeriesA11yElement:n,unhideChartElementFromAT:p, +hideSeriesFromAT:function(e){(e=n(e))&&e.setAttribute("aria-hidden",!0)},scrollToPoint:function(e){var d=e.series.xAxis,b=e.series.yAxis,f=(null===d||void 0===d?0:d.scrollbar)?d:b;if((d=null===f||void 0===f?void 0:f.scrollbar)&&g(d.to)&&g(d.from)){b=d.to-d.from;if(g(f.dataMin)&&g(f.dataMax)){var c=f.toPixels(f.dataMin),w=f.toPixels(f.dataMax);e=(f.toPixels(e["xAxis"===f.coll?"x":"y"]||0)-c)/(w-c)}else e=0;d.updatePosition(e-b/2,e+b/2);k(d,"changed",{from:d.from,to:d.to,trigger:"scrollbar",DOMEvent:null})}}}}); +r(a,"Accessibility/KeyboardNavigationHandler.js",[a["Core/Utilities.js"]],function(a){function m(a,m){this.chart=a;this.keyCodeMap=m.keyCodeMap||[];this.validate=m.validate;this.init=m.init;this.terminate=m.terminate;this.response={success:1,prev:2,next:3,noHandler:4,fail:5}}var q=a.find;m.prototype={run:function(a){var m=a.which||a.keyCode,l=this.response.noHandler,g=q(this.keyCodeMap,function(a){return-1a||f!==d-1;c.a11yProxyElement&&(c.a11yProxyElement.style.visibility=f?"hidden":"visible")})},onChartRender:function(){g(this.chart)?this.updateProxiesPositions(): +this.removeProxies()},updateProxiesPositions:function(){for(var b=0,d=this.proxyElementsList;b=v&&b||0<=v&&!b||5>g||e(k))&&g"+a+"
  • ":""})}var l=a.escapeStringForHTML,g=a.stripHTMLTagsFromString;return{getAnnotationsInfoHTML:function(a){var k=a.annotations;return k&&k.length?"
      "+p(a).join(" ")+"
    ":""},getAnnotationLabelDescription:n, +getAnnotationListItems:p,getPointAnnotationTexts:function(a){var k=m(a.series.chart).filter(function(e){return-1c&&b.graphic&&b.graphic.element)})||null:null}function g(b){var c=b.chart.options.accessibility.series.pointDescriptionEnabledThreshold;return!!(!1!==c&&b.points&&b.points.length>=c)}function m(b){var c=b.options.accessibility||{};return!g(b)&&!c.exposeAsGroupOnly}function k(b){var c=b.chart.options.accessibility.keyboardNavigation.seriesNavigation;return!(!b.points||!(b.points.length"," "),d=b.id&&0>b.id.indexOf("highcharts-"),e= +"x, "+b.x;return b.name||c||a||(d?b.id:e)}function w(b,c,a){var d=c||"",f=a||"";return b.series.pointArrayMap.reduce(function(c,a){c+=c.length?", ":"";var k=e(b,y(b[a],b.options[a]));return c+(a+": "+d+k+f)},"")}function A(b){var c=b.series,a=c.chart.options.accessibility.point||{},d=c.tooltipOptions||{},f=a.valuePrefix||d.valuePrefix||"";a=a.valueSuffix||d.valueSuffix||"";d=e(b,b["undefined"!==typeof b.value?"value":"y"]);return b.isNull?c.chart.langFormat("accessibility.series.nullPointValue",{point:b}): +c.pointArrayMap?w(b,f,a):f+d+a}function z(b){var a=b.series,d=a.chart,f=d.options.accessibility.point.valueDescriptionFormat,e=(a=y(a.xAxis&&a.xAxis.options.accessibility&&a.xAxis.options.accessibility.enabled,!d.angular))?c(b):"";b={point:b,index:D(b.index)?b.index+1:"",xDescription:e,value:A(b),separator:a?", ":""};return u(f,b,d)}function t(b){var c=b.series,a=c.chart,d=z(b),f=b.options&&b.options.accessibility&&b.options.accessibility.description;f=f?" "+f:"";c=1b&&da.dataMax&&(c=a.dataMax,d=c-f);this.setExtremes(d,c)};a=function(){};a.prototype=new q;g(a.prototype,{init:function(){var b=this,a=this.chart;["afterShowResetZoom","afterDrilldown","drillupall"].forEach(function(c){b.addEvent(a, +c,function(){b.updateProxyOverlays()})})},onChartUpdate:function(){var b=this.chart,a=this;b.mapNavButtons&&b.mapNavButtons.forEach(function(c,d){k(b,c.element);a.setMapNavButtonAttrs(c.element,"accessibility.zoom.mapZoom"+(d?"Out":"In"))})},setMapNavButtonAttrs:function(b,a){var c=this.chart;a=c.langFormat(a,{chart:c});e(b,{tabindex:-1,role:"button","aria-label":a})},onChartRender:function(){this.updateProxyOverlays()},updateProxyOverlays:function(){var b=this.chart;d(this.drillUpProxyGroup);d(this.resetZoomProxyGroup); +b.resetZoomButton&&this.recreateProxyButtonAndGroup(b.resetZoomButton,"resetZoomProxyButton","resetZoomProxyGroup",b.langFormat("accessibility.zoom.resetZoomButton",{chart:b}));b.drillUpButton&&this.recreateProxyButtonAndGroup(b.drillUpButton,"drillUpProxyButton","drillUpProxyGroup",b.langFormat("accessibility.drillUpButton",{chart:b,buttonText:b.getDrilldownBackText()}))},recreateProxyButtonAndGroup:function(b,a,c,e){d(this[c]);this[c]=this.addProxyGroup();this[a]=this.createProxyButton(b,this[c], +{"aria-label":e,tabindex:-1})},getMapZoomNavigation:function(){var b=this.keyCodes,a=this.chart,c=this;return new n(a,{keyCodeMap:[[[b.up,b.down,b.left,b.right],function(b){return c.onMapKbdArrow(this,b)}],[[b.tab],function(b,a){return c.onMapKbdTab(this,a)}],[[b.space,b.enter],function(){return c.onMapKbdClick(this)}]],validate:function(){return!!(a.mapZoom&&a.mapNavButtons&&a.mapNavButtons.length)},init:function(b){return c.onMapNavInit(b)}})},onMapKbdArrow:function(b,a){var c=this.keyCodes;this.chart[a=== +c.up||a===c.down?"yAxis":"xAxis"][0].panStep(a===c.left||a===c.up?-1:1);return b.response.success},onMapKbdTab:function(b,a){var c=this.chart;b=b.response;var d=(a=a.shiftKey)&&!this.focusedMapNavButtonIx||!a&&this.focusedMapNavButtonIx;c.mapNavButtons[this.focusedMapNavButtonIx].setState(0);if(d)return c.mapZoom(),b[a?"prev":"next"];this.focusedMapNavButtonIx+=a?-1:1;a=c.mapNavButtons[this.focusedMapNavButtonIx];c.setFocusToElement(a.box,a.element);a.setState(2);return b.success},onMapKbdClick:function(b){this.fakeClickEvent(this.chart.mapNavButtons[this.focusedMapNavButtonIx].element); +return b.response.success},onMapNavInit:function(b){var a=this.chart,c=a.mapNavButtons[0],d=a.mapNavButtons[1];c=0b)return a[0").replace(/</(h[1-7]|p|div|ul|ol|li|a|button)>/g,"").replace(/<(div|a|button) id="([a-zA-Z\-0-9#]*?)">/g,'<$1 id="$2">')}var k=a.doc,e=h.extend,d=h.format,b=h.pick,f=p.getAnnotationsInfoHTML,c=l.unhideChartElementFromAT, +w=l.getChartTitle,r=l.getAxisDescription,z=g.addClass,t=g.setElAttrs,E=g.escapeStringForHTML,B=g.stripHTMLTagsFromString,C=g.getElement,u=g.visuallyHideElement;a.Chart.prototype.getTypeDescription=function(b){var a=b[0],c=this.series&&this.series[0]||{};c={numSeries:this.series.length,numPoints:c.points&&c.points.length,chart:this,mapTitle:c.mapTitle};if(!a)return this.langFormat("accessibility.chartTypes.emptyChart",c);if("map"===a)return c.mapTitle?this.langFormat("accessibility.chartTypes.mapTypeDescription", +c):this.langFormat("accessibility.chartTypes.unknownMap",c);if(1this.series.length?"Single":"Multiple";return(this.langFormat("accessibility.chartTypes."+b+d,c)||this.langFormat("accessibility.chartTypes.default"+d,c))+(a?" "+a:"")};h=function(){};h.prototype=new q;e(h.prototype,{init:function(){var b=this.chart,a=this; +this.initRegionsDefinitions();this.addEvent(b,"afterGetTable",function(b){a.onDataTableCreated(b)});this.addEvent(b,"afterViewData",function(b){a.dataTableDiv=b;setTimeout(function(){a.focusDataTable()},300)});this.announcer=new n(b,"assertive")},initRegionsDefinitions:function(){var b=this;this.screenReaderSections={before:{element:null,buildContent:function(a){var c=a.options.accessibility.screenReaderSection.beforeChartFormatter;return c?c(a):b.defaultBeforeChartFormatter(a)},insertIntoDOM:function(b, +a){a.renderTo.insertBefore(b,a.renderTo.firstChild)},afterInserted:function(){"undefined"!==typeof b.sonifyButtonId&&b.initSonifyButton(b.sonifyButtonId);"undefined"!==typeof b.dataTableButtonId&&b.initDataTableButton(b.dataTableButtonId)}},after:{element:null,buildContent:function(a){var c=a.options.accessibility.screenReaderSection.afterChartFormatter;return c?c(a):b.defaultAfterChartFormatter()},insertIntoDOM:function(b,a){a.renderTo.insertBefore(b,a.container.nextSibling)}}}},onChartRender:function(){var b= +this;this.linkedDescriptionElement=this.getLinkedDescriptionElement();this.setLinkedDescriptionAttrs();Object.keys(this.screenReaderSections).forEach(function(a){b.updateScreenReaderSection(a)})},getLinkedDescriptionElement:function(){var b=this.chart.options.accessibility.linkedDescription;if(b){if("string"!==typeof b)return b;b=d(b,this.chart);b=k.querySelectorAll(b);if(1===b.length)return b[0]}},setLinkedDescriptionAttrs:function(){var b=this.linkedDescriptionElement;b&&(b.setAttribute("aria-hidden", +"true"),z(b,"highcharts-linked-description"))},updateScreenReaderSection:function(b){var a=this.chart,d=this.screenReaderSections[b],e=d.buildContent(a),f=d.element=d.element||this.createElement("div"),l=f.firstChild||this.createElement("div");this.setScreenReaderSectionAttribs(f,b);l.innerHTML=e;f.appendChild(l);d.insertIntoDOM(f,a);u(l);c(a,l);d.afterInserted&&d.afterInserted()},setScreenReaderSectionAttribs:function(b,a){var c=this.chart,d=c.langFormat("accessibility.screenReaderSection."+a+"RegionLabel", +{chart:c});t(b,{id:"highcharts-screen-reader-region-"+a+"-"+c.index,"aria-label":d});b.style.position="relative";"all"===c.options.accessibility.landmarkVerbosity&&d&&b.setAttribute("role","region")},defaultBeforeChartFormatter:function(){var b,c=this.chart,d=c.options.accessibility.screenReaderSection.beforeChartFormat,e=this.getAxesDescription(),l=c.sonify&&(null===(b=c.options.sonification)||void 0===b?void 0:b.enabled);b="highcharts-a11y-sonify-data-btn-"+c.index;var k="hc-linkto-highcharts-data-table-"+ +c.index,g=f(c),h=c.langFormat("accessibility.screenReaderSection.annotations.heading",{chart:c});e={chartTitle:w(c),typeDescription:this.getTypeDescriptionText(),chartSubtitle:this.getSubtitleText(),chartLongdesc:this.getLongdescText(),xAxisDescription:e.xAxis,yAxisDescription:e.yAxis,playAsSoundButton:l?this.getSonifyButtonText(b):"",viewTableButton:c.getCSV?this.getDataTableButtonText(k):"",annotationsTitle:g?h:"",annotationsList:g};c=a.i18nFormat(d,e,c);this.dataTableButtonId=k;this.sonifyButtonId= +b;return m(E(c)).replace(/<(\w+)[^>]*?>\s*<\/\1>/g,"")},defaultAfterChartFormatter:function(){var b=this.chart,c=b.options.accessibility.screenReaderSection.afterChartFormat,d={endOfChartMarker:this.getEndOfChartMarkerText()};b=a.i18nFormat(c,d,b);return m(E(b)).replace(/<(\w+)[^>]*?>\s*<\/\1>/g,"")},getLinkedDescription:function(){var b=this.linkedDescriptionElement;return B(b&&b.innerHTML||"")},getLongdescText:function(){var b=this.chart.options,a=b.caption;a=a&&a.text;var c=this.getLinkedDescription(); +return b.accessibility.description||c||a||""},getTypeDescriptionText:function(){var b=this.chart;return b.types?b.options.accessibility.typeDescription||b.getTypeDescription(b.types):""},getDataTableButtonText:function(b){var a=this.chart;a=a.langFormat("accessibility.table.viewAsDataTableButtonText",{chart:a,chartTitle:w(a)});return'"},getSonifyButtonText:function(b){var a,c=this.chart;if(!1===(null===(a=c.options.sonification)||void 0===a?void 0:a.enabled))return""; +a=c.langFormat("accessibility.sonification.playAsSoundButtonText",{chart:c,chartTitle:w(c)});return'"},getSubtitleText:function(){var b=this.chart.options.subtitle;return B(b&&b.text||"")},getEndOfChartMarkerText:function(){var b=this.chart,a=b.langFormat("accessibility.screenReaderSection.endOfChartMarker",{chart:b});return'
    '+a+"
    "},onDataTableCreated:function(b){var a=this.chart;a.options.accessibility.enabled&& +(this.viewDataTableButton&&this.viewDataTableButton.setAttribute("aria-expanded","true"),b.html=b.html.replace("a.types.indexOf("map"),e=!!a.hasCartesianSeries, +f=c("xAxis",!a.angular&&e&&d);c=c("yAxis",e&&d);d={};f&&(d.xAxis=this.getAxisDescriptionText("xAxis"));c&&(d.yAxis=this.getAxisDescriptionText("yAxis"));return d},getAxisDescriptionText:function(b){var a=this,c=this.chart,d=c[b];return c.langFormat("accessibility.axis."+b+"Description"+(1{chartTitle}
    {typeDescription}
    {chartSubtitle}
    {chartLongdesc}
    {playAsSoundButton}
    {viewTableButton}
    {xAxisDescription}
    {yAxisDescription}
    {annotationsTitle}{annotationsList}
    ", +afterChartFormat:"{endOfChartMarker}",axisRangeDateFormat:"%Y-%m-%d %H:%M:%S"},series:{describeSingleSeries:!1,pointDescriptionEnabledThreshold:200},point:{valueDescriptionFormat:"{index}. {xDescription}{separator}{value}."},landmarkVerbosity:"all",linkedDescription:'*[data-highcharts-chart="{index}"] + .highcharts-description',keyboardNavigation:{enabled:!0,focusBorder:{enabled:!0,hideBrowserFocusOutline:!0,style:{color:"#335cad",lineWidth:2,borderRadius:3},margin:2},order:["series","zoom","rangeSelector", +"legend","chartMenu"],wrapAround:!0,seriesNavigation:{skipNullPoints:!0,pointNavigationEnabledThreshold:!1}},announceNewData:{enabled:!1,minAnnounceInterval:5E3,interruptUser:!1}},legend:{accessibility:{enabled:!0,keyboardNavigation:{enabled:!0}}},exporting:{accessibility:{enabled:!0}}}});r(a,"Accessibility/Options/LangOptions.js",[],function(){return{accessibility:{defaultChartTitle:"Chart",chartContainerLabel:"{title}. Highcharts interactive chart.",svgContainerLabel:"Interactive chart",drillUpButton:"{buttonText}", +credits:"Chart credits: {creditsStr}",thousandsSep:",",svgContainerTitle:"",graphicContainerLabel:"",screenReaderSection:{beforeRegionLabel:"Chart screen reader information.",afterRegionLabel:"",annotations:{heading:"Chart annotations summary",descriptionSinglePoint:"{annotationText}. Related to {annotationPoint}",descriptionMultiplePoints:"{annotationText}. Related to {annotationPoint}{ Also related to, #each(additionalAnnotationPoints)}",descriptionNoPoints:"{annotationText}"},endOfChartMarker:"End of interactive chart."}, +sonification:{playAsSoundButtonText:"Play as sound, {chartTitle}",playAsSoundClickAnnouncement:"Play"},legend:{legendLabel:"Toggle series visibility",legendItem:"Hide {itemName}"},zoom:{mapZoomIn:"Zoom chart",mapZoomOut:"Zoom out chart",resetZoomButton:"Reset zoom"},rangeSelector:{minInputLabel:"Select start date.",maxInputLabel:"Select end date.",buttonText:"Select range {buttonText}"},table:{viewAsDataTableButtonText:"View as data table, {chartTitle}",tableSummary:"Table representation of chart."}, +announceNewData:{newDataAnnounce:"Updated data for chart {chartTitle}",newSeriesAnnounceSingle:"New data series: {seriesDesc}",newPointAnnounceSingle:"New data point: {pointDesc}",newSeriesAnnounceMultiple:"New data series in chart {chartTitle}: {seriesDesc}",newPointAnnounceMultiple:"New data point in chart {chartTitle}: {pointDesc}"},seriesTypeDescriptions:{boxplot:"Box plot charts are typically used to display groups of statistical data. Each data point in the chart can have up to 5 values: minimum, lower quartile, median, upper quartile, and maximum.", +arearange:"Arearange charts are line charts displaying a range between a lower and higher value for each point.",areasplinerange:"These charts are line charts displaying a range between a lower and higher value for each point.",bubble:"Bubble charts are scatter charts where each data point also has a size value.",columnrange:"Columnrange charts are column charts displaying a range between a lower and higher value for each point.",errorbar:"Errorbar series are used to display the variability of the data.", +funnel:"Funnel charts are used to display reduction of data in stages.",pyramid:"Pyramid charts consist of a single pyramid with item heights corresponding to each point value.",waterfall:"A waterfall chart is a column chart where each column contributes towards a total end value."},chartTypes:{emptyChart:"Empty chart",mapTypeDescription:"Map of {mapTitle} with {numSeries} data series.",unknownMap:"Map of unspecified region with {numSeries} data series.",combinationChart:"Combination chart with {numSeries} data series.", +defaultSingle:"Chart with {numPoints} data {#plural(numPoints, points, point)}.",defaultMultiple:"Chart with {numSeries} data series.",splineSingle:"Line chart with {numPoints} data {#plural(numPoints, points, point)}.",splineMultiple:"Line chart with {numSeries} lines.",lineSingle:"Line chart with {numPoints} data {#plural(numPoints, points, point)}.",lineMultiple:"Line chart with {numSeries} lines.",columnSingle:"Bar chart with {numPoints} {#plural(numPoints, bars, bar)}.",columnMultiple:"Bar chart with {numSeries} data series.", +barSingle:"Bar chart with {numPoints} {#plural(numPoints, bars, bar)}.",barMultiple:"Bar chart with {numSeries} data series.",pieSingle:"Pie chart with {numPoints} {#plural(numPoints, slices, slice)}.",pieMultiple:"Pie chart with {numSeries} pies.",scatterSingle:"Scatter chart with {numPoints} {#plural(numPoints, points, point)}.",scatterMultiple:"Scatter chart with {numSeries} data series.",boxplotSingle:"Boxplot with {numPoints} {#plural(numPoints, boxes, box)}.",boxplotMultiple:"Boxplot with {numSeries} data series.", +bubbleSingle:"Bubble chart with {numPoints} {#plural(numPoints, bubbles, bubble)}.",bubbleMultiple:"Bubble chart with {numSeries} data series."},axis:{xAxisDescriptionSingular:"The chart has 1 X axis displaying {names[0]}. {ranges[0]}",xAxisDescriptionPlural:"The chart has {numAxes} X axes displaying {#each(names, -1) }and {names[-1]}.",yAxisDescriptionSingular:"The chart has 1 Y axis displaying {names[0]}. {ranges[0]}",yAxisDescriptionPlural:"The chart has {numAxes} Y axes displaying {#each(names, -1) }and {names[-1]}.", +timeRangeDays:"Range: {range} days.",timeRangeHours:"Range: {range} hours.",timeRangeMinutes:"Range: {range} minutes.",timeRangeSeconds:"Range: {range} seconds.",rangeFromTo:"Range: {rangeFrom} to {rangeTo}.",rangeCategories:"Range: {numCategories} categories."},exporting:{chartMenuLabel:"Chart menu",menuButtonLabel:"View chart menu",exportRegionLabel:"Chart menu"},series:{summary:{"default":"{name}, series {ix} of {numSeries} with {numPoints} data {#plural(numPoints, points, point)}.",defaultCombination:"{name}, series {ix} of {numSeries} with {numPoints} data {#plural(numPoints, points, point)}.", +line:"{name}, line {ix} of {numSeries} with {numPoints} data {#plural(numPoints, points, point)}.",lineCombination:"{name}, series {ix} of {numSeries}. Line with {numPoints} data {#plural(numPoints, points, point)}.",spline:"{name}, line {ix} of {numSeries} with {numPoints} data {#plural(numPoints, points, point)}.",splineCombination:"{name}, series {ix} of {numSeries}. Line with {numPoints} data {#plural(numPoints, points, point)}.",column:"{name}, bar series {ix} of {numSeries} with {numPoints} {#plural(numPoints, bars, bar)}.", +columnCombination:"{name}, series {ix} of {numSeries}. Bar series with {numPoints} {#plural(numPoints, bars, bar)}.",bar:"{name}, bar series {ix} of {numSeries} with {numPoints} {#plural(numPoints, bars, bar)}.",barCombination:"{name}, series {ix} of {numSeries}. Bar series with {numPoints} {#plural(numPoints, bars, bar)}.",pie:"{name}, pie {ix} of {numSeries} with {numPoints} {#plural(numPoints, slices, slice)}.",pieCombination:"{name}, series {ix} of {numSeries}. Pie with {numPoints} {#plural(numPoints, slices, slice)}.", +scatter:"{name}, scatter plot {ix} of {numSeries} with {numPoints} {#plural(numPoints, points, point)}.",scatterCombination:"{name}, series {ix} of {numSeries}, scatter plot with {numPoints} {#plural(numPoints, points, point)}.",boxplot:"{name}, boxplot {ix} of {numSeries} with {numPoints} {#plural(numPoints, boxes, box)}.",boxplotCombination:"{name}, series {ix} of {numSeries}. Boxplot with {numPoints} {#plural(numPoints, boxes, box)}.",bubble:"{name}, bubble series {ix} of {numSeries} with {numPoints} {#plural(numPoints, bubbles, bubble)}.", +bubbleCombination:"{name}, series {ix} of {numSeries}. Bubble series with {numPoints} {#plural(numPoints, bubbles, bubble)}.",map:"{name}, map {ix} of {numSeries} with {numPoints} {#plural(numPoints, areas, area)}.",mapCombination:"{name}, series {ix} of {numSeries}. Map with {numPoints} {#plural(numPoints, areas, area)}.",mapline:"{name}, line {ix} of {numSeries} with {numPoints} data {#plural(numPoints, points, point)}.",maplineCombination:"{name}, series {ix} of {numSeries}. Line with {numPoints} data {#plural(numPoints, points, point)}.", +mapbubble:"{name}, bubble series {ix} of {numSeries} with {numPoints} {#plural(numPoints, bubbles, bubble)}.",mapbubbleCombination:"{name}, series {ix} of {numSeries}. Bubble series with {numPoints} {#plural(numPoints, bubbles, bubble)}."},description:"{description}",xAxisDescription:"X axis, {name}",yAxisDescription:"Y axis, {name}",nullPointValue:"No value",pointAnnotationsDescription:"{Annotation: #each(annotations). }"}}}});r(a,"Accessibility/Options/DeprecatedOptions.js",[a["Core/Utilities.js"]], +function(a){function h(a,e,d){for(var b,f=0;fh?g.length+h:Math.min(h,g.length),e=0;ea?(b=g[g.length+a],"undefined"===typeof b&&(b=g[0])):(b=g[a],"undefined"===typeof b&&(b=g[g.length-1]))),"undefined"!==typeof b?b:""):"{"+a+"}"}var n=h.format,p=h.pick;a.i18nFormat=function(a,g,h){var k=function(a,b){a=a.slice(b||0);var c=a.indexOf("{"),d=a.indexOf("}");if(-1c)return{statement:a.substring(c+1,d),begin:b+c+1,end:b+d}},e=[],d=0;do{var b=k(a,d);var f=a.substring(d,b&&b.begin- +1);f.length&&e.push({value:f,type:"constant"});b&&e.push({value:b.statement,type:"statement"});d=b?b.end+1:d+1}while(b);e.forEach(function(a){"statement"===a.type&&(a.value=m(a.value,g))});return n(e.reduce(function(a,b){return a+b.value},""),g,h)};a.Chart.prototype.langFormat=function(h,g){h=h.split(".");for(var l=this.options.lang,k=0;k/g, '>') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(/\//g, '/'); + } + /** + * Get an element by ID + * @param {string} id + * @private + * @return {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement|null} + */ + function getElement(id) { + return doc.getElementById(id); + } + /** + * Get a fake mouse event of a given type + * @param {string} type + * @private + * @return {global.MouseEvent} + */ + function getFakeMouseEvent(type) { + if (typeof win.MouseEvent === 'function') { + return new win.MouseEvent(type); + } + // No MouseEvent support, try using initMouseEvent + if (doc.createEvent) { + var evt = doc.createEvent('MouseEvent'); + if (evt.initMouseEvent) { + evt.initMouseEvent(type, true, // Bubble + true, // Cancel + win, // View + type === 'click' ? 1 : 0, // Detail + // Coords + 0, 0, 0, 0, + // Pressed keys + false, false, false, false, 0, // button + null // related target + ); + return evt; + } + } + return { type: type }; + } + /** + * Remove an element from the DOM. + * @private + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} [element] + * @return {void} + */ + function removeElement(element) { + if (element && element.parentNode) { + element.parentNode.removeChild(element); + } + } + /** + * Utility function. Reverses child nodes of a DOM element. + * @private + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} node + * @return {void} + */ + function reverseChildNodes(node) { + var i = node.childNodes.length; + while (i--) { + node.appendChild(node.childNodes[i]); + } + } + /** + * Set attributes on element. Set to null to remove attribute. + * @private + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} el + * @param {Highcharts.HTMLAttributes|Highcharts.SVGAttributes} attrs + * @return {void} + */ + function setElAttrs(el, attrs) { + Object.keys(attrs).forEach(function (attr) { + var val = attrs[attr]; + if (val === null) { + el.removeAttribute(attr); + } + else { + var cleanedVal = escapeStringForHTML('' + val); + el.setAttribute(attr, cleanedVal); + } + }); + } + /** + * Used for aria-label attributes, painting on a canvas will fail if the + * text contains tags. + * @private + * @param {string} str + * @return {string} + */ + function stripHTMLTagsFromString(str) { + return typeof str === 'string' ? + str.replace(/<\/?[^>]+(>|$)/g, '') : str; + } + /** + * Utility function for hiding an element visually, but still keeping it + * available to screen reader users. + * @private + * @param {Highcharts.HTMLDOMElement} element + * @return {void} + */ + function visuallyHideElement(element) { + var hiddenStyle = { + position: 'absolute', + width: '1px', + height: '1px', + overflow: 'hidden', + whiteSpace: 'nowrap', + clip: 'rect(1px, 1px, 1px, 1px)', + marginTop: '-3px', + '-ms-filter': 'progid:DXImageTransform.Microsoft.Alpha(Opacity=1)', + filter: 'alpha(opacity=1)', + opacity: '0.01' + }; + merge(true, element.style, hiddenStyle); + } + var HTMLUtilities = { + addClass: addClass, + escapeStringForHTML: escapeStringForHTML, + getElement: getElement, + getFakeMouseEvent: getFakeMouseEvent, + removeElement: removeElement, + reverseChildNodes: reverseChildNodes, + setElAttrs: setElAttrs, + stripHTMLTagsFromString: stripHTMLTagsFromString, + visuallyHideElement: visuallyHideElement + }; + + return HTMLUtilities; + }); + _registerModule(_modules, 'Accessibility/Utils/ChartUtilities.js', [_modules['Accessibility/Utils/HTMLUtilities.js'], _modules['Core/Utilities.js']], function (HTMLUtilities, U) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Utils for dealing with charts. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var stripHTMLTags = HTMLUtilities.stripHTMLTagsFromString; + var defined = U.defined, + find = U.find, + fireEvent = U.fireEvent; + /* eslint-disable valid-jsdoc */ + /** + * @return {string} + */ + function getChartTitle(chart) { + return stripHTMLTags(chart.options.title.text || + chart.langFormat('accessibility.defaultChartTitle', { chart: chart })); + } + /** + * @param {Highcharts.Axis} axis + * @return {string} + */ + function getAxisDescription(axis) { + return stripHTMLTags(axis && (axis.userOptions && axis.userOptions.accessibility && + axis.userOptions.accessibility.description || + axis.axisTitle && axis.axisTitle.textStr || + axis.options.id || + axis.categories && 'categories' || + axis.dateTime && 'Time' || + 'values')); + } + /** + * Get the DOM element for the first point in the series. + * @private + * @param {Highcharts.Series} series + * The series to get element for. + * @return {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement|undefined} + * The DOM element for the point. + */ + function getSeriesFirstPointElement(series) { + if (series.points && + series.points.length && + series.points[0].graphic) { + return series.points[0].graphic.element; + } + } + /** + * Get the DOM element for the series that we put accessibility info on. + * @private + * @param {Highcharts.Series} series + * The series to get element for. + * @return {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement|undefined} + * The DOM element for the series + */ + function getSeriesA11yElement(series) { + var firstPointEl = getSeriesFirstPointElement(series); + return (firstPointEl && + firstPointEl.parentNode || series.graph && + series.graph.element || series.group && + series.group.element); // Could be tracker series depending on series type + } + /** + * Remove aria-hidden from element. Also unhides parents of the element, and + * hides siblings that are not explicitly unhidden. + * @private + * @param {Highcharts.Chart} chart + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} element + */ + function unhideChartElementFromAT(chart, element) { + element.setAttribute('aria-hidden', false); + if (element === chart.renderTo || !element.parentNode) { + return; + } + // Hide siblings unless their hidden state is already explicitly set + Array.prototype.forEach.call(element.parentNode.childNodes, function (node) { + if (!node.hasAttribute('aria-hidden')) { + node.setAttribute('aria-hidden', true); + } + }); + // Repeat for parent + unhideChartElementFromAT(chart, element.parentNode); + } + /** + * Hide series from screen readers. + * @private + * @param {Highcharts.Series} series + * The series to hide + * @return {void} + */ + function hideSeriesFromAT(series) { + var seriesEl = getSeriesA11yElement(series); + if (seriesEl) { + seriesEl.setAttribute('aria-hidden', true); + } + } + /** + * Get series objects by series name. + * @private + * @param {Highcharts.Chart} chart + * @param {string} name + * @return {Array} + */ + function getSeriesFromName(chart, name) { + if (!name) { + return chart.series; + } + return (chart.series || []).filter(function (s) { + return s.name === name; + }); + } + /** + * Get point in a series from x/y values. + * @private + * @param {Array} series + * @param {number} x + * @param {number} y + * @return {Highcharts.Point|undefined} + */ + function getPointFromXY(series, x, y) { + var i = series.length, + res; + while (i--) { + res = find(series[i].points || [], function (p) { + return p.x === x && p.y === y; + }); + if (res) { + return res; + } + } + } + /** + * Get relative position of point on an x/y axis from 0 to 1. + * @private + * @param {Highcharts.Axis} axis + * @param {Highcharts.Point} point + * @return {number} + */ + function getRelativePointAxisPosition(axis, point) { + if (!defined(axis.dataMin) || !defined(axis.dataMax)) { + return 0; + } + var axisStart = axis.toPixels(axis.dataMin); + var axisEnd = axis.toPixels(axis.dataMax); + // We have to use pixel position because of axis breaks, log axis etc. + var positionProp = axis.coll === 'xAxis' ? 'x' : 'y'; + var pointPos = axis.toPixels(point[positionProp] || 0); + return (pointPos - axisStart) / (axisEnd - axisStart); + } + /** + * Get relative position of point on an x/y axis from 0 to 1. + * @private + * @param {Highcharts.Point} point + */ + function scrollToPoint(point) { + var xAxis = point.series.xAxis; + var yAxis = point.series.yAxis; + var axis = (xAxis === null || xAxis === void 0 ? void 0 : xAxis.scrollbar) ? xAxis : yAxis; + var scrollbar = axis === null || axis === void 0 ? void 0 : axis.scrollbar; + if (scrollbar && defined(scrollbar.to) && defined(scrollbar.from)) { + var range = scrollbar.to - scrollbar.from; + var pos = getRelativePointAxisPosition(axis, + point); + scrollbar.updatePosition(pos - range / 2, pos + range / 2); + fireEvent(scrollbar, 'changed', { + from: scrollbar.from, + to: scrollbar.to, + trigger: 'scrollbar', + DOMEvent: null + }); + } + } + var ChartUtilities = { + getChartTitle: getChartTitle, + getAxisDescription: getAxisDescription, + getPointFromXY: getPointFromXY, + getSeriesFirstPointElement: getSeriesFirstPointElement, + getSeriesFromName: getSeriesFromName, + getSeriesA11yElement: getSeriesA11yElement, + unhideChartElementFromAT: unhideChartElementFromAT, + hideSeriesFromAT: hideSeriesFromAT, + scrollToPoint: scrollToPoint + }; + + return ChartUtilities; + }); + _registerModule(_modules, 'Accessibility/KeyboardNavigationHandler.js', [_modules['Core/Utilities.js']], function (U) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Keyboard navigation handler base class definition + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var find = U.find; + /** + * Options for the keyboard navigation handler. + * + * @interface Highcharts.KeyboardNavigationHandlerOptionsObject + */ /** + * An array containing pairs of an array of keycodes, mapped to a handler + * function. When the keycode is received, the handler is called with the + * keycode as parameter. + * @name Highcharts.KeyboardNavigationHandlerOptionsObject#keyCodeMap + * @type {Array, Function>>} + */ /** + * Function to run on initialization of module. + * @name Highcharts.KeyboardNavigationHandlerOptionsObject#init + * @type {Function} + */ /** + * Function to run before moving to next/prev module. Receives moving direction + * as parameter: +1 for next, -1 for previous. + * @name Highcharts.KeyboardNavigationHandlerOptionsObject#terminate + * @type {Function|undefined} + */ /** + * Function to run to validate module. Should return false if module should not + * run, true otherwise. Receives chart as parameter. + * @name Highcharts.KeyboardNavigationHandlerOptionsObject#validate + * @type {Function|undefined} + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Define a keyboard navigation handler for use with a + * Highcharts.AccessibilityComponent instance. This functions as an abstraction + * layer for keyboard navigation, and defines a map of keyCodes to handler + * functions. + * + * @requires module:modules/accessibility + * + * @sample highcharts/accessibility/custom-component + * Custom accessibility component + * + * @class + * @name Highcharts.KeyboardNavigationHandler + * + * @param {Highcharts.Chart} chart + * The chart this module should act on. + * + * @param {Highcharts.KeyboardNavigationHandlerOptionsObject} options + * Options for the keyboard navigation handler. + */ + function KeyboardNavigationHandler(chart, options) { + this.chart = chart; + this.keyCodeMap = options.keyCodeMap || []; + this.validate = options.validate; + this.init = options.init; + this.terminate = options.terminate; + // Response enum + this.response = { + success: 1, + prev: 2, + next: 3, + noHandler: 4, + fail: 5 // Handler failed + }; + } + KeyboardNavigationHandler.prototype = { + /** + * Find handler function(s) for key code in the keyCodeMap and run it. + * + * @function KeyboardNavigationHandler#run + * @param {global.KeyboardEvent} e + * @return {number} Returns a response code indicating whether the run was + * a success/fail/unhandled, or if we should move to next/prev module. + */ + run: function (e) { + var keyCode = e.which || e.keyCode, + response = this.response.noHandler, + handlerCodeSet = find(this.keyCodeMap, + function (codeSet) { + return codeSet[0].indexOf(keyCode) > -1; + }); + if (handlerCodeSet) { + response = handlerCodeSet[1].call(this, keyCode, e); + } + else if (keyCode === 9) { + // Default tab handler, move to next/prev module + response = this.response[e.shiftKey ? 'prev' : 'next']; + } + return response; + } + }; + + return KeyboardNavigationHandler; + }); + _registerModule(_modules, 'Accessibility/Utils/EventProvider.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Class that can keep track of events added, and clean them up on destroy. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + extend = U.extend; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * @private + * @class + */ + var EventProvider = function () { + this.eventRemovers = []; + }; + extend(EventProvider.prototype, { + /** + * Add an event to an element and keep track of it for later removal. + * Same args as Highcharts.addEvent. + * @private + * @return {Function} + */ + addEvent: function () { + var remover = addEvent.apply(H, + arguments); + this.eventRemovers.push(remover); + return remover; + }, + /** + * Remove all added events. + * @private + * @return {void} + */ + removeAddedEvents: function () { + this.eventRemovers.forEach(function (remover) { + remover(); + }); + this.eventRemovers = []; + } + }); + + return EventProvider; + }); + _registerModule(_modules, 'Accessibility/Utils/DOMElementProvider.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js'], _modules['Accessibility/Utils/HTMLUtilities.js']], function (H, U, HTMLUtilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Class that can keep track of elements added to DOM and clean them up on + * destroy. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var doc = H.win.document; + var extend = U.extend; + var removeElement = HTMLUtilities.removeElement; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * @private + * @class + */ + var DOMElementProvider = function () { + this.elements = []; + }; + extend(DOMElementProvider.prototype, { + /** + * Create an element and keep track of it for later removal. + * Same args as document.createElement + * @private + */ + createElement: function () { + var el = doc.createElement.apply(doc, + arguments); + this.elements.push(el); + return el; + }, + /** + * Destroy all created elements, removing them from the DOM. + * @private + */ + destroyCreatedElements: function () { + this.elements.forEach(function (element) { + removeElement(element); + }); + this.elements = []; + } + }); + + return DOMElementProvider; + }); + _registerModule(_modules, 'Accessibility/AccessibilityComponent.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js'], _modules['Accessibility/Utils/HTMLUtilities.js'], _modules['Accessibility/Utils/ChartUtilities.js'], _modules['Accessibility/Utils/EventProvider.js'], _modules['Accessibility/Utils/DOMElementProvider.js']], function (H, U, HTMLUtilities, ChartUtilities, EventProvider, DOMElementProvider) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Accessibility component class definition + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var win = H.win, + doc = win.document; + var extend = U.extend, + fireEvent = U.fireEvent, + merge = U.merge; + var removeElement = HTMLUtilities.removeElement, + getFakeMouseEvent = HTMLUtilities.getFakeMouseEvent; + var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT; + /* eslint-disable valid-jsdoc */ + /** @lends Highcharts.AccessibilityComponent */ + var functionsToOverrideByDerivedClasses = { + /** + * Called on component initialization. + */ + init: function () { }, + /** + * Get keyboard navigation handler for this component. + * @return {Highcharts.KeyboardNavigationHandler} + */ + getKeyboardNavigation: function () { }, + /** + * Called on updates to the chart, + including options changes. + * Note that this is also called on first render of chart. + */ + onChartUpdate: function () { }, + /** + * Called on every chart render. + */ + onChartRender: function () { }, + /** + * Called when accessibility is disabled or chart is destroyed. + */ + destroy: function () { } + }; + /** + * The AccessibilityComponent base class, representing a part of the chart that + * has accessibility logic connected to it. This class can be inherited from to + * create a custom accessibility component for a chart. + * + * Components should take care to destroy added elements and unregister event + * handlers on destroy. This is handled automatically if using this.addEvent and + * this.createElement. + * + * @sample highcharts/accessibility/custom-component + * Custom accessibility component + * + * @requires module:modules/accessibility + * @class + * @name Highcharts.AccessibilityComponent + */ + function AccessibilityComponent() { } + /** + * @lends Highcharts.AccessibilityComponent + */ + AccessibilityComponent.prototype = { + /** + * Initialize the class + * @private + * @param {Highcharts.Chart} chart + * Chart object + */ + initBase: function (chart) { + this.chart = chart; + this.eventProvider = new EventProvider(); + this.domElementProvider = new DOMElementProvider(); + // Key code enum for common keys + this.keyCodes = { + left: 37, + right: 39, + up: 38, + down: 40, + enter: 13, + space: 32, + esc: 27, + tab: 9 + }; + }, + /** + * Add an event to an element and keep track of it for later removal. + * See EventProvider for details. + * @private + */ + addEvent: function () { + return this.eventProvider.addEvent + .apply(this.eventProvider, arguments); + }, + /** + * Create an element and keep track of it for later removal. + * See DOMElementProvider for details. + * @private + */ + createElement: function () { + return this.domElementProvider.createElement.apply(this.domElementProvider, arguments); + }, + /** + * Fire an event on an element that is either wrapped by Highcharts, + * or a DOM element + * @private + * @param {Highcharts.HTMLElement|Highcharts.HTMLDOMElement| + * Highcharts.SVGDOMElement|Highcharts.SVGElement} el + * @param {Event} eventObject + */ + fireEventOnWrappedOrUnwrappedElement: function (el, eventObject) { + var type = eventObject.type; + if (doc.createEvent && (el.dispatchEvent || el.fireEvent)) { + if (el.dispatchEvent) { + el.dispatchEvent(eventObject); + } + else { + el.fireEvent(type, eventObject); + } + } + else { + fireEvent(el, type, eventObject); + } + }, + /** + * Utility function to attempt to fake a click event on an element. + * @private + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} element + */ + fakeClickEvent: function (element) { + if (element) { + var fakeEventObject = getFakeMouseEvent('click'); + this.fireEventOnWrappedOrUnwrappedElement(element, fakeEventObject); + } + }, + /** + * Add a new proxy group to the proxy container. Creates the proxy container + * if it does not exist. + * @private + * @param {Highcharts.HTMLAttributes} [attrs] + * The attributes to set on the new group div. + * @return {Highcharts.HTMLDOMElement} + * The new proxy group element. + */ + addProxyGroup: function (attrs) { + this.createOrUpdateProxyContainer(); + var groupDiv = this.createElement('div'); + Object.keys(attrs || {}).forEach(function (prop) { + if (attrs[prop] !== null) { + groupDiv.setAttribute(prop, attrs[prop]); + } + }); + this.chart.a11yProxyContainer.appendChild(groupDiv); + return groupDiv; + }, + /** + * Creates and updates DOM position of proxy container + * @private + */ + createOrUpdateProxyContainer: function () { + var chart = this.chart, + rendererSVGEl = chart.renderer.box; + chart.a11yProxyContainer = chart.a11yProxyContainer || + this.createProxyContainerElement(); + if (rendererSVGEl.nextSibling !== chart.a11yProxyContainer) { + chart.container.insertBefore(chart.a11yProxyContainer, rendererSVGEl.nextSibling); + } + }, + /** + * @private + * @return {Highcharts.HTMLDOMElement} element + */ + createProxyContainerElement: function () { + var pc = doc.createElement('div'); + pc.className = 'highcharts-a11y-proxy-container'; + return pc; + }, + /** + * Create an invisible proxy HTML button in the same position as an SVG + * element + * @private + * @param {Highcharts.SVGElement} svgElement + * The wrapped svg el to proxy. + * @param {Highcharts.HTMLDOMElement} parentGroup + * The proxy group element in the proxy container to add this button to. + * @param {Highcharts.SVGAttributes} [attributes] + * Additional attributes to set. + * @param {Highcharts.SVGElement} [posElement] + * Element to use for positioning instead of svgElement. + * @param {Function} [preClickEvent] + * Function to call before click event fires. + * + * @return {Highcharts.HTMLDOMElement} The proxy button. + */ + createProxyButton: function (svgElement, parentGroup, attributes, posElement, preClickEvent) { + var svgEl = svgElement.element, + proxy = this.createElement('button'), + attrs = merge({ + 'aria-label': svgEl.getAttribute('aria-label') + }, + attributes); + Object.keys(attrs).forEach(function (prop) { + if (attrs[prop] !== null) { + proxy.setAttribute(prop, attrs[prop]); + } + }); + proxy.className = 'highcharts-a11y-proxy-button'; + if (preClickEvent) { + this.addEvent(proxy, 'click', preClickEvent); + } + this.setProxyButtonStyle(proxy); + this.updateProxyButtonPosition(proxy, posElement || svgElement); + this.proxyMouseEventsForButton(svgEl, proxy); + // Add to chart div and unhide from screen readers + parentGroup.appendChild(proxy); + if (!attrs['aria-hidden']) { + unhideChartElementFromAT(this.chart, proxy); + } + return proxy; + }, + /** + * Get the position relative to chart container for a wrapped SVG element. + * @private + * @param {Highcharts.SVGElement} element + * The element to calculate position for. + * @return {Highcharts.BBoxObject} + * Object with x and y props for the position. + */ + getElementPosition: function (element) { + var el = element.element, + div = this.chart.renderTo; + if (div && el && el.getBoundingClientRect) { + var rectEl = el.getBoundingClientRect(), + rectDiv = div.getBoundingClientRect(); + return { + x: rectEl.left - rectDiv.left, + y: rectEl.top - rectDiv.top, + width: rectEl.right - rectEl.left, + height: rectEl.bottom - rectEl.top + }; + } + return { x: 0, y: 0, width: 1, height: 1 }; + }, + /** + * @private + * @param {Highcharts.HTMLElement} button The proxy element. + */ + setProxyButtonStyle: function (button) { + merge(true, button.style, { + 'border-width': 0, + 'background-color': 'transparent', + cursor: 'pointer', + outline: 'none', + opacity: 0.001, + filter: 'alpha(opacity=1)', + '-ms-filter': 'progid:DXImageTransform.Microsoft.Alpha(Opacity=1)', + zIndex: 999, + overflow: 'hidden', + padding: 0, + margin: 0, + display: 'block', + position: 'absolute' + }); + }, + /** + * @private + * @param {Highcharts.HTMLElement} proxy The proxy to update position of. + * @param {Highcharts.SVGElement} posElement The element to overlay and take position from. + */ + updateProxyButtonPosition: function (proxy, posElement) { + var bBox = this.getElementPosition(posElement); + merge(true, proxy.style, { + width: (bBox.width || 1) + 'px', + height: (bBox.height || 1) + 'px', + left: (bBox.x || 0) + 'px', + top: (bBox.y || 0) + 'px' + }); + }, + /** + * @private + * @param {Highcharts.HTMLElement|Highcharts.HTMLDOMElement| + * Highcharts.SVGDOMElement|Highcharts.SVGElement} source + * @param {Highcharts.HTMLElement} button + */ + proxyMouseEventsForButton: function (source, button) { + var component = this; + [ + 'click', 'touchstart', 'touchend', 'touchcancel', 'touchmove', + 'mouseover', 'mouseenter', 'mouseleave', 'mouseout' + ].forEach(function (evtType) { + var isTouchEvent = evtType.indexOf('touch') === 0; + component.addEvent(button, evtType, function (e) { + var clonedEvent = isTouchEvent ? + component.cloneTouchEvent(e) : + component.cloneMouseEvent(e); + if (source) { + component.fireEventOnWrappedOrUnwrappedElement(source, clonedEvent); + } + e.stopPropagation(); + e.preventDefault(); + }); + }); + }, + /** + * Utility function to clone a mouse event for re-dispatching. + * @private + * @param {global.MouseEvent} e The event to clone. + * @return {global.MouseEvent} The cloned event + */ + cloneMouseEvent: function (e) { + if (typeof win.MouseEvent === 'function') { + return new win.MouseEvent(e.type, e); + } + // No MouseEvent support, try using initMouseEvent + if (doc.createEvent) { + var evt = doc.createEvent('MouseEvent'); + if (evt.initMouseEvent) { + evt.initMouseEvent(e.type, e.bubbles, // #10561, #12161 + e.cancelable, e.view || win, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget); + return evt; + } + } + return getFakeMouseEvent(e.type); + }, + /** + * Utility function to clone a touch event for re-dispatching. + * @private + * @param {global.TouchEvent} e The event to clone. + * @return {global.TouchEvent} The cloned event + */ + cloneTouchEvent: function (e) { + var touchListToTouchArray = function (l) { + var touchArray = []; + for (var i = 0; i < l.length; ++i) { + var item = l.item(i); + if (item) { + touchArray.push(item); + } + } + return touchArray; + }; + if (typeof win.TouchEvent === 'function') { + var newEvent = new win.TouchEvent(e.type, { + touches: touchListToTouchArray(e.touches), + targetTouches: touchListToTouchArray(e.targetTouches), + changedTouches: touchListToTouchArray(e.changedTouches), + ctrlKey: e.ctrlKey, + shiftKey: e.shiftKey, + altKey: e.altKey, + metaKey: e.metaKey, + bubbles: e.bubbles, + cancelable: e.cancelable, + composed: e.composed, + detail: e.detail, + view: e.view + }); + if (e.defaultPrevented) { + newEvent.preventDefault(); + } + return newEvent; + } + // Fallback to mouse event + var fakeEvt = this.cloneMouseEvent(e); + fakeEvt.touches = e.touches; + fakeEvt.changedTouches = e.changedTouches; + fakeEvt.targetTouches = e.targetTouches; + return fakeEvt; + }, + /** + * Remove traces of the component. + * @private + */ + destroyBase: function () { + removeElement(this.chart.a11yProxyContainer); + this.domElementProvider.destroyCreatedElements(); + this.eventProvider.removeAddedEvents(); + } + }; + extend(AccessibilityComponent.prototype, functionsToOverrideByDerivedClasses); + + return AccessibilityComponent; + }); + _registerModule(_modules, 'Accessibility/KeyboardNavigation.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js'], _modules['Accessibility/Utils/HTMLUtilities.js'], _modules['Accessibility/Utils/EventProvider.js']], function (H, U, HTMLUtilities, EventProvider) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Main keyboard navigation handling. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var doc = H.doc, + win = H.win; + var addEvent = U.addEvent, + fireEvent = U.fireEvent; + var getElement = HTMLUtilities.getElement; + /* eslint-disable valid-jsdoc */ + // Add event listener to document to detect ESC key press and dismiss + // hover/popup content. + addEvent(doc, 'keydown', function (e) { + var keycode = e.which || e.keyCode; + var esc = 27; + if (keycode === esc && H.charts) { + H.charts.forEach(function (chart) { + if (chart && chart.dismissPopupContent) { + chart.dismissPopupContent(); + } + }); + } + }); + /** + * Dismiss popup content in chart, including export menu and tooltip. + */ + H.Chart.prototype.dismissPopupContent = function () { + var chart = this; + fireEvent(this, 'dismissPopupContent', {}, function () { + if (chart.tooltip) { + chart.tooltip.hide(0); + } + chart.hideExportMenu(); + }); + }; + /** + * The KeyboardNavigation class, containing the overall keyboard navigation + * logic for the chart. + * + * @requires module:modules/accessibility + * + * @private + * @class + * @param {Highcharts.Chart} chart + * Chart object + * @param {object} components + * Map of component names to AccessibilityComponent objects. + * @name Highcharts.KeyboardNavigation + */ + function KeyboardNavigation(chart, components) { + this.init(chart, components); + } + KeyboardNavigation.prototype = { + /** + * Initialize the class + * @private + * @param {Highcharts.Chart} chart + * Chart object + * @param {object} components + * Map of component names to AccessibilityComponent objects. + */ + init: function (chart, components) { + var _this = this; + var ep = this.eventProvider = new EventProvider(); + this.chart = chart; + this.components = components; + this.modules = []; + this.currentModuleIx = 0; + // Run an update to get all modules + this.update(); + ep.addEvent(this.tabindexContainer, 'keydown', function (e) { return _this.onKeydown(e); }); + ep.addEvent(this.tabindexContainer, 'focus', function (e) { return _this.onFocus(e); }); + ep.addEvent(doc, 'mouseup', function () { return _this.onMouseUp(); }); + ep.addEvent(chart.renderTo, 'mousedown', function () { + _this.isClickingChart = true; + }); + ep.addEvent(chart.renderTo, 'mouseover', function () { + _this.pointerIsOverChart = true; + }); + ep.addEvent(chart.renderTo, 'mouseout', function () { + _this.pointerIsOverChart = false; + }); + // Init first module + if (this.modules.length) { + this.modules[0].init(1); + } + }, + /** + * Update the modules for the keyboard navigation. + * @param {Array} [order] + * Array specifying the tab order of the components. + */ + update: function (order) { + var a11yOptions = this.chart.options.accessibility, + keyboardOptions = a11yOptions && a11yOptions.keyboardNavigation, + components = this.components; + this.updateContainerTabindex(); + if (keyboardOptions && + keyboardOptions.enabled && + order && + order.length) { + // We (still) have keyboard navigation. Update module list + this.modules = order.reduce(function (modules, componentName) { + var navModules = components[componentName].getKeyboardNavigation(); + return modules.concat(navModules); + }, []); + this.updateExitAnchor(); + } + else { + this.modules = []; + this.currentModuleIx = 0; + this.removeExitAnchor(); + } + }, + /** + * Function to run on container focus + * @private + * @param {global.FocusEvent} e Browser focus event. + */ + onFocus: function (e) { + var _a; + var chart = this.chart; + var focusComesFromChart = (e.relatedTarget && + chart.container.contains(e.relatedTarget)); + // Init keyboard nav if tabbing into chart + if (!this.isClickingChart && !focusComesFromChart) { + (_a = this.modules[0]) === null || _a === void 0 ? void 0 : _a.init(1); + } + }, + /** + * Reset chart navigation state if we click outside the chart and it's + * not already reset. + * @private + */ + onMouseUp: function () { + delete this.isClickingChart; + if (!this.keyboardReset && !this.pointerIsOverChart) { + var chart = this.chart, + curMod = this.modules && + this.modules[this.currentModuleIx || 0]; + if (curMod && curMod.terminate) { + curMod.terminate(); + } + if (chart.focusElement) { + chart.focusElement.removeFocusBorder(); + } + this.currentModuleIx = 0; + this.keyboardReset = true; + } + }, + /** + * Function to run on keydown + * @private + * @param {global.KeyboardEvent} ev Browser keydown event. + */ + onKeydown: function (ev) { + var e = ev || win.event, + preventDefault, + curNavModule = this.modules && this.modules.length && + this.modules[this.currentModuleIx]; + // Used for resetting nav state when clicking outside chart + this.keyboardReset = false; + // If there is a nav module for the current index, run it. + // Otherwise, we are outside of the chart in some direction. + if (curNavModule) { + var response = curNavModule.run(e); + if (response === curNavModule.response.success) { + preventDefault = true; + } + else if (response === curNavModule.response.prev) { + preventDefault = this.prev(); + } + else if (response === curNavModule.response.next) { + preventDefault = this.next(); + } + if (preventDefault) { + e.preventDefault(); + e.stopPropagation(); + } + } + }, + /** + * Go to previous module. + * @private + */ + prev: function () { + return this.move(-1); + }, + /** + * Go to next module. + * @private + */ + next: function () { + return this.move(1); + }, + /** + * Move to prev/next module. + * @private + * @param {number} direction + * Direction to move. +1 for next, -1 for prev. + * @return {boolean} + * True if there was a valid module in direction. + */ + move: function (direction) { + var curModule = this.modules && this.modules[this.currentModuleIx]; + if (curModule && curModule.terminate) { + curModule.terminate(direction); + } + // Remove existing focus border if any + if (this.chart.focusElement) { + this.chart.focusElement.removeFocusBorder(); + } + this.currentModuleIx += direction; + var newModule = this.modules && this.modules[this.currentModuleIx]; + if (newModule) { + if (newModule.validate && !newModule.validate()) { + return this.move(direction); // Invalid module, recurse + } + if (newModule.init) { + newModule.init(direction); // Valid module, init it + return true; + } + } + // No module + this.currentModuleIx = 0; // Reset counter + // Set focus to chart or exit anchor depending on direction + if (direction > 0) { + this.exiting = true; + this.exitAnchor.focus(); + } + else { + this.tabindexContainer.focus(); + } + return false; + }, + /** + * We use an exit anchor to move focus out of chart whenever we want, by + * setting focus to this div and not preventing the default tab action. We + * also use this when users come back into the chart by tabbing back, in + * order to navigate from the end of the chart. + * @private + */ + updateExitAnchor: function () { + var endMarkerId = 'highcharts-end-of-chart-marker-' + this.chart.index, + endMarker = getElement(endMarkerId); + this.removeExitAnchor(); + if (endMarker) { + this.makeElementAnExitAnchor(endMarker); + this.exitAnchor = endMarker; + } + else { + this.createExitAnchor(); + } + }, + /** + * Chart container should have tabindex if navigation is enabled. + * @private + */ + updateContainerTabindex: function () { + var a11yOptions = this.chart.options.accessibility, + keyboardOptions = a11yOptions && a11yOptions.keyboardNavigation, + shouldHaveTabindex = !(keyboardOptions && keyboardOptions.enabled === false), + chart = this.chart, + container = chart.container; + var tabindexContainer; + if (chart.renderTo.hasAttribute('tabindex')) { + container.removeAttribute('tabindex'); + tabindexContainer = chart.renderTo; + } + else { + tabindexContainer = container; + } + this.tabindexContainer = tabindexContainer; + var curTabindex = tabindexContainer.getAttribute('tabindex'); + if (shouldHaveTabindex && !curTabindex) { + tabindexContainer.setAttribute('tabindex', '0'); + } + else if (!shouldHaveTabindex) { + chart.container.removeAttribute('tabindex'); + } + }, + /** + * @private + */ + makeElementAnExitAnchor: function (el) { + var chartTabindex = this.tabindexContainer.getAttribute('tabindex') || 0; + el.setAttribute('class', 'highcharts-exit-anchor'); + el.setAttribute('tabindex', chartTabindex); + el.setAttribute('aria-hidden', false); + // Handle focus + this.addExitAnchorEventsToEl(el); + }, + /** + * Add new exit anchor to the chart. + * + * @private + */ + createExitAnchor: function () { + var chart = this.chart, + exitAnchor = this.exitAnchor = doc.createElement('div'); + chart.renderTo.appendChild(exitAnchor); + this.makeElementAnExitAnchor(exitAnchor); + }, + /** + * @private + */ + removeExitAnchor: function () { + if (this.exitAnchor && this.exitAnchor.parentNode) { + this.exitAnchor.parentNode + .removeChild(this.exitAnchor); + delete this.exitAnchor; + } + }, + /** + * @private + */ + addExitAnchorEventsToEl: function (element) { + var chart = this.chart, + keyboardNavigation = this; + this.eventProvider.addEvent(element, 'focus', function (ev) { + var e = ev || win.event, + curModule, + focusComesFromChart = (e.relatedTarget && + chart.container.contains(e.relatedTarget)), + comingInBackwards = !(focusComesFromChart || keyboardNavigation.exiting); + if (comingInBackwards) { + keyboardNavigation.tabindexContainer.focus(); + e.preventDefault(); + // Move to last valid keyboard nav module + // Note the we don't run it, just set the index + if (keyboardNavigation.modules && + keyboardNavigation.modules.length) { + keyboardNavigation.currentModuleIx = + keyboardNavigation.modules.length - 1; + curModule = keyboardNavigation.modules[keyboardNavigation.currentModuleIx]; + // Validate the module + if (curModule && + curModule.validate && !curModule.validate()) { + // Invalid. Try moving backwards to find next valid. + keyboardNavigation.prev(); + } + else if (curModule) { + // We have a valid module, init it + curModule.init(-1); + } + } + } + else { + // Don't skip the next focus, we only skip once. + keyboardNavigation.exiting = false; + } + }); + }, + /** + * Remove all traces of keyboard navigation. + * @private + */ + destroy: function () { + this.removeExitAnchor(); + this.eventProvider.removeAddedEvents(); + this.chart.container.removeAttribute('tabindex'); + } + }; + + return KeyboardNavigation; + }); + _registerModule(_modules, 'Accessibility/Components/LegendComponent.js', [_modules['Core/Globals.js'], _modules['Core/Legend.js'], _modules['Core/Utilities.js'], _modules['Accessibility/AccessibilityComponent.js'], _modules['Accessibility/KeyboardNavigationHandler.js'], _modules['Accessibility/Utils/HTMLUtilities.js']], function (H, Legend, U, AccessibilityComponent, KeyboardNavigationHandler, HTMLUtilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Accessibility component for chart legend. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + extend = U.extend, + find = U.find, + fireEvent = U.fireEvent; + var stripHTMLTags = HTMLUtilities.stripHTMLTagsFromString, + removeElement = HTMLUtilities.removeElement; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * @private + */ + function scrollLegendToItem(legend, itemIx) { + var itemPage = legend.allItems[itemIx].pageIx, + curPage = legend.currentPage; + if (typeof itemPage !== 'undefined' && itemPage + 1 !== curPage) { + legend.scroll(1 + itemPage - curPage); + } + } + /** + * @private + */ + function shouldDoLegendA11y(chart) { + var items = chart.legend && chart.legend.allItems, + legendA11yOptions = (chart.options.legend.accessibility || {}); + return !!(items && items.length && + !(chart.colorAxis && chart.colorAxis.length) && + legendA11yOptions.enabled !== false); + } + /** + * Highlight legend item by index. + * + * @private + * @function Highcharts.Chart#highlightLegendItem + * + * @param {number} ix + * + * @return {boolean} + */ + H.Chart.prototype.highlightLegendItem = function (ix) { + var items = this.legend.allItems, + oldIx = this.highlightedLegendItemIx; + if (items[ix]) { + if (items[oldIx]) { + fireEvent(items[oldIx].legendGroup.element, 'mouseout'); + } + scrollLegendToItem(this.legend, ix); + this.setFocusToElement(items[ix].legendItem, items[ix].a11yProxyElement); + fireEvent(items[ix].legendGroup.element, 'mouseover'); + return true; + } + return false; + }; + // Keep track of pressed state for legend items + addEvent(Legend, 'afterColorizeItem', function (e) { + var chart = this.chart, + a11yOptions = chart.options.accessibility, + legendItem = e.item; + if (a11yOptions.enabled && legendItem && legendItem.a11yProxyElement) { + legendItem.a11yProxyElement.setAttribute('aria-pressed', e.visible ? 'false' : 'true'); + } + }); + /** + * The LegendComponent class + * + * @private + * @class + * @name Highcharts.LegendComponent + */ + var LegendComponent = function () { }; + LegendComponent.prototype = new AccessibilityComponent(); + extend(LegendComponent.prototype, /** @lends Highcharts.LegendComponent */ { + /** + * Init the component + * @private + */ + init: function () { + var component = this; + this.proxyElementsList = []; + this.recreateProxies(); + // Note: Chart could create legend dynamically, so events can not be + // tied to the component's chart's current legend. + this.addEvent(Legend, 'afterScroll', function () { + if (this.chart === component.chart) { + component.updateProxiesPositions(); + component.updateLegendItemProxyVisibility(); + this.chart.highlightLegendItem(component.highlightedLegendItemIx); + } + }); + this.addEvent(Legend, 'afterPositionItem', function (e) { + if (this.chart === component.chart && this.chart.renderer) { + component.updateProxyPositionForItem(e.item); + } + }); + }, + /** + * @private + */ + updateLegendItemProxyVisibility: function () { + var legend = this.chart.legend, + items = legend.allItems || [], + curPage = legend.currentPage || 1, + clipHeight = legend.clipHeight || 0; + items.forEach(function (item) { + var itemPage = item.pageIx || 0, + y = item._legendItemPos ? item._legendItemPos[1] : 0, + h = item.legendItem ? Math.round(item.legendItem.getBBox().height) : 0, + hide = y + h - legend.pages[itemPage] > clipHeight || itemPage !== curPage - 1; + if (item.a11yProxyElement) { + item.a11yProxyElement.style.visibility = hide ? + 'hidden' : 'visible'; + } + }); + }, + /** + * The legend needs updates on every render, in order to update positioning + * of the proxy overlays. + */ + onChartRender: function () { + if (shouldDoLegendA11y(this.chart)) { + this.updateProxiesPositions(); + } + else { + this.removeProxies(); + } + }, + /** + * @private + */ + updateProxiesPositions: function () { + for (var _i = 0, _a = this.proxyElementsList; _i < _a.length; _i++) { + var _b = _a[_i], + element = _b.element, + posElement = _b.posElement; + this.updateProxyButtonPosition(element, posElement); + } + }, + /** + * @private + */ + updateProxyPositionForItem: function (item) { + var proxyRef = find(this.proxyElementsList, + function (ref) { return ref.item === item; }); + if (proxyRef) { + this.updateProxyButtonPosition(proxyRef.element, proxyRef.posElement); + } + }, + /** + * @private + */ + recreateProxies: function () { + this.removeProxies(); + if (shouldDoLegendA11y(this.chart)) { + this.addLegendProxyGroup(); + this.proxyLegendItems(); + this.updateLegendItemProxyVisibility(); + } + }, + /** + * @private + */ + removeProxies: function () { + removeElement(this.legendProxyGroup); + this.proxyElementsList = []; + }, + /** + * @private + */ + addLegendProxyGroup: function () { + var a11yOptions = this.chart.options.accessibility, groupLabel = this.chart.langFormat('accessibility.legend.legendLabel', {}), groupRole = a11yOptions.landmarkVerbosity === 'all' ? + 'region' : null; + this.legendProxyGroup = this.addProxyGroup({ + 'aria-label': groupLabel, + 'role': groupRole + }); + }, + /** + * @private + */ + proxyLegendItems: function () { + var component = this, + items = (this.chart.legend && + this.chart.legend.allItems || []); + items.forEach(function (item) { + if (item.legendItem && item.legendItem.element) { + component.proxyLegendItem(item); + } + }); + }, + /** + * @private + * @param {Highcharts.BubbleLegend|Point|Highcharts.Series} item + */ + proxyLegendItem: function (item) { + if (!item.legendItem || !item.legendGroup) { + return; + } + var itemLabel = this.chart.langFormat('accessibility.legend.legendItem', { + chart: this.chart, + itemName: stripHTMLTags(item.name) + }), + attribs = { + tabindex: -1, + 'aria-pressed': !item.visible, + 'aria-label': itemLabel + }, + // Considers useHTML + proxyPositioningElement = item.legendGroup.div ? + item.legendItem : item.legendGroup; + item.a11yProxyElement = this.createProxyButton(item.legendItem, this.legendProxyGroup, attribs, proxyPositioningElement); + this.proxyElementsList.push({ + item: item, + element: item.a11yProxyElement, + posElement: proxyPositioningElement + }); + }, + /** + * Get keyboard navigation handler for this component. + * @return {Highcharts.KeyboardNavigationHandler} + */ + getKeyboardNavigation: function () { + var keys = this.keyCodes, + component = this, + chart = this.chart; + return new KeyboardNavigationHandler(chart, { + keyCodeMap: [ + [ + [keys.left, keys.right, keys.up, keys.down], + function (keyCode) { + return component.onKbdArrowKey(this, keyCode); + } + ], + [ + [keys.enter, keys.space], + function () { + return component.onKbdClick(this); + } + ] + ], + validate: function () { + return component.shouldHaveLegendNavigation(); + }, + init: function (direction) { + return component.onKbdNavigationInit(direction); + } + }); + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @param {number} keyCode + * @return {number} + * Response code + */ + onKbdArrowKey: function (keyboardNavigationHandler, keyCode) { + var keys = this.keyCodes, + response = keyboardNavigationHandler.response, + chart = this.chart, + a11yOptions = chart.options.accessibility, + numItems = chart.legend.allItems.length, + direction = (keyCode === keys.left || keyCode === keys.up) ? -1 : 1; + var res = chart.highlightLegendItem(this.highlightedLegendItemIx + direction); + if (res) { + this.highlightedLegendItemIx += direction; + return response.success; + } + if (numItems > 1 && + a11yOptions.keyboardNavigation.wrapAround) { + keyboardNavigationHandler.init(direction); + return response.success; + } + // No wrap, move + return response[direction > 0 ? 'next' : 'prev']; + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @return {number} + * Response code + */ + onKbdClick: function (keyboardNavigationHandler) { + var legendItem = this.chart.legend.allItems[this.highlightedLegendItemIx]; + if (legendItem && legendItem.a11yProxyElement) { + fireEvent(legendItem.a11yProxyElement, 'click'); + } + return keyboardNavigationHandler.response.success; + }, + /** + * @private + * @return {boolean|undefined} + */ + shouldHaveLegendNavigation: function () { + var chart = this.chart, + legendOptions = chart.options.legend || {}, + hasLegend = chart.legend && chart.legend.allItems, + hasColorAxis = chart.colorAxis && chart.colorAxis.length, + legendA11yOptions = (legendOptions.accessibility || {}); + return !!(hasLegend && + chart.legend.display && + !hasColorAxis && + legendA11yOptions.enabled && + legendA11yOptions.keyboardNavigation && + legendA11yOptions.keyboardNavigation.enabled); + }, + /** + * @private + * @param {number} direction + */ + onKbdNavigationInit: function (direction) { + var chart = this.chart, + lastIx = chart.legend.allItems.length - 1, + ixToHighlight = direction > 0 ? 0 : lastIx; + chart.highlightLegendItem(ixToHighlight); + this.highlightedLegendItemIx = ixToHighlight; + } + }); + + return LegendComponent; + }); + _registerModule(_modules, 'Accessibility/Components/MenuComponent.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js'], _modules['Accessibility/AccessibilityComponent.js'], _modules['Accessibility/KeyboardNavigationHandler.js'], _modules['Accessibility/Utils/ChartUtilities.js'], _modules['Accessibility/Utils/HTMLUtilities.js']], function (H, U, AccessibilityComponent, KeyboardNavigationHandler, ChartUtilities, HTMLUtilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Accessibility component for exporting menu. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend; + var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT; + var removeElement = HTMLUtilities.removeElement, + getFakeMouseEvent = HTMLUtilities.getFakeMouseEvent; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Get the wrapped export button element of a chart. + * + * @private + * @param {Highcharts.Chart} chart + * @returns {Highcharts.SVGElement} + */ + function getExportMenuButtonElement(chart) { + return chart.exportSVGElements && chart.exportSVGElements[0]; + } + /** + * Show the export menu and focus the first item (if exists). + * + * @private + * @function Highcharts.Chart#showExportMenu + */ + H.Chart.prototype.showExportMenu = function () { + var exportButton = getExportMenuButtonElement(this); + if (exportButton) { + var el = exportButton.element; + if (el.onclick) { + el.onclick(getFakeMouseEvent('click')); + } + } + }; + /** + * @private + * @function Highcharts.Chart#hideExportMenu + */ + H.Chart.prototype.hideExportMenu = function () { + var chart = this, + exportList = chart.exportDivElements; + if (exportList && chart.exportContextMenu) { + // Reset hover states etc. + exportList.forEach(function (el) { + if (el.className === 'highcharts-menu-item' && el.onmouseout) { + el.onmouseout(getFakeMouseEvent('mouseout')); + } + }); + chart.highlightedExportItemIx = 0; + // Hide the menu div + chart.exportContextMenu.hideMenu(); + // Make sure the chart has focus and can capture keyboard events + chart.container.focus(); + } + }; + /** + * Highlight export menu item by index. + * + * @private + * @function Highcharts.Chart#highlightExportItem + * + * @param {number} ix + * + * @return {boolean} + */ + H.Chart.prototype.highlightExportItem = function (ix) { + var listItem = this.exportDivElements && this.exportDivElements[ix], + curHighlighted = this.exportDivElements && + this.exportDivElements[this.highlightedExportItemIx], + hasSVGFocusSupport; + if (listItem && + listItem.tagName === 'LI' && + !(listItem.children && listItem.children.length)) { + // Test if we have focus support for SVG elements + hasSVGFocusSupport = !!(this.renderTo.getElementsByTagName('g')[0] || {}).focus; + // Only focus if we can set focus back to the elements after + // destroying the menu (#7422) + if (listItem.focus && hasSVGFocusSupport) { + listItem.focus(); + } + if (curHighlighted && curHighlighted.onmouseout) { + curHighlighted.onmouseout(getFakeMouseEvent('mouseout')); + } + if (listItem.onmouseover) { + listItem.onmouseover(getFakeMouseEvent('mouseover')); + } + this.highlightedExportItemIx = ix; + return true; + } + return false; + }; + /** + * Try to highlight the last valid export menu item. + * + * @private + * @function Highcharts.Chart#highlightLastExportItem + * @return {boolean} + */ + H.Chart.prototype.highlightLastExportItem = function () { + var chart = this, + i; + if (chart.exportDivElements) { + i = chart.exportDivElements.length; + while (i--) { + if (chart.highlightExportItem(i)) { + return true; + } + } + } + return false; + }; + /** + * @private + * @param {Highcharts.Chart} chart + */ + function exportingShouldHaveA11y(chart) { + var exportingOpts = chart.options.exporting, + exportButton = getExportMenuButtonElement(chart); + return !!(exportingOpts && + exportingOpts.enabled !== false && + exportingOpts.accessibility && + exportingOpts.accessibility.enabled && + exportButton && + exportButton.element); + } + /** + * The MenuComponent class + * + * @private + * @class + * @name Highcharts.MenuComponent + */ + var MenuComponent = function () { }; + MenuComponent.prototype = new AccessibilityComponent(); + extend(MenuComponent.prototype, /** @lends Highcharts.MenuComponent */ { + /** + * Init the component + */ + init: function () { + var chart = this.chart, + component = this; + this.addEvent(chart, 'exportMenuShown', function () { + component.onMenuShown(); + }); + this.addEvent(chart, 'exportMenuHidden', function () { + component.onMenuHidden(); + }); + }, + /** + * @private + */ + onMenuHidden: function () { + var menu = this.chart.exportContextMenu; + if (menu) { + menu.setAttribute('aria-hidden', 'true'); + } + this.isExportMenuShown = false; + this.setExportButtonExpandedState('false'); + }, + /** + * @private + */ + onMenuShown: function () { + var chart = this.chart, + menu = chart.exportContextMenu; + if (menu) { + this.addAccessibleContextMenuAttribs(); + unhideChartElementFromAT(chart, menu); + } + this.isExportMenuShown = true; + this.setExportButtonExpandedState('true'); + }, + /** + * @private + * @param {string} stateStr + */ + setExportButtonExpandedState: function (stateStr) { + var button = this.exportButtonProxy; + if (button) { + button.setAttribute('aria-expanded', stateStr); + } + }, + /** + * Called on each render of the chart. We need to update positioning of the + * proxy overlay. + */ + onChartRender: function () { + var chart = this.chart, + a11yOptions = chart.options.accessibility; + // Always start with a clean slate + removeElement(this.exportProxyGroup); + // Set screen reader properties on export menu + if (exportingShouldHaveA11y(chart)) { + // Proxy button and group + this.exportProxyGroup = this.addProxyGroup( + // Wrap in a region div if verbosity is high + a11yOptions.landmarkVerbosity === 'all' ? { + 'aria-label': chart.langFormat('accessibility.exporting.exportRegionLabel', { chart: chart }), + 'role': 'region' + } : {}); + var button = getExportMenuButtonElement(this.chart); + this.exportButtonProxy = this.createProxyButton(button, this.exportProxyGroup, { + 'aria-label': chart.langFormat('accessibility.exporting.menuButtonLabel', { chart: chart }), + 'aria-expanded': 'false' + }); + } + }, + /** + * @private + */ + addAccessibleContextMenuAttribs: function () { + var chart = this.chart, + exportList = chart.exportDivElements; + if (exportList && exportList.length) { + // Set tabindex on the menu items to allow focusing by script + // Set role to give screen readers a chance to pick up the contents + exportList.forEach(function (item) { + if (item.tagName === 'LI' && + !(item.children && item.children.length)) { + item.setAttribute('tabindex', -1); + } + else { + item.setAttribute('aria-hidden', 'true'); + } + }); + // Set accessibility properties on parent div + var parentDiv = exportList[0].parentNode; + parentDiv.removeAttribute('aria-hidden'); + parentDiv.setAttribute('aria-label', chart.langFormat('accessibility.exporting.chartMenuLabel', { chart: chart })); + } + }, + /** + * Get keyboard navigation handler for this component. + * @return {Highcharts.KeyboardNavigationHandler} + */ + getKeyboardNavigation: function () { + var keys = this.keyCodes, + chart = this.chart, + component = this; + return new KeyboardNavigationHandler(chart, { + keyCodeMap: [ + // Arrow prev handler + [ + [keys.left, keys.up], + function () { + return component.onKbdPrevious(this); + } + ], + // Arrow next handler + [ + [keys.right, keys.down], + function () { + return component.onKbdNext(this); + } + ], + // Click handler + [ + [keys.enter, keys.space], + function () { + return component.onKbdClick(this); + } + ] + ], + // Only run exporting navigation if exporting support exists and is + // enabled on chart + validate: function () { + return chart.exportChart && + chart.options.exporting.enabled !== false && + chart.options.exporting.accessibility.enabled !== + false; + }, + // Focus export menu button + init: function () { + var exportBtn = component.exportButtonProxy, + exportGroup = chart.exportingGroup; + if (exportGroup && exportBtn) { + chart.setFocusToElement(exportGroup, exportBtn); + } + }, + // Hide the menu + terminate: function () { + chart.hideExportMenu(); + } + }); + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @return {number} + * Response code + */ + onKbdPrevious: function (keyboardNavigationHandler) { + var chart = this.chart, + a11yOptions = chart.options.accessibility, + response = keyboardNavigationHandler.response, + i = chart.highlightedExportItemIx || 0; + // Try to highlight prev item in list. Highlighting e.g. + // separators will fail. + while (i--) { + if (chart.highlightExportItem(i)) { + return response.success; + } + } + // We failed, so wrap around or move to prev module + if (a11yOptions.keyboardNavigation.wrapAround) { + chart.highlightLastExportItem(); + return response.success; + } + return response.prev; + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @return {number} + * Response code + */ + onKbdNext: function (keyboardNavigationHandler) { + var chart = this.chart, + a11yOptions = chart.options.accessibility, + response = keyboardNavigationHandler.response, + i = (chart.highlightedExportItemIx || 0) + 1; + // Try to highlight next item in list. Highlighting e.g. + // separators will fail. + for (; i < chart.exportDivElements.length; ++i) { + if (chart.highlightExportItem(i)) { + return response.success; + } + } + // We failed, so wrap around or move to next module + if (a11yOptions.keyboardNavigation.wrapAround) { + chart.highlightExportItem(0); + return response.success; + } + return response.next; + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @return {number} + * Response code + */ + onKbdClick: function (keyboardNavigationHandler) { + var chart = this.chart, + curHighlightedItem = chart.exportDivElements[chart.highlightedExportItemIx], + exportButtonElement = getExportMenuButtonElement(chart).element; + if (this.isExportMenuShown) { + this.fakeClickEvent(curHighlightedItem); + } + else { + this.fakeClickEvent(exportButtonElement); + chart.highlightExportItem(0); + } + return keyboardNavigationHandler.response.success; + } + }); + + return MenuComponent; + }); + _registerModule(_modules, 'Accessibility/Components/SeriesComponent/SeriesKeyboardNavigation.js', [_modules['Core/Chart/Chart.js'], _modules['Core/Globals.js'], _modules['Core/Series/Point.js'], _modules['Core/Utilities.js'], _modules['Accessibility/KeyboardNavigationHandler.js'], _modules['Accessibility/Utils/EventProvider.js'], _modules['Accessibility/Utils/ChartUtilities.js']], function (Chart, H, Point, U, KeyboardNavigationHandler, EventProvider, ChartUtilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Handle keyboard navigation for series. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var defined = U.defined, + extend = U.extend; + var getPointFromXY = ChartUtilities.getPointFromXY, + getSeriesFromName = ChartUtilities.getSeriesFromName, + scrollToPoint = ChartUtilities.scrollToPoint; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /* + * Set for which series types it makes sense to move to the closest point with + * up/down arrows, and which series types should just move to next series. + */ + H.Series.prototype.keyboardMoveVertical = true; + ['column', 'pie'].forEach(function (type) { + if (H.seriesTypes[type]) { + H.seriesTypes[type].prototype.keyboardMoveVertical = false; + } + }); + /** + * Get the index of a point in a series. This is needed when using e.g. data + * grouping. + * + * @private + * @function getPointIndex + * + * @param {Highcharts.AccessibilityPoint} point + * The point to find index of. + * + * @return {number|undefined} + * The index in the series.points array of the point. + */ + function getPointIndex(point) { + var index = point.index, + points = point.series.points, + i = points.length; + if (points[index] !== point) { + while (i--) { + if (points[i] === point) { + return i; + } + } + } + else { + return index; + } + } + /** + * Determine if series navigation should be skipped + * + * @private + * @function isSkipSeries + * + * @param {Highcharts.Series} series + * + * @return {boolean|number|undefined} + */ + function isSkipSeries(series) { + var a11yOptions = series.chart.options.accessibility, + seriesNavOptions = a11yOptions.keyboardNavigation.seriesNavigation, + seriesA11yOptions = series.options.accessibility || {}, + seriesKbdNavOptions = seriesA11yOptions.keyboardNavigation; + return seriesKbdNavOptions && seriesKbdNavOptions.enabled === false || + seriesA11yOptions.enabled === false || + series.options.enableMouseTracking === false || // #8440 + !series.visible || + // Skip all points in a series where pointNavigationEnabledThreshold is + // reached + (seriesNavOptions.pointNavigationEnabledThreshold && + seriesNavOptions.pointNavigationEnabledThreshold <= + series.points.length); + } + /** + * Determine if navigation for a point should be skipped + * + * @private + * @function isSkipPoint + * + * @param {Highcharts.Point} point + * + * @return {boolean|number|undefined} + */ + function isSkipPoint(point) { + var a11yOptions = point.series.chart.options.accessibility; + return point.isNull && + a11yOptions.keyboardNavigation.seriesNavigation.skipNullPoints || + point.visible === false || + isSkipSeries(point.series); + } + /** + * Get the point in a series that is closest (in pixel distance) to a reference + * point. Optionally supply weight factors for x and y directions. + * + * @private + * @function getClosestPoint + * + * @param {Highcharts.Point} point + * @param {Highcharts.Series} series + * @param {number} [xWeight] + * @param {number} [yWeight] + * + * @return {Highcharts.Point|undefined} + */ + function getClosestPoint(point, series, xWeight, yWeight) { + var minDistance = Infinity, + dPoint, + minIx, + distance, + i = series.points.length, + hasUndefinedPosition = function (point) { + return !(defined(point.plotX) && defined(point.plotY)); + }; + if (hasUndefinedPosition(point)) { + return; + } + while (i--) { + dPoint = series.points[i]; + if (hasUndefinedPosition(dPoint)) { + continue; + } + distance = (point.plotX - dPoint.plotX) * + (point.plotX - dPoint.plotX) * + (xWeight || 1) + + (point.plotY - dPoint.plotY) * + (point.plotY - dPoint.plotY) * + (yWeight || 1); + if (distance < minDistance) { + minDistance = distance; + minIx = i; + } + } + return defined(minIx) ? series.points[minIx] : void 0; + } + /** + * Highlights a point (show tooltip and display hover state). + * + * @private + * @function Highcharts.Point#highlight + * + * @return {Highcharts.Point} + * This highlighted point. + */ + Point.prototype.highlight = function () { + var chart = this.series.chart; + if (!this.isNull) { + this.onMouseOver(); // Show the hover marker and tooltip + } + else { + if (chart.tooltip) { + chart.tooltip.hide(0); + } + // Don't call blur on the element, as it messes up the chart div's focus + } + scrollToPoint(this); + // We focus only after calling onMouseOver because the state change can + // change z-index and mess up the element. + if (this.graphic) { + chart.setFocusToElement(this.graphic); + } + chart.highlightedPoint = this; + return this; + }; + /** + * Function to highlight next/previous point in chart. + * + * @private + * @function Highcharts.Chart#highlightAdjacentPoint + * + * @param {boolean} next + * Flag for the direction. + * + * @return {Highcharts.Point|boolean} + * Returns highlighted point on success, false on failure (no adjacent + * point to highlight in chosen direction). + */ + Chart.prototype.highlightAdjacentPoint = function (next) { + var chart = this, + series = chart.series, + curPoint = chart.highlightedPoint, + curPointIndex = curPoint && getPointIndex(curPoint) || 0, + curPoints = (curPoint && curPoint.series.points), + lastSeries = chart.series && chart.series[chart.series.length - 1], + lastPoint = lastSeries && lastSeries.points && + lastSeries.points[lastSeries.points.length - 1], + newSeries, + newPoint; + // If no points, return false + if (!series[0] || !series[0].points) { + return false; + } + if (!curPoint) { + // No point is highlighted yet. Try first/last point depending on move + // direction + newPoint = next ? series[0].points[0] : lastPoint; + } + else { + // We have a highlighted point. + // Grab next/prev point & series + newSeries = series[curPoint.series.index + (next ? 1 : -1)]; + newPoint = curPoints[curPointIndex + (next ? 1 : -1)]; + if (!newPoint && newSeries) { + // Done with this series, try next one + newPoint = newSeries.points[next ? 0 : newSeries.points.length - 1]; + } + // If there is no adjacent point, we return false + if (!newPoint) { + return false; + } + } + // Recursively skip points + if (isSkipPoint(newPoint)) { + // If we skip this whole series, move to the end of the series before we + // recurse, just to optimize + newSeries = newPoint.series; + if (isSkipSeries(newSeries)) { + chart.highlightedPoint = next ? + newSeries.points[newSeries.points.length - 1] : + newSeries.points[0]; + } + else { + // Otherwise, just move one point + chart.highlightedPoint = newPoint; + } + // Retry + return chart.highlightAdjacentPoint(next); + } + // There is an adjacent point, highlight it + return newPoint.highlight(); + }; + /** + * Highlight first valid point in a series. Returns the point if successfully + * highlighted, otherwise false. If there is a highlighted point in the series, + * use that as starting point. + * + * @private + * @function Highcharts.Series#highlightFirstValidPoint + * + * @return {boolean|Highcharts.Point} + */ + H.Series.prototype.highlightFirstValidPoint = function () { + var curPoint = this.chart.highlightedPoint, + start = (curPoint && curPoint.series) === this ? + getPointIndex(curPoint) : + 0, + points = this.points, + len = points.length; + if (points && len) { + for (var i = start; i < len; ++i) { + if (!isSkipPoint(points[i])) { + return points[i].highlight(); + } + } + for (var j = start; j >= 0; --j) { + if (!isSkipPoint(points[j])) { + return points[j].highlight(); + } + } + } + return false; + }; + /** + * Highlight next/previous series in chart. Returns false if no adjacent series + * in the direction, otherwise returns new highlighted point. + * + * @private + * @function Highcharts.Chart#highlightAdjacentSeries + * + * @param {boolean} down + * + * @return {Highcharts.Point|boolean} + */ + Chart.prototype.highlightAdjacentSeries = function (down) { + var chart = this, + newSeries, + newPoint, + adjacentNewPoint, + curPoint = chart.highlightedPoint, + lastSeries = chart.series && chart.series[chart.series.length - 1], + lastPoint = lastSeries && lastSeries.points && + lastSeries.points[lastSeries.points.length - 1]; + // If no point is highlighted, highlight the first/last point + if (!chart.highlightedPoint) { + newSeries = down ? (chart.series && chart.series[0]) : lastSeries; + newPoint = down ? + (newSeries && newSeries.points && newSeries.points[0]) : lastPoint; + return newPoint ? newPoint.highlight() : false; + } + newSeries = chart.series[curPoint.series.index + (down ? -1 : 1)]; + if (!newSeries) { + return false; + } + // We have a new series in this direction, find the right point + // Weigh xDistance as counting much higher than Y distance + newPoint = getClosestPoint(curPoint, newSeries, 4); + if (!newPoint) { + return false; + } + // New series and point exists, but we might want to skip it + if (isSkipSeries(newSeries)) { + // Skip the series + newPoint.highlight(); + adjacentNewPoint = chart.highlightAdjacentSeries(down); // Try recurse + if (!adjacentNewPoint) { + // Recurse failed + curPoint.highlight(); + return false; + } + // Recurse succeeded + return adjacentNewPoint; + } + // Highlight the new point or any first valid point back or forwards from it + newPoint.highlight(); + return newPoint.series.highlightFirstValidPoint(); + }; + /** + * Highlight the closest point vertically. + * + * @private + * @function Highcharts.Chart#highlightAdjacentPointVertical + * + * @param {boolean} down + * + * @return {Highcharts.Point|boolean} + */ + Chart.prototype.highlightAdjacentPointVertical = function (down) { + var curPoint = this.highlightedPoint, + minDistance = Infinity, + bestPoint; + if (!defined(curPoint.plotX) || !defined(curPoint.plotY)) { + return false; + } + this.series.forEach(function (series) { + if (isSkipSeries(series)) { + return; + } + series.points.forEach(function (point) { + if (!defined(point.plotY) || !defined(point.plotX) || + point === curPoint) { + return; + } + var yDistance = point.plotY - curPoint.plotY, + width = Math.abs(point.plotX - curPoint.plotX), + distance = Math.abs(yDistance) * Math.abs(yDistance) + + width * width * 4; // Weigh horizontal distance highly + // Reverse distance number if axis is reversed + if (series.yAxis && series.yAxis.reversed) { + yDistance *= -1; + } + if (yDistance <= 0 && down || yDistance >= 0 && !down || // Chk dir + distance < 5 || // Points in same spot => infinite loop + isSkipPoint(point)) { + return; + } + if (distance < minDistance) { + minDistance = distance; + bestPoint = point; + } + }); + }); + return bestPoint ? bestPoint.highlight() : false; + }; + /** + * @private + * @param {Highcharts.Chart} chart + * @return {Highcharts.Point|boolean} + */ + function highlightFirstValidPointInChart(chart) { + var res = false; + delete chart.highlightedPoint; + res = chart.series.reduce(function (acc, cur) { + return acc || cur.highlightFirstValidPoint(); + }, false); + return res; + } + /** + * @private + * @param {Highcharts.Chart} chart + * @return {Highcharts.Point|boolean} + */ + function highlightLastValidPointInChart(chart) { + var numSeries = chart.series.length, + i = numSeries, + res = false; + while (i--) { + chart.highlightedPoint = chart.series[i].points[chart.series[i].points.length - 1]; + // Highlight first valid point in the series will also + // look backwards. It always starts from currently + // highlighted point. + res = chart.series[i].highlightFirstValidPoint(); + if (res) { + break; + } + } + return res; + } + /** + * @private + * @param {Highcharts.Chart} chart + */ + function updateChartFocusAfterDrilling(chart) { + highlightFirstValidPointInChart(chart); + if (chart.focusElement) { + chart.focusElement.removeFocusBorder(); + } + } + /** + * @private + * @class + * @name Highcharts.SeriesKeyboardNavigation + */ + function SeriesKeyboardNavigation(chart, keyCodes) { + this.keyCodes = keyCodes; + this.chart = chart; + } + extend(SeriesKeyboardNavigation.prototype, /** @lends Highcharts.SeriesKeyboardNavigation */ { + /** + * Init the keyboard navigation + */ + init: function () { + var keyboardNavigation = this, + chart = this.chart, + e = this.eventProvider = new EventProvider(); + e.addEvent(H.Series, 'destroy', function () { + return keyboardNavigation.onSeriesDestroy(this); + }); + e.addEvent(chart, 'afterDrilldown', function () { + updateChartFocusAfterDrilling(this); + }); + e.addEvent(chart, 'drilldown', function (e) { + var point = e.point, + series = point.series; + keyboardNavigation.lastDrilledDownPoint = { + x: point.x, + y: point.y, + seriesName: series ? series.name : '' + }; + }); + e.addEvent(chart, 'drillupall', function () { + setTimeout(function () { + keyboardNavigation.onDrillupAll(); + }, 10); + }); + }, + onDrillupAll: function () { + // After drillup we want to find the point that was drilled down to and + // highlight it. + var last = this.lastDrilledDownPoint, + chart = this.chart, + series = last && getSeriesFromName(chart, + last.seriesName), + point; + if (last && series && defined(last.x) && defined(last.y)) { + point = getPointFromXY(series, last.x, last.y); + } + // Container focus can be lost on drillup due to deleted elements. + if (chart.container) { + chart.container.focus(); + } + if (point && point.highlight) { + point.highlight(); + } + if (chart.focusElement) { + chart.focusElement.removeFocusBorder(); + } + }, + /** + * @return {Highcharts.KeyboardNavigationHandler} + */ + getKeyboardNavigationHandler: function () { + var keyboardNavigation = this, + keys = this.keyCodes, + chart = this.chart, + inverted = chart.inverted; + return new KeyboardNavigationHandler(chart, { + keyCodeMap: [ + [inverted ? [keys.up, keys.down] : [keys.left, keys.right], function (keyCode) { + return keyboardNavigation.onKbdSideways(this, keyCode); + }], + [inverted ? [keys.left, keys.right] : [keys.up, keys.down], function (keyCode) { + return keyboardNavigation.onKbdVertical(this, keyCode); + }], + [[keys.enter, keys.space], function () { + if (chart.highlightedPoint) { + chart.highlightedPoint.firePointEvent('click'); + } + return this.response.success; + }] + ], + init: function (dir) { + return keyboardNavigation.onHandlerInit(this, dir); + }, + terminate: function () { + return keyboardNavigation.onHandlerTerminate(); + } + }); + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} handler + * @param {number} keyCode + * @return {number} + * response + */ + onKbdSideways: function (handler, keyCode) { + var keys = this.keyCodes, + isNext = keyCode === keys.right || keyCode === keys.down; + return this.attemptHighlightAdjacentPoint(handler, isNext); + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} handler + * @param {number} keyCode + * @return {number} + * response + */ + onKbdVertical: function (handler, keyCode) { + var chart = this.chart, + keys = this.keyCodes, + isNext = keyCode === keys.down || keyCode === keys.right, + navOptions = chart.options.accessibility.keyboardNavigation + .seriesNavigation; + // Handle serialized mode, act like left/right + if (navOptions.mode && navOptions.mode === 'serialize') { + return this.attemptHighlightAdjacentPoint(handler, isNext); + } + // Normal mode, move between series + var highlightMethod = (chart.highlightedPoint && + chart.highlightedPoint.series.keyboardMoveVertical) ? + 'highlightAdjacentPointVertical' : + 'highlightAdjacentSeries'; + chart[highlightMethod](isNext); + return handler.response.success; + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} handler + * @param {number} initDirection + * @return {number} + * response + */ + onHandlerInit: function (handler, initDirection) { + var chart = this.chart; + if (initDirection > 0) { + highlightFirstValidPointInChart(chart); + } + else { + highlightLastValidPointInChart(chart); + } + return handler.response.success; + }, + /** + * @private + */ + onHandlerTerminate: function () { + var _a, + _b; + var chart = this.chart; + var curPoint = chart.highlightedPoint; + (_a = chart.tooltip) === null || _a === void 0 ? void 0 : _a.hide(0); + (_b = curPoint === null || curPoint === void 0 ? void 0 : curPoint.onMouseOut) === null || _b === void 0 ? void 0 : _b.call(curPoint); + delete chart.highlightedPoint; + }, + /** + * Function that attempts to highlight next/prev point. Handles wrap around. + * @private + * @param {Highcharts.KeyboardNavigationHandler} handler + * @param {boolean} directionIsNext + * @return {number} + * response + */ + attemptHighlightAdjacentPoint: function (handler, directionIsNext) { + var chart = this.chart, + wrapAround = chart.options.accessibility.keyboardNavigation + .wrapAround, + highlightSuccessful = chart.highlightAdjacentPoint(directionIsNext); + if (!highlightSuccessful) { + if (wrapAround) { + return handler.init(directionIsNext ? 1 : -1); + } + return handler.response[directionIsNext ? 'next' : 'prev']; + } + return handler.response.success; + }, + /** + * @private + */ + onSeriesDestroy: function (series) { + var chart = this.chart, + currentHighlightedPointDestroyed = chart.highlightedPoint && + chart.highlightedPoint.series === series; + if (currentHighlightedPointDestroyed) { + delete chart.highlightedPoint; + if (chart.focusElement) { + chart.focusElement.removeFocusBorder(); + } + } + }, + /** + * @private + */ + destroy: function () { + this.eventProvider.removeAddedEvents(); + } + }); + + return SeriesKeyboardNavigation; + }); + _registerModule(_modules, 'Accessibility/Components/AnnotationsA11y.js', [_modules['Accessibility/Utils/HTMLUtilities.js']], function (HTMLUtilities) { + /* * + * + * (c) 2009-2019 Øystein Moseng + * + * Annotations accessibility code. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var escapeStringForHTML = HTMLUtilities.escapeStringForHTML, + stripHTMLTagsFromString = HTMLUtilities.stripHTMLTagsFromString; + /** + * Get list of all annotation labels in the chart. + * + * @private + * @param {Highcharts.Chart} chart The chart to get annotation info on. + * @return {Array} The labels, or empty array if none. + */ + function getChartAnnotationLabels(chart) { + var annotations = chart.annotations || []; + return annotations.reduce(function (acc, cur) { + var _a; + if (((_a = cur.options) === null || _a === void 0 ? void 0 : _a.visible) !== false) { + acc = acc.concat(cur.labels); + } + return acc; + }, []); + } + /** + * Get the text of an annotation label. + * + * @private + * @param {object} label The annotation label object + * @return {string} The text in the label. + */ + function getLabelText(label) { + var _a, + _b, + _c, + _d; + var a11yDesc = (_b = (_a = label.options) === null || _a === void 0 ? void 0 : _a.accessibility) === null || _b === void 0 ? void 0 : _b.description; + return a11yDesc ? a11yDesc : ((_d = (_c = label.graphic) === null || _c === void 0 ? void 0 : _c.text) === null || _d === void 0 ? void 0 : _d.textStr) || ''; + } + /** + * Describe an annotation label. + * + * @private + * @param {object} label The annotation label object to describe + * @return {string} The description for the label. + */ + function getAnnotationLabelDescription(label) { + var _a, + _b; + var a11yDesc = (_b = (_a = label.options) === null || _a === void 0 ? void 0 : _a.accessibility) === null || _b === void 0 ? void 0 : _b.description; + if (a11yDesc) { + return a11yDesc; + } + var chart = label.chart; + var labelText = getLabelText(label); + var points = label.points; + var getAriaLabel = function (point) { var _a, + _b; return ((_b = (_a = point === null || point === void 0 ? void 0 : point.graphic) === null || _a === void 0 ? void 0 : _a.element) === null || _b === void 0 ? void 0 : _b.getAttribute('aria-label')) || ''; }; + var getValueDesc = function (point) { + var _a; + var valDesc = ((_a = point === null || point === void 0 ? void 0 : point.accessibility) === null || _a === void 0 ? void 0 : _a.valueDescription) || getAriaLabel(point); + var seriesName = (point === null || point === void 0 ? void 0 : point.series.name) || ''; + return (seriesName ? seriesName + ', ' : '') + 'data point ' + valDesc; + }; + var pointValueDescriptions = points + .filter(function (p) { return !!p.graphic; }) // Filter out mock points + .map(getValueDesc) + .filter(function (desc) { return !!desc; }); // Filter out points we can't describe + var numPoints = pointValueDescriptions.length; + var pointsSelector = numPoints > 1 ? 'MultiplePoints' : numPoints ? 'SinglePoint' : 'NoPoints'; + var langFormatStr = 'accessibility.screenReaderSection.annotations.description' + pointsSelector; + var context = { + annotationText: labelText, + numPoints: numPoints, + annotationPoint: pointValueDescriptions[0], + additionalAnnotationPoints: pointValueDescriptions.slice(1) + }; + return chart.langFormat(langFormatStr, context); + } + /** + * Return array of HTML strings for each annotation label in the chart. + * + * @private + * @param {Highcharts.Chart} chart The chart to get annotation info on. + * @return {Array} Array of strings with HTML content for each annotation label. + */ + function getAnnotationListItems(chart) { + var labels = getChartAnnotationLabels(chart); + return labels.map(function (label) { + var desc = escapeStringForHTML(stripHTMLTagsFromString(getAnnotationLabelDescription(label))); + return desc ? "
  • " + desc + "
  • " : ''; + }); + } + /** + * Return the annotation info for a chart as string. + * + * @private + * @param {Highcharts.Chart} chart The chart to get annotation info on. + * @return {string} String with HTML content or empty string if no annotations. + */ + function getAnnotationsInfoHTML(chart) { + var annotations = chart.annotations; + if (!(annotations && annotations.length)) { + return ''; + } + var annotationItems = getAnnotationListItems(chart); + return "
      " + annotationItems.join(' ') + "
    "; + } + /** + * Return the texts for the annotation(s) connected to a point, or empty array + * if none. + * + * @private + * @param {Highcharts.Point} point The data point to get the annotation info from. + * @return {Array} Annotation texts + */ + function getPointAnnotationTexts(point) { + var labels = getChartAnnotationLabels(point.series.chart); + var pointLabels = labels + .filter(function (label) { return label.points.indexOf(point) > -1; }); + if (!pointLabels.length) { + return []; + } + return pointLabels.map(function (label) { return "" + getLabelText(label); }); + } + var AnnotationsA11y = { + getAnnotationsInfoHTML: getAnnotationsInfoHTML, + getAnnotationLabelDescription: getAnnotationLabelDescription, + getAnnotationListItems: getAnnotationListItems, + getPointAnnotationTexts: getPointAnnotationTexts + }; + + return AnnotationsA11y; + }); + _registerModule(_modules, 'Accessibility/Components/SeriesComponent/SeriesDescriber.js', [_modules['Core/Utilities.js'], _modules['Accessibility/Components/AnnotationsA11y.js'], _modules['Accessibility/Utils/HTMLUtilities.js'], _modules['Accessibility/Utils/ChartUtilities.js'], _modules['Core/Tooltip.js']], function (U, AnnotationsA11y, HTMLUtilities, ChartUtilities, Tooltip) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Place desriptions on a series and its points. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var find = U.find, + format = U.format, + isNumber = U.isNumber, + numberFormat = U.numberFormat, + pick = U.pick, + defined = U.defined; + var getPointAnnotationTexts = AnnotationsA11y.getPointAnnotationTexts; + var escapeStringForHTML = HTMLUtilities.escapeStringForHTML, + reverseChildNodes = HTMLUtilities.reverseChildNodes, + stripHTMLTags = HTMLUtilities.stripHTMLTagsFromString; + var getAxisDescription = ChartUtilities.getAxisDescription, + getSeriesFirstPointElement = ChartUtilities.getSeriesFirstPointElement, + getSeriesA11yElement = ChartUtilities.getSeriesA11yElement, + unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT; + /* eslint-disable valid-jsdoc */ + /** + * @private + */ + function findFirstPointWithGraphic(point) { + var sourcePointIndex = point.index; + if (!point.series || !point.series.data || !defined(sourcePointIndex)) { + return null; + } + return find(point.series.data, function (p) { + return !!(p && + typeof p.index !== 'undefined' && + p.index > sourcePointIndex && + p.graphic && + p.graphic.element); + }) || null; + } + /** + * @private + */ + function shouldAddDummyPoint(point) { + // Note: Sunburst series use isNull for hidden points on drilldown. + // Ignore these. + var isSunburst = point.series && point.series.is('sunburst'), + isNull = point.isNull; + return isNull && !isSunburst; + } + /** + * @private + */ + function makeDummyElement(point, pos) { + var renderer = point.series.chart.renderer, + dummy = renderer.rect(pos.x, + pos.y, 1, 1); + dummy.attr({ + 'class': 'highcharts-a11y-dummy-point', + fill: 'none', + opacity: 0, + 'fill-opacity': 0, + 'stroke-opacity': 0 + }); + return dummy; + } + /** + * @private + * @param {Highcharts.Point} point + * @return {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement|undefined} + */ + function addDummyPointElement(point) { + var series = point.series, + firstPointWithGraphic = findFirstPointWithGraphic(point), + firstGraphic = firstPointWithGraphic && firstPointWithGraphic.graphic, + parentGroup = firstGraphic ? + firstGraphic.parentGroup : + series.graph || series.group, + dummyPos = firstPointWithGraphic ? { + x: pick(point.plotX, + firstPointWithGraphic.plotX, 0), + y: pick(point.plotY, + firstPointWithGraphic.plotY, 0) + } : { + x: pick(point.plotX, 0), + y: pick(point.plotY, 0) + }, + dummyElement = makeDummyElement(point, + dummyPos); + if (parentGroup && parentGroup.element) { + point.graphic = dummyElement; + point.hasDummyGraphic = true; + dummyElement.add(parentGroup); + // Move to correct pos in DOM + parentGroup.element.insertBefore(dummyElement.element, firstGraphic ? firstGraphic.element : null); + return dummyElement.element; + } + } + /** + * @private + * @param {Highcharts.Series} series + * @return {boolean} + */ + function hasMorePointsThanDescriptionThreshold(series) { + var chartA11yOptions = series.chart.options.accessibility, + threshold = (chartA11yOptions.series.pointDescriptionEnabledThreshold); + return !!(threshold !== false && + series.points && + series.points.length >= threshold); + } + /** + * @private + * @param {Highcharts.Series} series + * @return {boolean} + */ + function shouldSetScreenReaderPropsOnPoints(series) { + var seriesA11yOptions = series.options.accessibility || {}; + return !hasMorePointsThanDescriptionThreshold(series) && + !seriesA11yOptions.exposeAsGroupOnly; + } + /** + * @private + * @param {Highcharts.Series} series + * @return {boolean} + */ + function shouldSetKeyboardNavPropsOnPoints(series) { + var chartA11yOptions = series.chart.options.accessibility, + seriesNavOptions = chartA11yOptions.keyboardNavigation.seriesNavigation; + return !!(series.points && (series.points.length < + seriesNavOptions.pointNavigationEnabledThreshold || + seriesNavOptions.pointNavigationEnabledThreshold === false)); + } + /** + * @private + * @param {Highcharts.Series} series + * @return {boolean} + */ + function shouldDescribeSeriesElement(series) { + var chart = series.chart, + chartOptions = chart.options.chart || {}, + chartHas3d = chartOptions.options3d && chartOptions.options3d.enabled, + hasMultipleSeries = chart.series.length > 1, + describeSingleSeriesOption = chart.options.accessibility.series.describeSingleSeries, + exposeAsGroupOnlyOption = (series.options.accessibility || {}).exposeAsGroupOnly, + noDescribe3D = chartHas3d && hasMultipleSeries; + return !noDescribe3D && (hasMultipleSeries || describeSingleSeriesOption || + exposeAsGroupOnlyOption || hasMorePointsThanDescriptionThreshold(series)); + } + /** + * @private + * @param {Highcharts.Point} point + * @param {number} value + * @return {string} + */ + function pointNumberToString(point, value) { + var chart = point.series.chart, + a11yPointOptions = chart.options.accessibility.point || {}, + tooltipOptions = point.series.tooltipOptions || {}, + lang = chart.options.lang; + if (isNumber(value)) { + return numberFormat(value, a11yPointOptions.valueDecimals || + tooltipOptions.valueDecimals || + -1, lang.decimalPoint, lang.accessibility.thousandsSep || lang.thousandsSep); + } + return value; + } + /** + * @private + * @param {Highcharts.Series} series + * @return {string} + */ + function getSeriesDescriptionText(series) { + var seriesA11yOptions = series.options.accessibility || {}, + descOpt = seriesA11yOptions.description; + return descOpt && series.chart.langFormat('accessibility.series.description', { + description: descOpt, + series: series + }) || ''; + } + /** + * @private + * @param {Highcharts.series} series + * @param {string} axisCollection + * @return {string} + */ + function getSeriesAxisDescriptionText(series, axisCollection) { + var axis = series[axisCollection]; + return series.chart.langFormat('accessibility.series.' + axisCollection + 'Description', { + name: getAxisDescription(axis), + series: series + }); + } + /** + * Get accessible time description for a point on a datetime axis. + * + * @private + * @function Highcharts.Point#getTimeDescription + * @param {Highcharts.Point} point + * @return {string|undefined} + * The description as string. + */ + function getPointA11yTimeDescription(point) { + var series = point.series, + chart = series.chart, + a11yOptions = chart.options.accessibility.point || {}, + hasDateXAxis = series.xAxis && series.xAxis.dateTime; + if (hasDateXAxis) { + var tooltipDateFormat = Tooltip.prototype.getXDateFormat.call({ + getDateFormat: Tooltip.prototype.getDateFormat, + chart: chart + }, + point, + chart.options.tooltip, + series.xAxis), + dateFormat = a11yOptions.dateFormatter && + a11yOptions.dateFormatter(point) || + a11yOptions.dateFormat || + tooltipDateFormat; + return chart.time.dateFormat(dateFormat, point.x, void 0); + } + } + /** + * @private + * @param {Highcharts.Point} point + * @return {string} + */ + function getPointXDescription(point) { + var timeDesc = getPointA11yTimeDescription(point), xAxis = point.series.xAxis || {}, pointCategory = xAxis.categories && defined(point.category) && + ('' + point.category).replace('
    ', ' '), canUseId = point.id && point.id.indexOf('highcharts-') < 0, fallback = 'x, ' + point.x; + return point.name || timeDesc || pointCategory || + (canUseId ? point.id : fallback); + } + /** + * @private + * @param {Highcharts.Point} point + * @param {string} prefix + * @param {string} suffix + * @return {string} + */ + function getPointArrayMapValueDescription(point, prefix, suffix) { + var pre = prefix || '', suf = suffix || '', keyToValStr = function (key) { + var num = pointNumberToString(point, pick(point[key], point.options[key])); + return key + ': ' + pre + num + suf; + }, pointArrayMap = point.series.pointArrayMap; + return pointArrayMap.reduce(function (desc, key) { + return desc + (desc.length ? ', ' : '') + keyToValStr(key); + }, ''); + } + /** + * @private + * @param {Highcharts.Point} point + * @return {string} + */ + function getPointValue(point) { + var series = point.series, + a11yPointOpts = series.chart.options.accessibility.point || {}, + tooltipOptions = series.tooltipOptions || {}, + valuePrefix = a11yPointOpts.valuePrefix || + tooltipOptions.valuePrefix || '', + valueSuffix = a11yPointOpts.valueSuffix || + tooltipOptions.valueSuffix || '', + fallbackKey = (typeof point.value !== + 'undefined' ? + 'value' : 'y'), + fallbackDesc = pointNumberToString(point, + point[fallbackKey]); + if (point.isNull) { + return series.chart.langFormat('accessibility.series.nullPointValue', { + point: point + }); + } + if (series.pointArrayMap) { + return getPointArrayMapValueDescription(point, valuePrefix, valueSuffix); + } + return valuePrefix + fallbackDesc + valueSuffix; + } + /** + * Return the description for the annotation(s) connected to a point, or empty + * string if none. + * + * @private + * @param {Highcharts.Point} point The data point to get the annotation info from. + * @return {string} Annotation description + */ + function getPointAnnotationDescription(point) { + var chart = point.series.chart; + var langKey = 'accessibility.series.pointAnnotationsDescription'; + var annotations = getPointAnnotationTexts(point); + var context = { point: point, + annotations: annotations }; + return annotations.length ? chart.langFormat(langKey, context) : ''; + } + /** + * Return string with information about point. + * @private + * @return {string} + */ + function getPointValueDescription(point) { + var series = point.series, chart = series.chart, pointValueDescriptionFormat = chart.options.accessibility + .point.valueDescriptionFormat, showXDescription = pick(series.xAxis && + series.xAxis.options.accessibility && + series.xAxis.options.accessibility.enabled, !chart.angular), xDesc = showXDescription ? getPointXDescription(point) : '', context = { + point: point, + index: defined(point.index) ? (point.index + 1) : '', + xDescription: xDesc, + value: getPointValue(point), + separator: showXDescription ? ', ' : '' + }; + return format(pointValueDescriptionFormat, context, chart); + } + /** + * Return string with information about point. + * @private + * @return {string} + */ + function defaultPointDescriptionFormatter(point) { + var series = point.series, chart = series.chart, valText = getPointValueDescription(point), description = point.options && point.options.accessibility && + point.options.accessibility.description, userDescText = description ? ' ' + description : '', seriesNameText = chart.series.length > 1 && series.name ? + ' ' + series.name + '.' : '', annotationsDesc = getPointAnnotationDescription(point), pointAnnotationsText = annotationsDesc ? ' ' + annotationsDesc : ''; + point.accessibility = point.accessibility || {}; + point.accessibility.valueDescription = valText; + return valText + userDescText + seriesNameText + pointAnnotationsText; + } + /** + * Set a11y props on a point element + * @private + * @param {Highcharts.Point} point + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} pointElement + */ + function setPointScreenReaderAttribs(point, pointElement) { + var series = point.series, + a11yPointOptions = series.chart.options.accessibility.point || {}, + seriesA11yOptions = series.options.accessibility || {}, + label = escapeStringForHTML(stripHTMLTags(seriesA11yOptions.pointDescriptionFormatter && + seriesA11yOptions.pointDescriptionFormatter(point) || + a11yPointOptions.descriptionFormatter && + a11yPointOptions.descriptionFormatter(point) || + defaultPointDescriptionFormatter(point))); + pointElement.setAttribute('role', 'img'); + pointElement.setAttribute('aria-label', label); + } + /** + * Add accessible info to individual point elements of a series + * @private + * @param {Highcharts.Series} series + */ + function describePointsInSeries(series) { + var setScreenReaderProps = shouldSetScreenReaderPropsOnPoints(series), + setKeyboardProps = shouldSetKeyboardNavPropsOnPoints(series); + if (setScreenReaderProps || setKeyboardProps) { + series.points.forEach(function (point) { + var pointEl = point.graphic && point.graphic.element || + shouldAddDummyPoint(point) && addDummyPointElement(point); + if (pointEl) { + // We always set tabindex, as long as we are setting props. + // When setting tabindex, also remove default outline to + // avoid ugly border on click. + pointEl.setAttribute('tabindex', '-1'); + pointEl.style.outline = '0'; + if (setScreenReaderProps) { + setPointScreenReaderAttribs(point, pointEl); + } + else { + pointEl.setAttribute('aria-hidden', true); + } + } + }); + } + } + /** + * Return string with information about series. + * @private + * @return {string} + */ + function defaultSeriesDescriptionFormatter(series) { + var chart = series.chart, + chartTypes = chart.types || [], + description = getSeriesDescriptionText(series), + shouldDescribeAxis = function (coll) { + return chart[coll] && chart[coll].length > 1 && series[coll]; + }, xAxisInfo = getSeriesAxisDescriptionText(series, 'xAxis'), yAxisInfo = getSeriesAxisDescriptionText(series, 'yAxis'), summaryContext = { + name: series.name || '', + ix: series.index + 1, + numSeries: chart.series && chart.series.length, + numPoints: series.points && series.points.length, + series: series + }, combinationSuffix = chartTypes.length > 1 ? 'Combination' : '', summary = chart.langFormat('accessibility.series.summary.' + series.type + combinationSuffix, summaryContext) || chart.langFormat('accessibility.series.summary.default' + combinationSuffix, summaryContext); + return summary + (description ? ' ' + description : '') + (shouldDescribeAxis('yAxis') ? ' ' + yAxisInfo : '') + (shouldDescribeAxis('xAxis') ? ' ' + xAxisInfo : ''); + } + /** + * Set a11y props on a series element + * @private + * @param {Highcharts.Series} series + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} seriesElement + */ + function describeSeriesElement(series, seriesElement) { + var seriesA11yOptions = series.options.accessibility || {}, + a11yOptions = series.chart.options.accessibility, + landmarkVerbosity = a11yOptions.landmarkVerbosity; + // Handle role attribute + if (seriesA11yOptions.exposeAsGroupOnly) { + seriesElement.setAttribute('role', 'img'); + } + else if (landmarkVerbosity === 'all') { + seriesElement.setAttribute('role', 'region'); + } /* else do not add role */ + seriesElement.setAttribute('tabindex', '-1'); + seriesElement.style.outline = '0'; // Don't show browser outline on click, despite tabindex + seriesElement.setAttribute('aria-label', escapeStringForHTML(stripHTMLTags(a11yOptions.series.descriptionFormatter && + a11yOptions.series.descriptionFormatter(series) || + defaultSeriesDescriptionFormatter(series)))); + } + /** + * Put accessible info on series and points of a series. + * @param {Highcharts.Series} series The series to add info on. + */ + function describeSeries(series) { + var chart = series.chart, + firstPointEl = getSeriesFirstPointElement(series), + seriesEl = getSeriesA11yElement(series), + is3d = chart.is3d && chart.is3d(); + if (seriesEl) { + // For some series types the order of elements do not match the + // order of points in series. In that case we have to reverse them + // in order for AT to read them out in an understandable order. + // Due to z-index issues we can not do this for 3D charts. + if (seriesEl.lastChild === firstPointEl && !is3d) { + reverseChildNodes(seriesEl); + } + describePointsInSeries(series); + unhideChartElementFromAT(chart, seriesEl); + if (shouldDescribeSeriesElement(series)) { + describeSeriesElement(series, seriesEl); + } + else { + seriesEl.setAttribute('aria-label', ''); + } + } + } + var SeriesDescriber = { + describeSeries: describeSeries, + defaultPointDescriptionFormatter: defaultPointDescriptionFormatter, + defaultSeriesDescriptionFormatter: defaultSeriesDescriptionFormatter, + getPointA11yTimeDescription: getPointA11yTimeDescription, + getPointXDescription: getPointXDescription, + getPointValue: getPointValue, + getPointValueDescription: getPointValueDescription + }; + + return SeriesDescriber; + }); + _registerModule(_modules, 'Accessibility/Utils/Announcer.js', [_modules['Core/Globals.js'], _modules['Accessibility/Utils/DOMElementProvider.js'], _modules['Accessibility/Utils/HTMLUtilities.js']], function (H, DOMElementProvider, HTMLUtilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Create announcer to speak messages to screen readers and other AT. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var visuallyHideElement = HTMLUtilities.visuallyHideElement; + var Announcer = /** @class */ (function () { + function Announcer(chart, type) { + this.chart = chart; + this.domElementProvider = new DOMElementProvider(); + this.announceRegion = this.addAnnounceRegion(type); + } + Announcer.prototype.destroy = function () { + this.domElementProvider.destroyCreatedElements(); + }; + Announcer.prototype.announce = function (message) { + var _this = this; + this.announceRegion.innerHTML = message; + // Delete contents after a little while to avoid user finding the live + // region in the DOM. + if (this.clearAnnouncementRegionTimer) { + clearTimeout(this.clearAnnouncementRegionTimer); + } + this.clearAnnouncementRegionTimer = setTimeout(function () { + _this.announceRegion.innerHTML = ''; + delete _this.clearAnnouncementRegionTimer; + }, 1000); + }; + Announcer.prototype.addAnnounceRegion = function (type) { + var chartContainer = this.chart.renderTo; + var div = this.domElementProvider.createElement('div'); + div.setAttribute('aria-hidden', false); + div.setAttribute('aria-live', type); + visuallyHideElement(div); + chartContainer.insertBefore(div, chartContainer.firstChild); + return div; + }; + return Announcer; + }()); + H.Announcer = Announcer; + + return Announcer; + }); + _registerModule(_modules, 'Accessibility/Components/SeriesComponent/NewDataAnnouncer.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js'], _modules['Accessibility/Utils/ChartUtilities.js'], _modules['Accessibility/Components/SeriesComponent/SeriesDescriber.js'], _modules['Accessibility/Utils/Announcer.js'], _modules['Accessibility/Utils/EventProvider.js']], function (H, U, ChartUtilities, SeriesDescriber, Announcer, EventProvider) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Handle announcing new data for a chart. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend, + defined = U.defined; + var getChartTitle = ChartUtilities.getChartTitle; + var defaultPointDescriptionFormatter = SeriesDescriber + .defaultPointDescriptionFormatter, + defaultSeriesDescriptionFormatter = SeriesDescriber + .defaultSeriesDescriptionFormatter; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * @private + */ + function chartHasAnnounceEnabled(chart) { + return !!chart.options.accessibility.announceNewData.enabled; + } + /** + * @private + */ + function findPointInDataArray(point) { + var candidates = point.series.data.filter(function (candidate) { + return point.x === candidate.x && point.y === candidate.y; + }); + return candidates.length === 1 ? candidates[0] : point; + } + /** + * Get array of unique series from two arrays + * @private + */ + function getUniqueSeries(arrayA, arrayB) { + var uniqueSeries = (arrayA || []).concat(arrayB || []) + .reduce(function (acc, + cur) { + acc[cur.name + cur.index] = cur; + return acc; + }, {}); + return Object.keys(uniqueSeries).map(function (ix) { + return uniqueSeries[ix]; + }); + } + /** + * @private + * @class + */ + var NewDataAnnouncer = function (chart) { + this.chart = chart; + }; + extend(NewDataAnnouncer.prototype, { + /** + * Initialize the new data announcer. + * @private + */ + init: function () { + var chart = this.chart; + var announceOptions = chart.options.accessibility.announceNewData; + var announceType = announceOptions.interruptUser ? 'assertive' : 'polite'; + this.lastAnnouncementTime = 0; + this.dirty = { + allSeries: {} + }; + this.eventProvider = new EventProvider(); + this.announcer = new Announcer(chart, announceType); + this.addEventListeners(); + }, + /** + * Remove traces of announcer. + * @private + */ + destroy: function () { + this.eventProvider.removeAddedEvents(); + this.announcer.destroy(); + }, + /** + * Add event listeners for the announcer + * @private + */ + addEventListeners: function () { + var announcer = this, + chart = this.chart, + e = this.eventProvider; + e.addEvent(chart, 'afterDrilldown', function () { + announcer.lastAnnouncementTime = 0; + }); + e.addEvent(H.Series, 'updatedData', function () { + announcer.onSeriesUpdatedData(this); + }); + e.addEvent(chart, 'afterAddSeries', function (e) { + announcer.onSeriesAdded(e.series); + }); + e.addEvent(H.Series, 'addPoint', function (e) { + announcer.onPointAdded(e.point); + }); + e.addEvent(chart, 'redraw', function () { + announcer.announceDirtyData(); + }); + }, + /** + * On new data in the series, make sure we add it to the dirty list. + * @private + * @param {Highcharts.Series} series + */ + onSeriesUpdatedData: function (series) { + var chart = this.chart; + if (series.chart === chart && chartHasAnnounceEnabled(chart)) { + this.dirty.hasDirty = true; + this.dirty.allSeries[series.name + series.index] = series; + } + }, + /** + * On new data series added, update dirty list. + * @private + * @param {Highcharts.Series} series + */ + onSeriesAdded: function (series) { + if (chartHasAnnounceEnabled(this.chart)) { + this.dirty.hasDirty = true; + this.dirty.allSeries[series.name + series.index] = series; + // Add it to newSeries storage unless we already have one + this.dirty.newSeries = defined(this.dirty.newSeries) ? + void 0 : series; + } + }, + /** + * On new point added, update dirty list. + * @private + * @param {Highcharts.Point} point + */ + onPointAdded: function (point) { + var chart = point.series.chart; + if (this.chart === chart && chartHasAnnounceEnabled(chart)) { + // Add it to newPoint storage unless we already have one + this.dirty.newPoint = defined(this.dirty.newPoint) ? + void 0 : point; + } + }, + /** + * Gather what we know and announce the data to user. + * @private + */ + announceDirtyData: function () { + var chart = this.chart, + announcer = this; + if (chart.options.accessibility.announceNewData && + this.dirty.hasDirty) { + var newPoint = this.dirty.newPoint; + // If we have a single new point, see if we can find it in the + // data array. Otherwise we can only pass through options to + // the description builder, and it is a bit sparse in info. + if (newPoint) { + newPoint = findPointInDataArray(newPoint); + } + this.queueAnnouncement(Object.keys(this.dirty.allSeries).map(function (ix) { + return announcer.dirty.allSeries[ix]; + }), this.dirty.newSeries, newPoint); + // Reset + this.dirty = { + allSeries: {} + }; + } + }, + /** + * Announce to user that there is new data. + * @private + * @param {Array} dirtySeries + * Array of series with new data. + * @param {Highcharts.Series} [newSeries] + * If a single new series was added, a reference to this series. + * @param {Highcharts.Point} [newPoint] + * If a single point was added, a reference to this point. + */ + queueAnnouncement: function (dirtySeries, newSeries, newPoint) { + var _this = this; + var chart = this.chart; + var annOptions = chart.options.accessibility.announceNewData; + if (annOptions.enabled) { + var now = +new Date(); + var dTime = now - this.lastAnnouncementTime; + var time = Math.max(0, + annOptions.minAnnounceInterval - dTime); + // Add series from previously queued announcement. + var allSeries = getUniqueSeries(this.queuedAnnouncement && this.queuedAnnouncement.series, + dirtySeries); + // Build message and announce + var message = this.buildAnnouncementMessage(allSeries, + newSeries, + newPoint); + if (message) { + // Is there already one queued? + if (this.queuedAnnouncement) { + clearTimeout(this.queuedAnnouncementTimer); + } + // Build the announcement + this.queuedAnnouncement = { + time: now, + message: message, + series: allSeries + }; + // Queue the announcement + this.queuedAnnouncementTimer = setTimeout(function () { + if (_this && _this.announcer) { + _this.lastAnnouncementTime = +new Date(); + _this.announcer.announce(_this.queuedAnnouncement.message); + delete _this.queuedAnnouncement; + delete _this.queuedAnnouncementTimer; + } + }, time); + } + } + }, + /** + * Get announcement message for new data. + * @private + * @param {Array} dirtySeries + * Array of series with new data. + * @param {Highcharts.Series} [newSeries] + * If a single new series was added, a reference to this series. + * @param {Highcharts.Point} [newPoint] + * If a single point was added, a reference to this point. + * + * @return {string|null} + * The announcement message to give to user. + */ + buildAnnouncementMessage: function (dirtySeries, newSeries, newPoint) { + var chart = this.chart, + annOptions = chart.options.accessibility.announceNewData; + // User supplied formatter? + if (annOptions.announcementFormatter) { + var formatterRes = annOptions.announcementFormatter(dirtySeries, + newSeries, + newPoint); + if (formatterRes !== false) { + return formatterRes.length ? formatterRes : null; + } + } + // Default formatter - use lang options + var multiple = H.charts && H.charts.length > 1 ? 'Multiple' : 'Single', langKey = newSeries ? 'newSeriesAnnounce' + multiple : + newPoint ? 'newPointAnnounce' + multiple : 'newDataAnnounce', chartTitle = getChartTitle(chart); + return chart.langFormat('accessibility.announceNewData.' + langKey, { + chartTitle: chartTitle, + seriesDesc: newSeries ? + defaultSeriesDescriptionFormatter(newSeries) : + null, + pointDesc: newPoint ? + defaultPointDescriptionFormatter(newPoint) : + null, + point: newPoint, + series: newSeries + }); + } + }); + + return NewDataAnnouncer; + }); + _registerModule(_modules, 'Accessibility/Components/SeriesComponent/ForcedMarkers.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Handle forcing series markers. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + merge = U.merge; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * @private + */ + function isWithinDescriptionThreshold(series) { + var a11yOptions = series.chart.options.accessibility; + return series.points.length < + a11yOptions.series.pointDescriptionEnabledThreshold || + a11yOptions.series.pointDescriptionEnabledThreshold === false; + } + /** + * @private + */ + function shouldForceMarkers(series) { + var chart = series.chart, + chartA11yEnabled = chart.options.accessibility.enabled, + seriesA11yEnabled = (series.options.accessibility && + series.options.accessibility.enabled) !== false; + return chartA11yEnabled && seriesA11yEnabled && isWithinDescriptionThreshold(series); + } + /** + * @private + */ + function hasIndividualPointMarkerOptions(series) { + return !!(series._hasPointMarkers && series.points && series.points.length); + } + /** + * @private + */ + function unforceSeriesMarkerOptions(series) { + var resetMarkerOptions = series.resetA11yMarkerOptions; + if (resetMarkerOptions) { + merge(true, series.options, { + marker: { + enabled: resetMarkerOptions.enabled, + states: { + normal: { + opacity: resetMarkerOptions.states && + resetMarkerOptions.states.normal && + resetMarkerOptions.states.normal.opacity + } + } + } + }); + } + } + /** + * @private + */ + function forceZeroOpacityMarkerOptions(options) { + merge(true, options, { + marker: { + enabled: true, + states: { + normal: { + opacity: 0 + } + } + } + }); + } + /** + * @private + */ + function getPointMarkerOpacity(pointOptions) { + return pointOptions.marker.states && + pointOptions.marker.states.normal && + pointOptions.marker.states.normal.opacity || 1; + } + /** + * @private + */ + function unforcePointMarkerOptions(pointOptions) { + merge(true, pointOptions.marker, { + states: { + normal: { + opacity: getPointMarkerOpacity(pointOptions) + } + } + }); + } + /** + * @private + */ + function handleForcePointMarkers(series) { + var i = series.points.length; + while (i--) { + var point = series.points[i]; + var pointOptions = point.options; + delete point.hasForcedA11yMarker; + if (pointOptions.marker) { + if (pointOptions.marker.enabled) { + unforcePointMarkerOptions(pointOptions); + point.hasForcedA11yMarker = false; + } + else { + forceZeroOpacityMarkerOptions(pointOptions); + point.hasForcedA11yMarker = true; + } + } + } + } + /** + * @private + */ + function addForceMarkersEvents() { + /** + * Keep track of forcing markers. + * @private + */ + addEvent(H.Series, 'render', function () { + var series = this, + options = series.options; + if (shouldForceMarkers(series)) { + if (options.marker && options.marker.enabled === false) { + series.a11yMarkersForced = true; + forceZeroOpacityMarkerOptions(series.options); + } + if (hasIndividualPointMarkerOptions(series)) { + handleForcePointMarkers(series); + } + } + else if (series.a11yMarkersForced) { + delete series.a11yMarkersForced; + unforceSeriesMarkerOptions(series); + } + }); + /** + * Keep track of options to reset markers to if no longer forced. + * @private + */ + addEvent(H.Series, 'afterSetOptions', function (e) { + this.resetA11yMarkerOptions = merge(e.options.marker || {}, this.userOptions.marker || {}); + }); + /** + * Process marker graphics after render + * @private + */ + addEvent(H.Series, 'afterRender', function () { + var series = this; + // For styled mode the rendered graphic does not reflect the style + // options, and we need to add/remove classes to achieve the same. + if (series.chart.styledMode) { + if (series.markerGroup) { + series.markerGroup[series.a11yMarkersForced ? 'addClass' : 'removeClass']('highcharts-a11y-markers-hidden'); + } + // Do we need to handle individual points? + if (hasIndividualPointMarkerOptions(series)) { + series.points.forEach(function (point) { + if (point.graphic) { + point.graphic[point.hasForcedA11yMarker ? 'addClass' : 'removeClass']('highcharts-a11y-marker-hidden'); + point.graphic[point.hasForcedA11yMarker === false ? 'addClass' : 'removeClass']('highcharts-a11y-marker-visible'); + } + }); + } + } + }); + } + + return addForceMarkersEvents; + }); + _registerModule(_modules, 'Accessibility/Components/SeriesComponent/SeriesComponent.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js'], _modules['Accessibility/AccessibilityComponent.js'], _modules['Accessibility/Components/SeriesComponent/SeriesKeyboardNavigation.js'], _modules['Accessibility/Components/SeriesComponent/NewDataAnnouncer.js'], _modules['Accessibility/Components/SeriesComponent/ForcedMarkers.js'], _modules['Accessibility/Utils/ChartUtilities.js'], _modules['Accessibility/Components/SeriesComponent/SeriesDescriber.js'], _modules['Core/Tooltip.js']], function (H, U, AccessibilityComponent, SeriesKeyboardNavigation, NewDataAnnouncer, addForceMarkersEvents, ChartUtilities, SeriesDescriber, Tooltip) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Accessibility component for series and points. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend; + var hideSeriesFromAT = ChartUtilities.hideSeriesFromAT; + var describeSeries = SeriesDescriber.describeSeries; + // Expose functionality to users + H.SeriesAccessibilityDescriber = SeriesDescriber; + // Handle forcing markers + addForceMarkersEvents(); + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The SeriesComponent class + * + * @private + * @class + * @name Highcharts.SeriesComponent + */ + var SeriesComponent = function () { }; + SeriesComponent.prototype = new AccessibilityComponent(); + extend(SeriesComponent.prototype, /** @lends Highcharts.SeriesComponent */ { + /** + * Init the component. + */ + init: function () { + this.newDataAnnouncer = new NewDataAnnouncer(this.chart); + this.newDataAnnouncer.init(); + this.keyboardNavigation = new SeriesKeyboardNavigation(this.chart, this.keyCodes); + this.keyboardNavigation.init(); + this.hideTooltipFromATWhenShown(); + this.hideSeriesLabelsFromATWhenShown(); + }, + /** + * @private + */ + hideTooltipFromATWhenShown: function () { + var component = this; + this.addEvent(Tooltip, 'refresh', function () { + if (this.chart === component.chart && + this.label && + this.label.element) { + this.label.element.setAttribute('aria-hidden', true); + } + }); + }, + /** + * @private + */ + hideSeriesLabelsFromATWhenShown: function () { + this.addEvent(this.chart, 'afterDrawSeriesLabels', function () { + this.series.forEach(function (series) { + if (series.labelBySeries) { + series.labelBySeries.attr('aria-hidden', true); + } + }); + }); + }, + /** + * Called on chart render. It is necessary to do this for render in case + * markers change on zoom/pixel density. + */ + onChartRender: function () { + var chart = this.chart; + chart.series.forEach(function (series) { + var shouldDescribeSeries = (series.options.accessibility && + series.options.accessibility.enabled) !== false && + series.visible; + if (shouldDescribeSeries) { + describeSeries(series); + } + else { + hideSeriesFromAT(series); + } + }); + }, + /** + * Get keyboard navigation handler for this component. + * @return {Highcharts.KeyboardNavigationHandler} + */ + getKeyboardNavigation: function () { + return this.keyboardNavigation.getKeyboardNavigationHandler(); + }, + /** + * Remove traces + */ + destroy: function () { + this.newDataAnnouncer.destroy(); + this.keyboardNavigation.destroy(); + } + }); + + return SeriesComponent; + }); + _registerModule(_modules, 'Accessibility/Components/ZoomComponent.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js'], _modules['Accessibility/AccessibilityComponent.js'], _modules['Accessibility/KeyboardNavigationHandler.js'], _modules['Accessibility/Utils/ChartUtilities.js'], _modules['Accessibility/Utils/HTMLUtilities.js']], function (H, U, AccessibilityComponent, KeyboardNavigationHandler, ChartUtilities, HTMLUtilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Accessibility component for chart zoom. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend, + pick = U.pick; + var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT; + var setElAttrs = HTMLUtilities.setElAttrs, + removeElement = HTMLUtilities.removeElement; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * @private + */ + function chartHasMapZoom(chart) { + return !!(chart.mapZoom && + chart.mapNavButtons && + chart.mapNavButtons.length); + } + /** + * Pan along axis in a direction (1 or -1), optionally with a defined + * granularity (number of steps it takes to walk across current view) + * + * @private + * @function Highcharts.Axis#panStep + * + * @param {number} direction + * @param {number} [granularity] + */ + H.Axis.prototype.panStep = function (direction, granularity) { + var gran = granularity || 3, + extremes = this.getExtremes(), + step = (extremes.max - extremes.min) / gran * direction, + newMax = extremes.max + step, + newMin = extremes.min + step, + size = newMax - newMin; + if (direction < 0 && newMin < extremes.dataMin) { + newMin = extremes.dataMin; + newMax = newMin + size; + } + else if (direction > 0 && newMax > extremes.dataMax) { + newMax = extremes.dataMax; + newMin = newMax - size; + } + this.setExtremes(newMin, newMax); + }; + /** + * The ZoomComponent class + * + * @private + * @class + * @name Highcharts.ZoomComponent + */ + var ZoomComponent = function () { }; + ZoomComponent.prototype = new AccessibilityComponent(); + extend(ZoomComponent.prototype, /** @lends Highcharts.ZoomComponent */ { + /** + * Initialize the component + */ + init: function () { + var component = this, + chart = this.chart; + [ + 'afterShowResetZoom', 'afterDrilldown', 'drillupall' + ].forEach(function (eventType) { + component.addEvent(chart, eventType, function () { + component.updateProxyOverlays(); + }); + }); + }, + /** + * Called when chart is updated + */ + onChartUpdate: function () { + var chart = this.chart, + component = this; + // Make map zoom buttons accessible + if (chart.mapNavButtons) { + chart.mapNavButtons.forEach(function (button, i) { + unhideChartElementFromAT(chart, button.element); + component.setMapNavButtonAttrs(button.element, 'accessibility.zoom.mapZoom' + (i ? 'Out' : 'In')); + }); + } + }, + /** + * @private + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} button + * @param {string} labelFormatKey + */ + setMapNavButtonAttrs: function (button, labelFormatKey) { + var chart = this.chart, + label = chart.langFormat(labelFormatKey, { chart: chart }); + setElAttrs(button, { + tabindex: -1, + role: 'button', + 'aria-label': label + }); + }, + /** + * Update the proxy overlays on every new render to ensure positions are + * correct. + */ + onChartRender: function () { + this.updateProxyOverlays(); + }, + /** + * Update proxy overlays, recreating the buttons. + */ + updateProxyOverlays: function () { + var chart = this.chart; + // Always start with a clean slate + removeElement(this.drillUpProxyGroup); + removeElement(this.resetZoomProxyGroup); + if (chart.resetZoomButton) { + this.recreateProxyButtonAndGroup(chart.resetZoomButton, 'resetZoomProxyButton', 'resetZoomProxyGroup', chart.langFormat('accessibility.zoom.resetZoomButton', { chart: chart })); + } + if (chart.drillUpButton) { + this.recreateProxyButtonAndGroup(chart.drillUpButton, 'drillUpProxyButton', 'drillUpProxyGroup', chart.langFormat('accessibility.drillUpButton', { + chart: chart, + buttonText: chart.getDrilldownBackText() + })); + } + }, + /** + * @private + * @param {Highcharts.SVGElement} buttonEl + * @param {string} buttonProp + * @param {string} groupProp + * @param {string} label + */ + recreateProxyButtonAndGroup: function (buttonEl, buttonProp, groupProp, label) { + removeElement(this[groupProp]); + this[groupProp] = this.addProxyGroup(); + this[buttonProp] = this.createProxyButton(buttonEl, this[groupProp], { 'aria-label': label, tabindex: -1 }); + }, + /** + * Get keyboard navigation handler for map zoom. + * @private + * @return {Highcharts.KeyboardNavigationHandler} The module object + */ + getMapZoomNavigation: function () { + var keys = this.keyCodes, + chart = this.chart, + component = this; + return new KeyboardNavigationHandler(chart, { + keyCodeMap: [ + [ + [keys.up, keys.down, keys.left, keys.right], + function (keyCode) { + return component.onMapKbdArrow(this, keyCode); + } + ], + [ + [keys.tab], + function (_keyCode, e) { + return component.onMapKbdTab(this, e); + } + ], + [ + [keys.space, keys.enter], + function () { + return component.onMapKbdClick(this); + } + ] + ], + validate: function () { + return chartHasMapZoom(chart); + }, + init: function (direction) { + return component.onMapNavInit(direction); + } + }); + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @param {number} keyCode + * @return {number} Response code + */ + onMapKbdArrow: function (keyboardNavigationHandler, keyCode) { + var keys = this.keyCodes, + panAxis = (keyCode === keys.up || keyCode === keys.down) ? + 'yAxis' : 'xAxis', + stepDirection = (keyCode === keys.left || keyCode === keys.up) ? + -1 : 1; + this.chart[panAxis][0].panStep(stepDirection); + return keyboardNavigationHandler.response.success; + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @param {global.KeyboardEvent} event + * @return {number} Response code + */ + onMapKbdTab: function (keyboardNavigationHandler, event) { + var button, + chart = this.chart, + response = keyboardNavigationHandler.response, + isBackwards = event.shiftKey, + isMoveOutOfRange = isBackwards && !this.focusedMapNavButtonIx || + !isBackwards && this.focusedMapNavButtonIx; + // Deselect old + chart.mapNavButtons[this.focusedMapNavButtonIx].setState(0); + if (isMoveOutOfRange) { + chart.mapZoom(); // Reset zoom + return response[isBackwards ? 'prev' : 'next']; + } + // Select other button + this.focusedMapNavButtonIx += isBackwards ? -1 : 1; + button = chart.mapNavButtons[this.focusedMapNavButtonIx]; + chart.setFocusToElement(button.box, button.element); + button.setState(2); + return response.success; + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @return {number} Response code + */ + onMapKbdClick: function (keyboardNavigationHandler) { + this.fakeClickEvent(this.chart.mapNavButtons[this.focusedMapNavButtonIx] + .element); + return keyboardNavigationHandler.response.success; + }, + /** + * @private + * @param {number} direction + */ + onMapNavInit: function (direction) { + var chart = this.chart, + zoomIn = chart.mapNavButtons[0], + zoomOut = chart.mapNavButtons[1], + initialButton = direction > 0 ? zoomIn : zoomOut; + chart.setFocusToElement(initialButton.box, initialButton.element); + initialButton.setState(2); + this.focusedMapNavButtonIx = direction > 0 ? 0 : 1; + }, + /** + * Get keyboard navigation handler for a simple chart button. Provide the + * button reference for the chart, and a function to call on click. + * + * @private + * @param {string} buttonProp The property on chart referencing the button. + * @return {Highcharts.KeyboardNavigationHandler} The module object + */ + simpleButtonNavigation: function (buttonProp, proxyProp, onClick) { + var keys = this.keyCodes, + component = this, + chart = this.chart; + return new KeyboardNavigationHandler(chart, { + keyCodeMap: [ + [ + [keys.tab, keys.up, keys.down, keys.left, keys.right], + function (keyCode, e) { + var isBackwards = keyCode === keys.tab && e.shiftKey || + keyCode === keys.left || keyCode === keys.up; + // Arrow/tab => just move + return this.response[isBackwards ? 'prev' : 'next']; + } + ], + [ + [keys.space, keys.enter], + function () { + var res = onClick(this, + chart); + return pick(res, this.response.success); + } + ] + ], + validate: function () { + var hasButton = (chart[buttonProp] && + chart[buttonProp].box && + component[proxyProp]); + return hasButton; + }, + init: function () { + chart.setFocusToElement(chart[buttonProp].box, component[proxyProp]); + } + }); + }, + /** + * Get keyboard navigation handlers for this component. + * @return {Array} + * List of module objects + */ + getKeyboardNavigation: function () { + return [ + this.simpleButtonNavigation('resetZoomButton', 'resetZoomProxyButton', function (_handler, chart) { + chart.zoomOut(); + }), + this.simpleButtonNavigation('drillUpButton', 'drillUpProxyButton', function (handler, chart) { + chart.drillUp(); + return handler.response.prev; + }), + this.getMapZoomNavigation() + ]; + } + }); + + return ZoomComponent; + }); + _registerModule(_modules, 'Accessibility/Components/RangeSelectorComponent.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js'], _modules['Accessibility/AccessibilityComponent.js'], _modules['Accessibility/KeyboardNavigationHandler.js'], _modules['Accessibility/Utils/ChartUtilities.js'], _modules['Accessibility/Utils/HTMLUtilities.js']], function (H, U, AccessibilityComponent, KeyboardNavigationHandler, ChartUtilities, HTMLUtilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Accessibility component for the range selector. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend; + var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT; + var setElAttrs = HTMLUtilities.setElAttrs; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * @private + */ + function shouldRunInputNavigation(chart) { + var inputVisible = (chart.rangeSelector && + chart.rangeSelector.inputGroup && + chart.rangeSelector.inputGroup.element + .getAttribute('visibility') !== 'hidden'); + return (inputVisible && + chart.options.rangeSelector.inputEnabled !== false && + chart.rangeSelector.minInput && + chart.rangeSelector.maxInput); + } + /** + * Highlight range selector button by index. + * + * @private + * @function Highcharts.Chart#highlightRangeSelectorButton + * + * @param {number} ix + * + * @return {boolean} + */ + H.Chart.prototype.highlightRangeSelectorButton = function (ix) { + var buttons = this.rangeSelector.buttons, + curSelectedIx = this.highlightedRangeSelectorItemIx; + // Deselect old + if (typeof curSelectedIx !== 'undefined' && buttons[curSelectedIx]) { + buttons[curSelectedIx].setState(this.oldRangeSelectorItemState || 0); + } + // Select new + this.highlightedRangeSelectorItemIx = ix; + if (buttons[ix]) { + this.setFocusToElement(buttons[ix].box, buttons[ix].element); + this.oldRangeSelectorItemState = buttons[ix].state; + buttons[ix].setState(2); + return true; + } + return false; + }; + /** + * The RangeSelectorComponent class + * + * @private + * @class + * @name Highcharts.RangeSelectorComponent + */ + var RangeSelectorComponent = function () { }; + RangeSelectorComponent.prototype = new AccessibilityComponent(); + extend(RangeSelectorComponent.prototype, /** @lends Highcharts.RangeSelectorComponent */ { + /** + * Called on first render/updates to the chart, including options changes. + */ + onChartUpdate: function () { + var chart = this.chart, + component = this, + rangeSelector = chart.rangeSelector; + if (!rangeSelector) { + return; + } + if (rangeSelector.buttons && rangeSelector.buttons.length) { + rangeSelector.buttons.forEach(function (button) { + unhideChartElementFromAT(chart, button.element); + component.setRangeButtonAttrs(button); + }); + } + // Make sure input boxes are accessible and focusable + if (rangeSelector.maxInput && rangeSelector.minInput) { + ['minInput', 'maxInput'].forEach(function (key, i) { + var input = rangeSelector[key]; + if (input) { + unhideChartElementFromAT(chart, input); + component.setRangeInputAttrs(input, 'accessibility.rangeSelector.' + (i ? 'max' : 'min') + + 'InputLabel'); + } + }); + } + }, + /** + * @private + * @param {Highcharts.SVGElement} button + */ + setRangeButtonAttrs: function (button) { + var chart = this.chart, + label = chart.langFormat('accessibility.rangeSelector.buttonText', { + chart: chart, + buttonText: button.text && button.text.textStr + }); + setElAttrs(button.element, { + tabindex: -1, + role: 'button', + 'aria-label': label + }); + }, + /** + * @private + */ + setRangeInputAttrs: function (input, langKey) { + var chart = this.chart; + setElAttrs(input, { + tabindex: -1, + role: 'textbox', + 'aria-label': chart.langFormat(langKey, { chart: chart }) + }); + }, + /** + * Get navigation for the range selector buttons. + * @private + * @return {Highcharts.KeyboardNavigationHandler} The module object. + */ + getRangeSelectorButtonNavigation: function () { + var chart = this.chart, + keys = this.keyCodes, + component = this; + return new KeyboardNavigationHandler(chart, { + keyCodeMap: [ + [ + [keys.left, keys.right, keys.up, keys.down], + function (keyCode) { + return component.onButtonNavKbdArrowKey(this, keyCode); + } + ], + [ + [keys.enter, keys.space], + function () { + return component.onButtonNavKbdClick(this); + } + ] + ], + validate: function () { + var hasRangeSelector = chart.rangeSelector && + chart.rangeSelector.buttons && + chart.rangeSelector.buttons.length; + return hasRangeSelector; + }, + init: function (direction) { + var lastButtonIx = (chart.rangeSelector.buttons.length - 1); + chart.highlightRangeSelectorButton(direction > 0 ? 0 : lastButtonIx); + } + }); + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @param {number} keyCode + * @return {number} Response code + */ + onButtonNavKbdArrowKey: function (keyboardNavigationHandler, keyCode) { + var response = keyboardNavigationHandler.response, + keys = this.keyCodes, + chart = this.chart, + wrapAround = chart.options.accessibility + .keyboardNavigation.wrapAround, + direction = (keyCode === keys.left || keyCode === keys.up) ? -1 : 1, + didHighlight = chart.highlightRangeSelectorButton(chart.highlightedRangeSelectorItemIx + direction); + if (!didHighlight) { + if (wrapAround) { + keyboardNavigationHandler.init(direction); + return response.success; + } + return response[direction > 0 ? 'next' : 'prev']; + } + return response.success; + }, + /** + * @private + */ + onButtonNavKbdClick: function (keyboardNavigationHandler) { + var response = keyboardNavigationHandler.response, + chart = this.chart, + wasDisabled = chart.oldRangeSelectorItemState === 3; + if (!wasDisabled) { + this.fakeClickEvent(chart.rangeSelector.buttons[chart.highlightedRangeSelectorItemIx].element); + } + return response.success; + }, + /** + * Get navigation for the range selector input boxes. + * @private + * @return {Highcharts.KeyboardNavigationHandler} + * The module object. + */ + getRangeSelectorInputNavigation: function () { + var chart = this.chart, + keys = this.keyCodes, + component = this; + return new KeyboardNavigationHandler(chart, { + keyCodeMap: [ + [ + [ + keys.tab, keys.up, keys.down + ], + function (keyCode, e) { + var direction = (keyCode === keys.tab && e.shiftKey || + keyCode === keys.up) ? -1 : 1; + return component.onInputKbdMove(this, direction); + } + ] + ], + validate: function () { + return shouldRunInputNavigation(chart); + }, + init: function (direction) { + component.onInputNavInit(direction); + }, + terminate: function () { + component.onInputNavTerminate(); + } + }); + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @param {number} direction + * @return {number} Response code + */ + onInputKbdMove: function (keyboardNavigationHandler, direction) { + var chart = this.chart, + response = keyboardNavigationHandler.response, + newIx = chart.highlightedInputRangeIx = + chart.highlightedInputRangeIx + direction, + newIxOutOfRange = newIx > 1 || newIx < 0; + if (newIxOutOfRange) { + return response[direction > 0 ? 'next' : 'prev']; + } + chart.rangeSelector[newIx ? 'maxInput' : 'minInput'].focus(); + return response.success; + }, + /** + * @private + * @param {number} direction + */ + onInputNavInit: function (direction) { + var chart = this.chart, + buttonIxToHighlight = direction > 0 ? 0 : 1; + chart.highlightedInputRangeIx = buttonIxToHighlight; + chart.rangeSelector[buttonIxToHighlight ? 'maxInput' : 'minInput'].focus(); + }, + /** + * @private + */ + onInputNavTerminate: function () { + var rangeSel = (this.chart.rangeSelector || {}); + if (rangeSel.maxInput) { + rangeSel.hideInput('max'); + } + if (rangeSel.minInput) { + rangeSel.hideInput('min'); + } + }, + /** + * Get keyboard navigation handlers for this component. + * @return {Array} + * List of module objects. + */ + getKeyboardNavigation: function () { + return [ + this.getRangeSelectorButtonNavigation(), + this.getRangeSelectorInputNavigation() + ]; + } + }); + + return RangeSelectorComponent; + }); + _registerModule(_modules, 'Accessibility/Components/InfoRegionsComponent.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js'], _modules['Accessibility/AccessibilityComponent.js'], _modules['Accessibility/Utils/Announcer.js'], _modules['Accessibility/Components/AnnotationsA11y.js'], _modules['Accessibility/Utils/ChartUtilities.js'], _modules['Accessibility/Utils/HTMLUtilities.js']], function (H, U, AccessibilityComponent, Announcer, AnnotationsA11y, ChartUtilities, HTMLUtilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Accessibility component for chart info region and table. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var doc = H.doc; + var extend = U.extend, + format = U.format, + pick = U.pick; + var getAnnotationsInfoHTML = AnnotationsA11y.getAnnotationsInfoHTML; + var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT, + getChartTitle = ChartUtilities.getChartTitle, + getAxisDescription = ChartUtilities.getAxisDescription; + var addClass = HTMLUtilities.addClass, + setElAttrs = HTMLUtilities.setElAttrs, + escapeStringForHTML = HTMLUtilities.escapeStringForHTML, + stripHTMLTagsFromString = HTMLUtilities.stripHTMLTagsFromString, + getElement = HTMLUtilities.getElement, + visuallyHideElement = HTMLUtilities.visuallyHideElement; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * @private + */ + function getTypeDescForMapChart(chart, formatContext) { + return formatContext.mapTitle ? + chart.langFormat('accessibility.chartTypes.mapTypeDescription', formatContext) : + chart.langFormat('accessibility.chartTypes.unknownMap', formatContext); + } + /** + * @private + */ + function getTypeDescForCombinationChart(chart, formatContext) { + return chart.langFormat('accessibility.chartTypes.combinationChart', formatContext); + } + /** + * @private + */ + function getTypeDescForEmptyChart(chart, formatContext) { + return chart.langFormat('accessibility.chartTypes.emptyChart', formatContext); + } + /** + * @private + */ + function buildTypeDescriptionFromSeries(chart, types, context) { + var firstType = types[0], typeExplaination = chart.langFormat('accessibility.seriesTypeDescriptions.' + firstType, context), multi = chart.series && chart.series.length < 2 ? 'Single' : 'Multiple'; + return (chart.langFormat('accessibility.chartTypes.' + firstType + multi, context) || + chart.langFormat('accessibility.chartTypes.default' + multi, context)) + (typeExplaination ? ' ' + typeExplaination : ''); + } + /** + * @private + */ + function getTableSummary(chart) { + return chart.langFormat('accessibility.table.tableSummary', { chart: chart }); + } + /** + * @private + */ + function stripEmptyHTMLTags(str) { + return str.replace(/<(\w+)[^>]*?>\s*<\/\1>/g, ''); + } + /** + * @private + */ + function enableSimpleHTML(str) { + return str + .replace(/<(h[1-7]|p|div|ul|ol|li)>/g, '<$1>') + .replace(/</(h[1-7]|p|div|ul|ol|li|a|button)>/g, '') + .replace(/<(div|a|button) id="([a-zA-Z\-0-9#]*?)">/g, '<$1 id="$2">'); + } + /** + * @private + */ + function stringToSimpleHTML(str) { + return stripEmptyHTMLTags(enableSimpleHTML(escapeStringForHTML(str))); + } + /** + * Return simplified explaination of chart type. Some types will not be familiar + * to most users, but in those cases we try to add an explaination of the type. + * + * @private + * @function Highcharts.Chart#getTypeDescription + * @param {Array} types The series types in this chart. + * @return {string} The text description of the chart type. + */ + H.Chart.prototype.getTypeDescription = function (types) { + var firstType = types[0], + firstSeries = this.series && this.series[0] || {}, + formatContext = { + numSeries: this.series.length, + numPoints: firstSeries.points && firstSeries.points.length, + chart: this, + mapTitle: firstSeries.mapTitle + }; + if (!firstType) { + return getTypeDescForEmptyChart(this, formatContext); + } + if (firstType === 'map') { + return getTypeDescForMapChart(this, formatContext); + } + if (this.types.length > 1) { + return getTypeDescForCombinationChart(this, formatContext); + } + return buildTypeDescriptionFromSeries(this, types, formatContext); + }; + /** + * The InfoRegionsComponent class + * + * @private + * @class + * @name Highcharts.InfoRegionsComponent + */ + var InfoRegionsComponent = function () { }; + InfoRegionsComponent.prototype = new AccessibilityComponent(); + extend(InfoRegionsComponent.prototype, /** @lends Highcharts.InfoRegionsComponent */ { + /** + * Init the component + * @private + */ + init: function () { + var chart = this.chart; + var component = this; + this.initRegionsDefinitions(); + this.addEvent(chart, 'afterGetTable', function (e) { + component.onDataTableCreated(e); + }); + this.addEvent(chart, 'afterViewData', function (tableDiv) { + component.dataTableDiv = tableDiv; + // Use small delay to give browsers & AT time to register new table + setTimeout(function () { + component.focusDataTable(); + }, 300); + }); + this.announcer = new Announcer(chart, 'assertive'); + }, + /** + * @private + */ + initRegionsDefinitions: function () { + var component = this; + this.screenReaderSections = { + before: { + element: null, + buildContent: function (chart) { + var formatter = chart.options.accessibility + .screenReaderSection.beforeChartFormatter; + return formatter ? formatter(chart) : + component.defaultBeforeChartFormatter(chart); + }, + insertIntoDOM: function (el, chart) { + chart.renderTo.insertBefore(el, chart.renderTo.firstChild); + }, + afterInserted: function () { + if (typeof component.sonifyButtonId !== 'undefined') { + component.initSonifyButton(component.sonifyButtonId); + } + if (typeof component.dataTableButtonId !== 'undefined') { + component.initDataTableButton(component.dataTableButtonId); + } + } + }, + after: { + element: null, + buildContent: function (chart) { + var formatter = chart.options.accessibility.screenReaderSection + .afterChartFormatter; + return formatter ? formatter(chart) : + component.defaultAfterChartFormatter(); + }, + insertIntoDOM: function (el, chart) { + chart.renderTo.insertBefore(el, chart.container.nextSibling); + } + } + }; + }, + /** + * Called on chart render. Have to update the sections on render, in order + * to get a11y info from series. + */ + onChartRender: function () { + var component = this; + this.linkedDescriptionElement = this.getLinkedDescriptionElement(); + this.setLinkedDescriptionAttrs(); + Object.keys(this.screenReaderSections).forEach(function (regionKey) { + component.updateScreenReaderSection(regionKey); + }); + }, + /** + * @private + */ + getLinkedDescriptionElement: function () { + var chartOptions = this.chart.options, + linkedDescOption = chartOptions.accessibility.linkedDescription; + if (!linkedDescOption) { + return; + } + if (typeof linkedDescOption !== 'string') { + return linkedDescOption; + } + var query = format(linkedDescOption, + this.chart), + queryMatch = doc.querySelectorAll(query); + if (queryMatch.length === 1) { + return queryMatch[0]; + } + }, + /** + * @private + */ + setLinkedDescriptionAttrs: function () { + var el = this.linkedDescriptionElement; + if (el) { + el.setAttribute('aria-hidden', 'true'); + addClass(el, 'highcharts-linked-description'); + } + }, + /** + * @private + * @param {string} regionKey The name/key of the region to update + */ + updateScreenReaderSection: function (regionKey) { + var chart = this.chart, region = this.screenReaderSections[regionKey], content = region.buildContent(chart), sectionDiv = region.element = (region.element || this.createElement('div')), hiddenDiv = (sectionDiv.firstChild || this.createElement('div')); + this.setScreenReaderSectionAttribs(sectionDiv, regionKey); + hiddenDiv.innerHTML = content; + sectionDiv.appendChild(hiddenDiv); + region.insertIntoDOM(sectionDiv, chart); + visuallyHideElement(hiddenDiv); + unhideChartElementFromAT(chart, hiddenDiv); + if (region.afterInserted) { + region.afterInserted(); + } + }, + /** + * @private + * @param {Highcharts.HTMLDOMElement} sectionDiv The section element + * @param {string} regionKey Name/key of the region we are setting attrs for + */ + setScreenReaderSectionAttribs: function (sectionDiv, regionKey) { + var labelLangKey = ('accessibility.screenReaderSection.' + regionKey + 'RegionLabel'), chart = this.chart, labelText = chart.langFormat(labelLangKey, { chart: chart }), sectionId = 'highcharts-screen-reader-region-' + regionKey + '-' + + chart.index; + setElAttrs(sectionDiv, { + id: sectionId, + 'aria-label': labelText + }); + // Sections are wrapped to be positioned relatively to chart in case + // elements inside are tabbed to. + sectionDiv.style.position = 'relative'; + if (chart.options.accessibility.landmarkVerbosity === 'all' && + labelText) { + sectionDiv.setAttribute('role', 'region'); + } + }, + /** + * @private + * @return {string} + */ + defaultBeforeChartFormatter: function () { + var _a; + var chart = this.chart, + format = chart.options.accessibility + .screenReaderSection.beforeChartFormat, + axesDesc = this.getAxesDescription(), + shouldHaveSonifyBtn = chart.sonify && ((_a = chart.options.sonification) === null || _a === void 0 ? void 0 : _a.enabled), + sonifyButtonId = 'highcharts-a11y-sonify-data-btn-' + + chart.index, + dataTableButtonId = 'hc-linkto-highcharts-data-table-' + + chart.index, + annotationsList = getAnnotationsInfoHTML(chart), + annotationsTitleStr = chart.langFormat('accessibility.screenReaderSection.annotations.heading', { chart: chart }), + context = { + chartTitle: getChartTitle(chart), + typeDescription: this.getTypeDescriptionText(), + chartSubtitle: this.getSubtitleText(), + chartLongdesc: this.getLongdescText(), + xAxisDescription: axesDesc.xAxis, + yAxisDescription: axesDesc.yAxis, + playAsSoundButton: shouldHaveSonifyBtn ? + this.getSonifyButtonText(sonifyButtonId) : '', + viewTableButton: chart.getCSV ? + this.getDataTableButtonText(dataTableButtonId) : '', + annotationsTitle: annotationsList ? annotationsTitleStr : '', + annotationsList: annotationsList + }, + formattedString = H.i18nFormat(format, + context, + chart); + this.dataTableButtonId = dataTableButtonId; + this.sonifyButtonId = sonifyButtonId; + return stringToSimpleHTML(formattedString); + }, + /** + * @private + * @return {string} + */ + defaultAfterChartFormatter: function () { + var chart = this.chart, + format = chart.options.accessibility + .screenReaderSection.afterChartFormat, + context = { + endOfChartMarker: this.getEndOfChartMarkerText() + }, + formattedString = H.i18nFormat(format, + context, + chart); + return stringToSimpleHTML(formattedString); + }, + /** + * @private + * @return {string} + */ + getLinkedDescription: function () { + var el = this.linkedDescriptionElement, + content = el && el.innerHTML || ''; + return stripHTMLTagsFromString(content); + }, + /** + * @private + * @return {string} + */ + getLongdescText: function () { + var chartOptions = this.chart.options, + captionOptions = chartOptions.caption, + captionText = captionOptions && captionOptions.text, + linkedDescription = this.getLinkedDescription(); + return (chartOptions.accessibility.description || + linkedDescription || + captionText || + ''); + }, + /** + * @private + * @return {string} + */ + getTypeDescriptionText: function () { + var chart = this.chart; + return chart.types ? + chart.options.accessibility.typeDescription || + chart.getTypeDescription(chart.types) : ''; + }, + /** + * @private + * @param {string} buttonId + * @return {string} + */ + getDataTableButtonText: function (buttonId) { + var chart = this.chart, + buttonText = chart.langFormat('accessibility.table.viewAsDataTableButtonText', { chart: chart, + chartTitle: getChartTitle(chart) }); + return ''; + }, + /** + * @private + * @param {string} buttonId + * @return {string} + */ + getSonifyButtonText: function (buttonId) { + var _a; + var chart = this.chart; + if (((_a = chart.options.sonification) === null || _a === void 0 ? void 0 : _a.enabled) === false) { + return ''; + } + var buttonText = chart.langFormat('accessibility.sonification.playAsSoundButtonText', { chart: chart, + chartTitle: getChartTitle(chart) }); + return ''; + }, + /** + * @private + * @return {string} + */ + getSubtitleText: function () { + var subtitle = (this.chart.options.subtitle); + return stripHTMLTagsFromString(subtitle && subtitle.text || ''); + }, + /** + * @private + * @return {string} + */ + getEndOfChartMarkerText: function () { + var chart = this.chart, markerText = chart.langFormat('accessibility.screenReaderSection.endOfChartMarker', { chart: chart }), id = 'highcharts-end-of-chart-marker-' + chart.index; + return '
    ' + markerText + '
    '; + }, + /** + * @private + * @param {Highcharts.Dictionary} e + */ + onDataTableCreated: function (e) { + var chart = this.chart; + if (chart.options.accessibility.enabled) { + if (this.viewDataTableButton) { + this.viewDataTableButton.setAttribute('aria-expanded', 'true'); + } + e.html = e.html.replace('
    } + */ + getAxesDescription: function () { + var chart = this.chart, + shouldDescribeColl = function (collectionKey, + defaultCondition) { + var axes = chart[collectionKey]; + return axes.length > 1 || axes[0] && + pick(axes[0].options.accessibility && + axes[0].options.accessibility.enabled, defaultCondition); + }, hasNoMap = !!chart.types && chart.types.indexOf('map') < 0, hasCartesian = !!chart.hasCartesianSeries, showXAxes = shouldDescribeColl('xAxis', !chart.angular && hasCartesian && hasNoMap), showYAxes = shouldDescribeColl('yAxis', hasCartesian && hasNoMap), desc = {}; + if (showXAxes) { + desc.xAxis = this.getAxisDescriptionText('xAxis'); + } + if (showYAxes) { + desc.yAxis = this.getAxisDescriptionText('yAxis'); + } + return desc; + }, + /** + * @private + * @param {string} collectionKey + * @return {string} + */ + getAxisDescriptionText: function (collectionKey) { + var component = this, + chart = this.chart, + axes = chart[collectionKey]; + return chart.langFormat('accessibility.axis.' + collectionKey + 'Description' + (axes.length > 1 ? 'Plural' : 'Singular'), { + chart: chart, + names: axes.map(function (axis) { + return getAxisDescription(axis); + }), + ranges: axes.map(function (axis) { + return component.getAxisRangeDescription(axis); + }), + numAxes: axes.length + }); + }, + /** + * Return string with text description of the axis range. + * @private + * @param {Highcharts.Axis} axis The axis to get range desc of. + * @return {string} A string with the range description for the axis. + */ + getAxisRangeDescription: function (axis) { + var axisOptions = axis.options || {}; + // Handle overridden range description + if (axisOptions.accessibility && + typeof axisOptions.accessibility.rangeDescription !== 'undefined') { + return axisOptions.accessibility.rangeDescription; + } + // Handle category axes + if (axis.categories) { + return this.getCategoryAxisRangeDesc(axis); + } + // Use time range, not from-to? + if (axis.dateTime && (axis.min === 0 || axis.dataMin === 0)) { + return this.getAxisTimeLengthDesc(axis); + } + // Just use from and to. + // We have the range and the unit to use, find the desc format + return this.getAxisFromToDescription(axis); + }, + /** + * @private + * @param {Highcharts.Axis} axis + * @return {string} + */ + getCategoryAxisRangeDesc: function (axis) { + var chart = this.chart; + if (axis.dataMax && axis.dataMin) { + return chart.langFormat('accessibility.axis.rangeCategories', { + chart: chart, + axis: axis, + numCategories: axis.dataMax - axis.dataMin + 1 + }); + } + return ''; + }, + /** + * @private + * @param {Highcharts.Axis} axis + * @return {string} + */ + getAxisTimeLengthDesc: function (axis) { + var chart = this.chart, + range = {}, + rangeUnit = 'Seconds'; + range.Seconds = ((axis.max || 0) - (axis.min || 0)) / 1000; + range.Minutes = range.Seconds / 60; + range.Hours = range.Minutes / 60; + range.Days = range.Hours / 24; + ['Minutes', 'Hours', 'Days'].forEach(function (unit) { + if (range[unit] > 2) { + rangeUnit = unit; + } + }); + var rangeValue = range[rangeUnit].toFixed(rangeUnit !== 'Seconds' && + rangeUnit !== 'Minutes' ? 1 : 0 // Use decimals for days/hours + ); + // We have the range and the unit to use, find the desc format + return chart.langFormat('accessibility.axis.timeRange' + rangeUnit, { + chart: chart, + axis: axis, + range: rangeValue.replace('.0', '') + }); + }, + /** + * @private + * @param {Highcharts.Axis} axis + * @return {string} + */ + getAxisFromToDescription: function (axis) { + var chart = this.chart, + dateRangeFormat = chart.options.accessibility + .screenReaderSection.axisRangeDateFormat, + format = function (axisKey) { + return axis.dateTime ? chart.time.dateFormat(dateRangeFormat, + axis[axisKey]) : axis[axisKey]; + }; + return chart.langFormat('accessibility.axis.rangeFromTo', { + chart: chart, + axis: axis, + rangeFrom: format('min'), + rangeTo: format('max') + }); + }, + /** + * Remove component traces + */ + destroy: function () { + var _a; + (_a = this.announcer) === null || _a === void 0 ? void 0 : _a.destroy(); + } + }); + + return InfoRegionsComponent; + }); + _registerModule(_modules, 'Accessibility/Components/ContainerComponent.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js'], _modules['Accessibility/Utils/HTMLUtilities.js'], _modules['Accessibility/Utils/ChartUtilities.js'], _modules['Accessibility/AccessibilityComponent.js']], function (H, U, HTMLUtilities, ChartUtilities, AccessibilityComponent) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Accessibility component for chart container. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var doc = H.win.document; + var extend = U.extend; + var stripHTMLTags = HTMLUtilities.stripHTMLTagsFromString; + var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT, + getChartTitle = ChartUtilities.getChartTitle; + /* eslint-disable valid-jsdoc */ + /** + * The ContainerComponent class + * + * @private + * @class + * @name Highcharts.ContainerComponent + */ + var ContainerComponent = function () { }; + ContainerComponent.prototype = new AccessibilityComponent(); + extend(ContainerComponent.prototype, /** @lends Highcharts.ContainerComponent */ { + /** + * Called on first render/updates to the chart, including options changes. + */ + onChartUpdate: function () { + this.handleSVGTitleElement(); + this.setSVGContainerLabel(); + this.setGraphicContainerAttrs(); + this.setRenderToAttrs(); + this.makeCreditsAccessible(); + }, + /** + * @private + */ + handleSVGTitleElement: function () { + var chart = this.chart, titleId = 'highcharts-title-' + chart.index, titleContents = stripHTMLTags(chart.langFormat('accessibility.svgContainerTitle', { + chartTitle: getChartTitle(chart) + })); + if (titleContents.length) { + var titleElement = this.svgTitleElement = + this.svgTitleElement || doc.createElementNS('http://www.w3.org/2000/svg', 'title'); + titleElement.textContent = titleContents; + titleElement.id = titleId; + chart.renderTo.insertBefore(titleElement, chart.renderTo.firstChild); + } + }, + /** + * @private + */ + setSVGContainerLabel: function () { + var chart = this.chart, + svgContainerLabel = stripHTMLTags(chart.langFormat('accessibility.svgContainerLabel', { + chartTitle: getChartTitle(chart) + })); + if (chart.renderer.box && svgContainerLabel.length) { + chart.renderer.box.setAttribute('aria-label', svgContainerLabel); + } + }, + /** + * @private + */ + setGraphicContainerAttrs: function () { + var chart = this.chart, + label = chart.langFormat('accessibility.graphicContainerLabel', { + chartTitle: getChartTitle(chart) + }); + if (label.length) { + chart.container.setAttribute('aria-label', label); + } + }, + /** + * @private + */ + setRenderToAttrs: function () { + var chart = this.chart; + if (chart.options.accessibility.landmarkVerbosity !== 'disabled') { + chart.renderTo.setAttribute('role', 'region'); + } + else { + chart.renderTo.removeAttribute('role'); + } + chart.renderTo.setAttribute('aria-label', chart.langFormat('accessibility.chartContainerLabel', { + title: getChartTitle(chart), + chart: chart + })); + }, + /** + * @private + */ + makeCreditsAccessible: function () { + var chart = this.chart, + credits = chart.credits; + if (credits) { + if (credits.textStr) { + credits.element.setAttribute('aria-label', stripHTMLTags(chart.langFormat('accessibility.credits', { creditsStr: credits.textStr }))); + } + unhideChartElementFromAT(chart, credits.element); + } + }, + /** + * Accessibility disabled/chart destroyed. + */ + destroy: function () { + this.chart.renderTo.setAttribute('aria-hidden', true); + } + }); + + return ContainerComponent; + }); + _registerModule(_modules, 'Accessibility/HighContrastMode.js', [_modules['Core/Globals.js']], function (H) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Handling for Windows High Contrast Mode. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var isMS = H.isMS, + win = H.win, + doc = win.document; + var whcm = { + /** + * Detect WHCM in the browser. + * + * @function Highcharts#isHighContrastModeActive + * @private + * @return {boolean} Returns true if the browser is in High Contrast mode. + */ + isHighContrastModeActive: function () { + // Use media query on Edge, but not on IE + var isEdge = /(Edg)/.test(win.navigator.userAgent); + if (win.matchMedia && isEdge) { + return win.matchMedia('(-ms-high-contrast: active)').matches; + } + // Test BG image for IE + if (isMS && win.getComputedStyle) { + var testDiv = doc.createElement('div'); + var imageSrc = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='; + testDiv.style.backgroundImage = "url(" + imageSrc + ")"; // #13071 + doc.body.appendChild(testDiv); + var bi = (testDiv.currentStyle || + win.getComputedStyle(testDiv)).backgroundImage; + doc.body.removeChild(testDiv); + return bi === 'none'; + } + // Not used for other browsers + return false; + }, + /** + * Force high contrast theme for the chart. The default theme is defined in + * a separate file. + * + * @function Highcharts#setHighContrastTheme + * @private + * @param {Highcharts.AccessibilityChart} chart The chart to set the theme of. + * @return {void} + */ + setHighContrastTheme: function (chart) { + // We might want to add additional functionality here in the future for + // storing the old state so that we can reset the theme if HC mode is + // disabled. For now, the user will have to reload the page. + chart.highContrastModeActive = true; + // Apply theme to chart + var theme = (chart.options.accessibility.highContrastTheme); + chart.update(theme, false); + // Force series colors (plotOptions is not enough) + chart.series.forEach(function (s) { + var plotOpts = theme.plotOptions[s.type] || {}; + s.update({ + color: plotOpts.color || 'windowText', + colors: [plotOpts.color || 'windowText'], + borderColor: plotOpts.borderColor || 'window' + }); + // Force point colors if existing + s.points.forEach(function (p) { + if (p.options && p.options.color) { + p.update({ + color: plotOpts.color || 'windowText', + borderColor: plotOpts.borderColor || 'window' + }, false); + } + }); + }); + // The redraw for each series and after is required for 3D pie + // (workaround) + chart.redraw(); + } + }; + + return whcm; + }); + _registerModule(_modules, 'Accessibility/HighContrastTheme.js', [], function () { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Default theme for Windows High Contrast Mode. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var theme = { + chart: { + backgroundColor: 'window' + }, + title: { + style: { + color: 'windowText' + } + }, + subtitle: { + style: { + color: 'windowText' + } + }, + colorAxis: { + minColor: 'windowText', + maxColor: 'windowText', + stops: [] + }, + colors: ['windowText'], + xAxis: { + gridLineColor: 'windowText', + labels: { + style: { + color: 'windowText' + } + }, + lineColor: 'windowText', + minorGridLineColor: 'windowText', + tickColor: 'windowText', + title: { + style: { + color: 'windowText' + } + } + }, + yAxis: { + gridLineColor: 'windowText', + labels: { + style: { + color: 'windowText' + } + }, + lineColor: 'windowText', + minorGridLineColor: 'windowText', + tickColor: 'windowText', + title: { + style: { + color: 'windowText' + } + } + }, + tooltip: { + backgroundColor: 'window', + borderColor: 'windowText', + style: { + color: 'windowText' + } + }, + plotOptions: { + series: { + lineColor: 'windowText', + fillColor: 'window', + borderColor: 'windowText', + edgeColor: 'windowText', + borderWidth: 1, + dataLabels: { + connectorColor: 'windowText', + color: 'windowText', + style: { + color: 'windowText', + textOutline: 'none' + } + }, + marker: { + lineColor: 'windowText', + fillColor: 'windowText' + } + }, + pie: { + color: 'window', + colors: ['window'], + borderColor: 'windowText', + borderWidth: 1 + }, + boxplot: { + fillColor: 'window' + }, + candlestick: { + lineColor: 'windowText', + fillColor: 'window' + }, + errorbar: { + fillColor: 'window' + } + }, + legend: { + backgroundColor: 'window', + itemStyle: { + color: 'windowText' + }, + itemHoverStyle: { + color: 'windowText' + }, + itemHiddenStyle: { + color: '#555' + }, + title: { + style: { + color: 'windowText' + } + } + }, + credits: { + style: { + color: 'windowText' + } + }, + labels: { + style: { + color: 'windowText' + } + }, + drilldown: { + activeAxisLabelStyle: { + color: 'windowText' + }, + activeDataLabelStyle: { + color: 'windowText' + } + }, + navigation: { + buttonOptions: { + symbolStroke: 'windowText', + theme: { + fill: 'window' + } + } + }, + rangeSelector: { + buttonTheme: { + fill: 'window', + stroke: 'windowText', + style: { + color: 'windowText' + }, + states: { + hover: { + fill: 'window', + stroke: 'windowText', + style: { + color: 'windowText' + } + }, + select: { + fill: '#444', + stroke: 'windowText', + style: { + color: 'windowText' + } + } + } + }, + inputBoxBorderColor: 'windowText', + inputStyle: { + backgroundColor: 'window', + color: 'windowText' + }, + labelStyle: { + color: 'windowText' + } + }, + navigator: { + handles: { + backgroundColor: 'window', + borderColor: 'windowText' + }, + outlineColor: 'windowText', + maskFill: 'transparent', + series: { + color: 'windowText', + lineColor: 'windowText' + }, + xAxis: { + gridLineColor: 'windowText' + } + }, + scrollbar: { + barBackgroundColor: '#444', + barBorderColor: 'windowText', + buttonArrowColor: 'windowText', + buttonBackgroundColor: 'window', + buttonBorderColor: 'windowText', + rifleColor: 'windowText', + trackBackgroundColor: 'window', + trackBorderColor: 'windowText' + } + }; + + return theme; + }); + _registerModule(_modules, 'Accessibility/Options/Options.js', [], function () { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Default options for accessibility. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Formatter callback for the accessibility announcement. + * + * @callback Highcharts.AccessibilityAnnouncementFormatter + * + * @param {Array} updatedSeries + * Array of all series that received updates. If an announcement is already + * queued, the series that received updates for that announcement are also + * included in this array. + * + * @param {Highcharts.Series} [addedSeries] + * This is provided if {@link Highcharts.Chart#addSeries} was called, and there + * is a new series. In that case, this argument is a reference to the new + * series. + * + * @param {Highcharts.Point} [addedPoint] + * This is provided if {@link Highcharts.Series#addPoint} was called, and there + * is a new point. In that case, this argument is a reference to the new point. + * + * @return {false|string} + * The function should return a string with the text to announce to the user. + * Return empty string to not announce anything. Return `false` to use the + * default announcement format. + */ + /** + * @interface Highcharts.PointAccessibilityOptionsObject + */ /** + * Provide a description of the data point, announced to screen readers. + * @name Highcharts.PointAccessibilityOptionsObject#description + * @type {string|undefined} + * @requires modules/accessibility + * @since 7.1.0 + */ + /* * + * @interface Highcharts.PointOptionsObject in parts/Point.ts + */ /** + * @name Highcharts.PointOptionsObject#accessibility + * @type {Highcharts.PointAccessibilityOptionsObject|undefined} + * @requires modules/accessibility + * @since 7.1.0 + */ + /** + * @callback Highcharts.ScreenReaderClickCallbackFunction + * + * @param {global.MouseEvent} evt + * Mouse click event + * + * @return {void} + */ + /** + * Creates a formatted string for the screen reader module. + * + * @callback Highcharts.ScreenReaderFormatterCallbackFunction + * + * @param {T} context + * Context to format + * + * @return {string} + * Formatted string for the screen reader module. + */ + var options = { + /** + * Options for configuring accessibility for the chart. Requires the + * [accessibility module](https://code.highcharts.com/modules/accessibility.js) + * to be loaded. For a description of the module and information + * on its features, see + * [Highcharts Accessibility](https://www.highcharts.com/docs/chart-concepts/accessibility). + * + * @since 5.0.0 + * @requires modules/accessibility + * @optionparent accessibility + */ + accessibility: { + /** + * Enable accessibility functionality for the chart. + * + * @since 5.0.0 + */ + enabled: true, + /** + * Accessibility options for the screen reader information sections + * added before and after the chart. + * + * @since 8.0.0 + */ + screenReaderSection: { + /** + * Function to run upon clicking the "View as Data Table" link in + * the screen reader region. + * + * By default Highcharts will insert and set focus to a data table + * representation of the chart. + * + * @type {Highcharts.ScreenReaderClickCallbackFunction} + * @since 8.0.0 + * @apioption accessibility.screenReaderSection.onViewDataTableClick + */ + /** + * Function to run upon clicking the "Play as sound" button in + * the screen reader region. + * + * By default Highcharts will call the `chart.sonify` function. + * + * @type {Highcharts.ScreenReaderClickCallbackFunction} + * @since 8.0.1 + * @apioption accessibility.screenReaderSection.onPlayAsSoundClick + */ + /** + * A formatter function to create the HTML contents of the hidden + * screen reader information region before the chart. Receives one + * argument, `chart`, referring to the chart object. Should return a + * string with the HTML content of the region. By default this + * returns an automatic description of the chart based on + * [beforeChartFormat](#accessibility.screenReaderSection.beforeChartFormat). + * + * @type {Highcharts.ScreenReaderFormatterCallbackFunction} + * @since 8.0.0 + * @apioption accessibility.screenReaderSection.beforeChartFormatter + */ + /** + * Format for the screen reader information region before the chart. + * Supported HTML tags are ``, `

    `, `

    `, ``, `
    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    `this.min`The mininimum value of the points in the selected + * range.
    `this.max`The maximum value of the points in the selected + * range.
    `this.average`The average value of the points in the selected + * range.
    `this.bins`The amount of the points in the selected range.
    + * + * @type {function} + * + */ + formatter: void 0 + } + }, + controlPointOptions: { + positioner: function (target) { + var cpIndex = this.index, + chart = target.chart, + options = target.options, + typeOptions = options.typeOptions, + selectType = typeOptions.selectType, + controlPointOptions = options.controlPointOptions, + inverted = chart.inverted, + xAxis = chart.xAxis[typeOptions.xAxis], + yAxis = chart.yAxis[typeOptions.yAxis], + targetX = target.xAxisMax, + targetY = target.yAxisMax, + ext = Measure.calculations.getExtremes(target.xAxisMin, + target.xAxisMax, + target.yAxisMin, + target.yAxisMax), + x, + y; + if (selectType === 'x') { + targetY = (ext.yAxisMax - ext.yAxisMin) / 2; + // first control point + if (cpIndex === 0) { + targetX = target.xAxisMin; + } + } + if (selectType === 'y') { + targetX = ext.xAxisMin + + ((ext.xAxisMax - ext.xAxisMin) / 2); + // first control point + if (cpIndex === 0) { + targetY = target.yAxisMin; + } + } + if (inverted) { + x = yAxis.toPixels(targetY); + y = xAxis.toPixels(targetX); + } + else { + x = xAxis.toPixels(targetX); + y = yAxis.toPixels(targetY); + } + return { + x: x - (controlPointOptions.width / 2), + y: y - (controlPointOptions.height / 2) + }; + }, + events: { + drag: function (e, target) { + var translation = this.mouseMoveToTranslation(e), selectType = target.options.typeOptions.selectType, index = this.index, x = selectType === 'y' ? 0 : translation.x, y = selectType === 'x' ? 0 : translation.y; + target.resize(x, y, index, selectType); + target.resizeX += x; + target.resizeY += y; + target.redraw(false, true); + } + } + } + }); + Annotation.types.measure = Measure; + + return Measure; + }); + _registerModule(_modules, 'Mixins/Navigation.js', [], function () { + /** + * + * (c) 2010-2018 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var chartNavigation = { + /** + * Initializes `chart.navigation` object which delegates `update()` methods + * to all other common classes (used in exporting and navigationBindings). + * + * @private + * @param {Highcharts.Chart} chart + * The chart instance. + * @return {void} + */ + initUpdate: function (chart) { + if (!chart.navigation) { + chart.navigation = { + updates: [], + update: function (options, + redraw) { + this.updates.forEach(function (updateConfig) { + updateConfig.update.call(updateConfig.context, + options, + redraw); + }); + } + }; + } + }, + /** + * Registers an `update()` method in the `chart.navigation` object. + * + * @private + * @param {Highcharts.ChartNavigationUpdateFunction} update + * The `update()` method that will be called in `chart.update()`. + * @param {Highcharts.Chart} chart + * The chart instance. `update()` will use that as a context + * (`this`). + * @return {void} + */ + addUpdate: function (update, chart) { + if (!chart.navigation) { + this.initUpdate(chart); + } + chart.navigation.updates.push({ + update: update, + context: chart + }); + } + }; + + return chartNavigation; + }); + _registerModule(_modules, 'Extensions/Annotations/NavigationBindings.js', [_modules['Extensions/Annotations/Annotations.js'], _modules['Mixins/Navigation.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (Annotation, chartNavigationMixin, H, U) { + /* * + * + * (c) 2009-2017 Highsoft, Black Label + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + attr = U.attr, + extend = U.extend, + format = U.format, + fireEvent = U.fireEvent, + isArray = U.isArray, + isFunction = U.isFunction, + isNumber = U.isNumber, + isObject = U.isObject, + merge = U.merge, + objectEach = U.objectEach, + pick = U.pick, + setOptions = U.setOptions; + /** + * A config object for navigation bindings in annotations. + * + * @interface Highcharts.NavigationBindingsOptionsObject + */ /** + * ClassName of the element for a binding. + * @name Highcharts.NavigationBindingsOptionsObject#className + * @type {string|undefined} + */ /** + * Last event to be fired after last step event. + * @name Highcharts.NavigationBindingsOptionsObject#end + * @type {Function|undefined} + */ /** + * Initial event, fired on a button click. + * @name Highcharts.NavigationBindingsOptionsObject#init + * @type {Function|undefined} + */ /** + * Event fired on first click on a chart. + * @name Highcharts.NavigationBindingsOptionsObject#start + * @type {Function|undefined} + */ /** + * Last event to be fired after last step event. Array of step events to be + * called sequentially after each user click. + * @name Highcharts.NavigationBindingsOptionsObject#steps + * @type {Array|undefined} + */ + var doc = H.doc, + win = H.win, + PREFIX = 'highcharts-'; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * IE 9-11 polyfill for Element.closest(): + * @private + */ + function closestPolyfill(el, s) { + var ElementProto = win.Element.prototype, + elementMatches = ElementProto.matches || + ElementProto.msMatchesSelector || + ElementProto.webkitMatchesSelector, + ret = null; + if (ElementProto.closest) { + ret = ElementProto.closest.call(el, s); + } + else { + do { + if (elementMatches.call(el, s)) { + return el; + } + el = el.parentElement || el.parentNode; + } while (el !== null && el.nodeType === 1); + } + return ret; + } + /** + * @private + * @interface bindingsUtils + */ + var bindingsUtils = { + /** + * Update size of background (rect) in some annotations: Measure, + Simple + * Rect. + * + * @private + * @function Highcharts.NavigationBindingsUtilsObject.updateRectSize + * + * @param {Highcharts.PointerEventObject} event + * Normalized browser event + * + * @param {Highcharts.Annotation} annotation + * Annotation to be updated + */ + updateRectSize: function (event, + annotation) { + var chart = annotation.chart, + options = annotation.options.typeOptions, + coords = chart.pointer.getCoordinates(event), + width = coords.xAxis[0].value - options.point.x, + height = options.point.y - coords.yAxis[0].value; + annotation.update({ + typeOptions: { + background: { + width: chart.inverted ? height : width, + height: chart.inverted ? width : height + } + } + }); + }, + /** + * Get field type according to value + * + * @private + * @function Highcharts.NavigationBindingsUtilsObject.getFieldType + * + * @param {'boolean'|'number'|'string'} value + * Atomic type (one of: string, number, boolean) + * + * @return {'checkbox'|'number'|'text'} + * Field type (one of: text, number, checkbox) + */ + getFieldType: function (value) { + return { + 'string': 'text', + 'number': 'number', + 'boolean': 'checkbox' + }[typeof value]; + } + }; + /** + * @private + */ + var NavigationBindings = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function NavigationBindings(chart, options) { + this.boundClassNames = void 0; + this.selectedButton = void 0; + this.chart = chart; + this.options = options; + this.eventsToUnbind = []; + this.container = doc.getElementsByClassName(this.options.bindingsClassName || ''); + } + // Private properties added by bindings: + // Active (selected) annotation that is editted through popup/forms + // activeAnnotation: Annotation + // Holder for current step, used on mouse move to update bound object + // mouseMoveEvent: function () {} + // Next event in `step` array to be called on chart's click + // nextEvent: function () {} + // Index in the `step` array of the current event + // stepIndex: 0 + // Flag to determine if current binding has steps + // steps: true|false + // Bindings holder for all events + // selectedButton: {} + // Holder for user options, returned from `start` event, and passed on to + // `step`'s' and `end`. + // currentUserDetails: {} + /* * + * + * Functions + * + * */ + /** + * Initi all events conencted to NavigationBindings. + * + * @private + * @function Highcharts.NavigationBindings#initEvents + */ + NavigationBindings.prototype.initEvents = function () { + var navigation = this, + chart = navigation.chart, + bindingsContainer = navigation.container, + options = navigation.options; + // Shorthand object for getting events for buttons: + navigation.boundClassNames = {}; + objectEach((options.bindings || {}), function (value) { + navigation.boundClassNames[value.className] = value; + }); + // Handle multiple containers with the same class names: + [].forEach.call(bindingsContainer, function (subContainer) { + navigation.eventsToUnbind.push(addEvent(subContainer, 'click', function (event) { + var bindings = navigation.getButtonEvents(subContainer, + event); + if (bindings) { + navigation.bindingsButtonClick(bindings.button, bindings.events, event); + } + })); + }); + objectEach(options.events || {}, function (callback, eventName) { + if (isFunction(callback)) { + navigation.eventsToUnbind.push(addEvent(navigation, eventName, callback)); + } + }); + navigation.eventsToUnbind.push(addEvent(chart.container, 'click', function (e) { + if (!chart.cancelClick && + chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop)) { + navigation.bindingsChartClick(this, e); + } + })); + navigation.eventsToUnbind.push(addEvent(chart.container, H.isTouchDevice ? 'touchmove' : 'mousemove', function (e) { + navigation.bindingsContainerMouseMove(this, e); + })); + }; + /** + * Common chart.update() delegation, shared between bindings and exporting. + * + * @private + * @function Highcharts.NavigationBindings#initUpdate + */ + NavigationBindings.prototype.initUpdate = function () { + var navigation = this; + chartNavigationMixin.addUpdate(function (options) { + navigation.update(options); + }, this.chart); + }; + /** + * Hook for click on a button, method selcts/unselects buttons, + * then calls `bindings.init` callback. + * + * @private + * @function Highcharts.NavigationBindings#bindingsButtonClick + * + * @param {Highcharts.HTMLDOMElement} [button] + * Clicked button + * + * @param {object} events + * Events passed down from bindings (`init`, `start`, `step`, `end`) + * + * @param {Highcharts.PointerEventObject} clickEvent + * Browser's click event + */ + NavigationBindings.prototype.bindingsButtonClick = function (button, events, clickEvent) { + var navigation = this, + chart = navigation.chart; + if (navigation.selectedButtonElement) { + fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement }); + if (navigation.nextEvent) { + // Remove in-progress annotations adders: + if (navigation.currentUserDetails && + navigation.currentUserDetails.coll === 'annotations') { + chart.removeAnnotation(navigation.currentUserDetails); + } + navigation.mouseMoveEvent = navigation.nextEvent = false; + } + } + navigation.selectedButton = events; + navigation.selectedButtonElement = button; + fireEvent(navigation, 'selectButton', { button: button }); + // Call "init" event, for example to open modal window + if (events.init) { + events.init.call(navigation, button, clickEvent); + } + if (events.start || events.steps) { + chart.renderer.boxWrapper.addClass(PREFIX + 'draw-mode'); + } + }; + /** + * Hook for click on a chart, first click on a chart calls `start` event, + * then on all subsequent clicks iterate over `steps` array. + * When finished, calls `end` event. + * + * @private + * @function Highcharts.NavigationBindings#bindingsChartClick + * + * @param {Highcharts.Chart} chart + * Chart that click was performed on. + * + * @param {Highcharts.PointerEventObject} clickEvent + * Browser's click event. + */ + NavigationBindings.prototype.bindingsChartClick = function (chart, clickEvent) { + var navigation = this, + chart = navigation.chart, + selectedButton = navigation.selectedButton, + svgContainer = chart.renderer.boxWrapper; + // Click outside popups, should close them and deselect the annotation + if (navigation.activeAnnotation && + !clickEvent.activeAnnotation && + // Element could be removed in the child action, e.g. button + clickEvent.target.parentNode && + // TO DO: Polyfill for IE11? + !closestPolyfill(clickEvent.target, '.' + PREFIX + 'popup')) { + fireEvent(navigation, 'closePopup'); + navigation.deselectAnnotation(); + } + if (!selectedButton || !selectedButton.start) { + return; + } + if (!navigation.nextEvent) { + // Call init method: + navigation.currentUserDetails = selectedButton.start.call(navigation, clickEvent); + // If steps exists (e.g. Annotations), bind them: + if (selectedButton.steps) { + navigation.stepIndex = 0; + navigation.steps = true; + navigation.mouseMoveEvent = navigation.nextEvent = + selectedButton.steps[navigation.stepIndex]; + } + else { + fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement }); + svgContainer.removeClass(PREFIX + 'draw-mode'); + navigation.steps = false; + navigation.selectedButton = null; + // First click is also the last one: + if (selectedButton.end) { + selectedButton.end.call(navigation, clickEvent, navigation.currentUserDetails); + } + } + } + else { + navigation.nextEvent(clickEvent, navigation.currentUserDetails); + if (navigation.steps) { + navigation.stepIndex++; + if (selectedButton.steps[navigation.stepIndex]) { + // If we have more steps, bind them one by one: + navigation.mouseMoveEvent = navigation.nextEvent = + selectedButton.steps[navigation.stepIndex]; + } + else { + fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement }); + svgContainer.removeClass(PREFIX + 'draw-mode'); + // That was the last step, call end(): + if (selectedButton.end) { + selectedButton.end.call(navigation, clickEvent, navigation.currentUserDetails); + } + navigation.nextEvent = false; + navigation.mouseMoveEvent = false; + navigation.selectedButton = null; + } + } + } + }; + /** + * Hook for mouse move on a chart's container. It calls current step. + * + * @private + * @function Highcharts.NavigationBindings#bindingsContainerMouseMove + * + * @param {Highcharts.HTMLDOMElement} container + * Chart's container. + * + * @param {global.Event} moveEvent + * Browser's move event. + */ + NavigationBindings.prototype.bindingsContainerMouseMove = function (_container, moveEvent) { + if (this.mouseMoveEvent) { + this.mouseMoveEvent(moveEvent, this.currentUserDetails); + } + }; + /** + * Translate fields (e.g. `params.period` or `marker.styles.color`) to + * Highcharts options object (e.g. `{ params: { period } }`). + * + * @private + * @function Highcharts.NavigationBindings#fieldsToOptions + * + * @param {Highcharts.Dictionary} fields + * Fields from popup form. + * + * @param {T} config + * Default config to be modified. + * + * @return {T} + * Modified config + */ + NavigationBindings.prototype.fieldsToOptions = function (fields, config) { + objectEach(fields, function (value, field) { + var parsedValue = parseFloat(value), + path = field.split('.'), + parent = config, + pathLength = path.length - 1; + // If it's a number (not "format" options), parse it: + if (isNumber(parsedValue) && + !value.match(/px/g) && + !field.match(/format/g)) { + value = parsedValue; + } + // Remove empty strings or values like 0 + if (value !== '' && value !== 'undefined') { + path.forEach(function (name, index) { + var nextName = pick(path[index + 1], ''); + if (pathLength === index) { + // Last index, put value: + parent[name] = value; + } + else if (!parent[name]) { + // Create middle property: + parent[name] = nextName.match(/\d/g) ? [] : {}; + parent = parent[name]; + } + else { + // Jump into next property + parent = parent[name]; + } + }); + } + }); + return config; + }; + /** + * Shorthand method to deselect an annotation. + * + * @function Highcharts.NavigationBindings#deselectAnnotation + */ + NavigationBindings.prototype.deselectAnnotation = function () { + if (this.activeAnnotation) { + this.activeAnnotation.setControlPointsVisibility(false); + this.activeAnnotation = false; + } + }; + /** + * Generates API config for popup in the same format as options for + * Annotation object. + * + * @function Highcharts.NavigationBindings#annotationToFields + * + * @param {Highcharts.Annotation} annotation + * Annotations object + * + * @return {Highcharts.Dictionary} + * Annotation options to be displayed in popup box + */ + NavigationBindings.prototype.annotationToFields = function (annotation) { + var options = annotation.options, + editables = NavigationBindings.annotationsEditable, + nestedEditables = editables.nestedOptions, + getFieldType = this.utils.getFieldType, + type = pick(options.type, + options.shapes && options.shapes[0] && + options.shapes[0].type, + options.labels && options.labels[0] && + options.labels[0].itemType, 'label'), + nonEditables = NavigationBindings.annotationsNonEditable[options.langKey] || [], + visualOptions = { + langKey: options.langKey, + type: type + }; + /** + * Nested options traversing. Method goes down to the options and copies + * allowed options (with values) to new object, which is last parameter: + * "parent". + * + * @private + * + * @param {*} option + * Atomic type or object/array + * + * @param {string} key + * Option name, for example "visible" or "x", "y" + * + * @param {object} parentEditables + * Editables from NavigationBindings.annotationsEditable + * + * @param {object} parent + * Where new options will be assigned + */ + function traverse(option, key, parentEditables, parent) { + var nextParent; + if (parentEditables && + option && + nonEditables.indexOf(key) === -1 && + ((parentEditables.indexOf && + parentEditables.indexOf(key)) >= 0 || + parentEditables[key] || // nested array + parentEditables === true // simple array + )) { + // Roots: + if (isArray(option)) { + parent[key] = []; + option.forEach(function (arrayOption, i) { + if (!isObject(arrayOption)) { + // Simple arrays, e.g. [String, Number, Boolean] + traverse(arrayOption, 0, nestedEditables[key], parent[key]); + } + else { + // Advanced arrays, e.g. [Object, Object] + parent[key][i] = {}; + objectEach(arrayOption, function (nestedOption, nestedKey) { + traverse(nestedOption, nestedKey, nestedEditables[key], parent[key][i]); + }); + } + }); + } + else if (isObject(option)) { + nextParent = {}; + if (isArray(parent)) { + parent.push(nextParent); + nextParent[key] = {}; + nextParent = nextParent[key]; + } + else { + parent[key] = nextParent; + } + objectEach(option, function (nestedOption, nestedKey) { + traverse(nestedOption, nestedKey, key === 0 ? parentEditables : nestedEditables[key], nextParent); + }); + } + else { + // Leaf: + if (key === 'format') { + parent[key] = [ + format(option, annotation.labels[0].points[0]).toString(), + 'text' + ]; + } + else if (isArray(parent)) { + parent.push([option, getFieldType(option)]); + } + else { + parent[key] = [option, getFieldType(option)]; + } + } + } + } + objectEach(options, function (option, key) { + if (key === 'typeOptions') { + visualOptions[key] = {}; + objectEach(options[key], function (typeOption, typeKey) { + traverse(typeOption, typeKey, nestedEditables, visualOptions[key], true); + }); + } + else { + traverse(option, key, editables[type], visualOptions); + } + }); + return visualOptions; + }; + /** + * Get all class names for all parents in the element. Iterates until finds + * main container. + * + * @function Highcharts.NavigationBindings#getClickedClassNames + * + * @param {Highcharts.HTMLDOMElement} + * Container that event is bound to. + * + * @param {global.Event} event + * Browser's event. + * + * @return {Array>} + * Array of class names with corresponding elements + */ + NavigationBindings.prototype.getClickedClassNames = function (container, event) { + var element = event.target, + classNames = [], + elemClassName; + while (element) { + elemClassName = attr(element, 'class'); + if (elemClassName) { + classNames = classNames.concat(elemClassName + .split(' ') + .map(function (name) { + return [ + name, + element + ]; + })); + } + element = element.parentNode; + if (element === container) { + return classNames; + } + } + return classNames; + }; + /** + * Get events bound to a button. It's a custom event delegation to find all + * events connected to the element. + * + * @private + * @function Highcharts.NavigationBindings#getButtonEvents + * + * @param {Highcharts.HTMLDOMElement} container + * Container that event is bound to. + * + * @param {global.Event} event + * Browser's event. + * + * @return {object} + * Object with events (init, start, steps, and end) + */ + NavigationBindings.prototype.getButtonEvents = function (container, event) { + var navigation = this, + classNames = this.getClickedClassNames(container, + event), + bindings; + classNames.forEach(function (className) { + if (navigation.boundClassNames[className[0]] && !bindings) { + bindings = { + events: navigation.boundClassNames[className[0]], + button: className[1] + }; + } + }); + return bindings; + }; + /** + * Bindings are just events, so the whole update process is simply + * removing old events and adding new ones. + * + * @private + * @function Highcharts.NavigationBindings#update + */ + NavigationBindings.prototype.update = function (options) { + this.options = merge(true, this.options, options); + this.removeEvents(); + this.initEvents(); + }; + /** + * Remove all events created in the navigation. + * + * @private + * @function Highcharts.NavigationBindings#removeEvents + */ + NavigationBindings.prototype.removeEvents = function () { + this.eventsToUnbind.forEach(function (unbinder) { + unbinder(); + }); + }; + NavigationBindings.prototype.destroy = function () { + this.removeEvents(); + }; + /* * + * + * Static Properties + * + * */ + // Define which options from annotations should show up in edit box: + NavigationBindings.annotationsEditable = { + // `typeOptions` are always available + // Nested and shared options: + nestedOptions: { + labelOptions: ['style', 'format', 'backgroundColor'], + labels: ['style'], + label: ['style'], + style: ['fontSize', 'color'], + background: ['fill', 'strokeWidth', 'stroke'], + innerBackground: ['fill', 'strokeWidth', 'stroke'], + outerBackground: ['fill', 'strokeWidth', 'stroke'], + shapeOptions: ['fill', 'strokeWidth', 'stroke'], + shapes: ['fill', 'strokeWidth', 'stroke'], + line: ['strokeWidth', 'stroke'], + backgroundColors: [true], + connector: ['fill', 'strokeWidth', 'stroke'], + crosshairX: ['strokeWidth', 'stroke'], + crosshairY: ['strokeWidth', 'stroke'] + }, + // Simple shapes: + circle: ['shapes'], + verticalLine: [], + label: ['labelOptions'], + // Measure + measure: ['background', 'crosshairY', 'crosshairX'], + // Others: + fibonacci: [], + tunnel: ['background', 'line', 'height'], + pitchfork: ['innerBackground', 'outerBackground'], + rect: ['shapes'], + // Crooked lines, elliots, arrows etc: + crookedLine: [], + basicAnnotation: ['shapes', 'labelOptions'] + }; + // Define non editable fields per annotation, for example Rectangle inherits + // options from Measure, but crosshairs are not available + NavigationBindings.annotationsNonEditable = { + rectangle: ['crosshairX', 'crosshairY', 'label'] + }; + return NavigationBindings; + }()); + /** + * General utils for bindings + * + * @private + * @name Highcharts.NavigationBindings.utils + * @type {bindingsUtils} + */ + NavigationBindings.prototype.utils = bindingsUtils; + H.Chart.prototype.initNavigationBindings = function () { + var chart = this, + options = chart.options; + if (options && options.navigation && options.navigation.bindings) { + chart.navigationBindings = new NavigationBindings(chart, options.navigation); + chart.navigationBindings.initEvents(); + chart.navigationBindings.initUpdate(); + } + }; + addEvent(H.Chart, 'load', function () { + this.initNavigationBindings(); + }); + addEvent(H.Chart, 'destroy', function () { + if (this.navigationBindings) { + this.navigationBindings.destroy(); + } + }); + addEvent(NavigationBindings, 'deselectButton', function () { + this.selectedButtonElement = null; + }); + addEvent(Annotation, 'remove', function () { + if (this.chart.navigationBindings) { + this.chart.navigationBindings.deselectAnnotation(); + } + }); + /** + * Show edit-annotation form: + * @private + */ + function selectableAnnotation(annotationType) { + var originalClick = annotationType.prototype.defaultOptions.events && + annotationType.prototype.defaultOptions.events.click; + /** + * @private + */ + function selectAndshowPopup(event) { + var annotation = this, + navigation = annotation.chart.navigationBindings, + prevAnnotation = navigation.activeAnnotation; + if (originalClick) { + originalClick.call(annotation, event); + } + if (prevAnnotation !== annotation) { + // Select current: + navigation.deselectAnnotation(); + navigation.activeAnnotation = annotation; + annotation.setControlPointsVisibility(true); + fireEvent(navigation, 'showPopup', { + annotation: annotation, + formType: 'annotation-toolbar', + options: navigation.annotationToFields(annotation), + onSubmit: function (data) { + var config = {}, + typeOptions; + if (data.actionType === 'remove') { + navigation.activeAnnotation = false; + navigation.chart.removeAnnotation(annotation); + } + else { + navigation.fieldsToOptions(data.fields, config); + navigation.deselectAnnotation(); + typeOptions = config.typeOptions; + if (annotation.options.type === 'measure') { + // Manually disable crooshars according to + // stroke width of the shape: + typeOptions.crosshairY.enabled = + typeOptions.crosshairY.strokeWidth !== 0; + typeOptions.crosshairX.enabled = + typeOptions.crosshairX.strokeWidth !== 0; + } + annotation.update(config); + } + } + }); + } + else { + // Deselect current: + navigation.deselectAnnotation(); + fireEvent(navigation, 'closePopup'); + } + // Let bubble event to chart.click: + event.activeAnnotation = true; + } + merge(true, annotationType.prototype.defaultOptions.events, { + click: selectAndshowPopup + }); + } + if (H.Annotation) { + // Basic shapes: + selectableAnnotation(Annotation); + // Advanced annotations: + objectEach(Annotation.types, function (annotationType) { + selectableAnnotation(annotationType); + }); + } + setOptions({ + /** + * @optionparent lang + * + * @private + */ + lang: { + /** + * Configure the Popup strings in the chart. Requires the + * `annotations.js` or `annotations-advanced.src.js` module to be + * loaded. + * + * @since 7.0.0 + * @product highcharts highstock + */ + navigation: { + /** + * Translations for all field names used in popup. + * + * @product highcharts highstock + */ + popup: { + simpleShapes: 'Simple shapes', + lines: 'Lines', + circle: 'Circle', + rectangle: 'Rectangle', + label: 'Label', + shapeOptions: 'Shape options', + typeOptions: 'Details', + fill: 'Fill', + format: 'Text', + strokeWidth: 'Line width', + stroke: 'Line color', + title: 'Title', + name: 'Name', + labelOptions: 'Label options', + labels: 'Labels', + backgroundColor: 'Background color', + backgroundColors: 'Background colors', + borderColor: 'Border color', + borderRadius: 'Border radius', + borderWidth: 'Border width', + style: 'Style', + padding: 'Padding', + fontSize: 'Font size', + color: 'Color', + height: 'Height', + shapes: 'Shape options' + } + } + }, + /** + * @optionparent navigation + * @product highcharts highstock + * + * @private + */ + navigation: { + /** + * A CSS class name where all bindings will be attached to. Multiple + * charts on the same page should have separate class names to prevent + * duplicating events. + * + * Default value of versions < 7.0.4 `highcharts-bindings-wrapper` + * + * @since 7.0.0 + * @type {string} + */ + bindingsClassName: 'highcharts-bindings-container', + /** + * Bindings definitions for custom HTML buttons. Each binding implements + * simple event-driven interface: + * + * - `className`: classname used to bind event to + * + * - `init`: initial event, fired on button click + * + * - `start`: fired on first click on a chart + * + * - `steps`: array of sequential events fired one after another on each + * of users clicks + * + * - `end`: last event to be called after last step event + * + * @type {Highcharts.Dictionary|*} + * @sample stock/stocktools/stocktools-thresholds + * Custom bindings in Highstock + * @since 7.0.0 + * @product highcharts highstock + */ + bindings: { + /** + * A circle annotation bindings. Includes `start` and one event in + * `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @default {"className": "highcharts-circle-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + circleAnnotation: { + /** @ignore-option */ + className: 'highcharts-circle-annotation', + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), + navigation = this.chart.options.navigation; + return this.chart.addAnnotation(merge({ + langKey: 'circle', + type: 'basicAnnotation', + shapes: [{ + type: 'circle', + point: { + xAxis: 0, + yAxis: 0, + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, + r: 5 + }] + }, navigation + .annotationsOptions, navigation + .bindings + .circleAnnotation + .annotationsOptions)); + }, + /** @ignore-option */ + steps: [ + function (e, annotation) { + var point = annotation.options.shapes[0].point, + x = this.chart.xAxis[0].toPixels(point.x), + y = this.chart.yAxis[0].toPixels(point.y), + inverted = this.chart.inverted, + distance = Math.max(Math.sqrt(Math.pow(inverted ? y - e.chartX : x - e.chartX, 2) + + Math.pow(inverted ? x - e.chartY : y - e.chartY, 2)), 5); + annotation.update({ + shapes: [{ + r: distance + }] + }); + } + ] + }, + /** + * A rectangle annotation bindings. Includes `start` and one event + * in `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @default {"className": "highcharts-rectangle-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + rectangleAnnotation: { + /** @ignore-option */ + className: 'highcharts-rectangle-annotation', + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), + navigation = this.chart.options.navigation, + x = coords.xAxis[0].value, + y = coords.yAxis[0].value; + return this.chart.addAnnotation(merge({ + langKey: 'rectangle', + type: 'basicAnnotation', + shapes: [{ + type: 'path', + points: [{ + xAxis: 0, + yAxis: 0, + x: x, + y: y + }, { + xAxis: 0, + yAxis: 0, + x: x, + y: y + }, { + xAxis: 0, + yAxis: 0, + x: x, + y: y + }, { + xAxis: 0, + yAxis: 0, + x: x, + y: y + }] + }] + }, navigation + .annotationsOptions, navigation + .bindings + .rectangleAnnotation + .annotationsOptions)); + }, + /** @ignore-option */ + steps: [ + function (e, annotation) { + var points = annotation.options.shapes[0].points, + coords = this.chart.pointer.getCoordinates(e), + x = coords.xAxis[0].value, + y = coords.yAxis[0].value; + // Top right point + points[1].x = x; + // Bottom right point (cursor position) + points[2].x = x; + points[2].y = y; + // Bottom left + points[3].y = y; + annotation.update({ + shapes: [{ + points: points + }] + }); + } + ] + }, + /** + * A label annotation bindings. Includes `start` event only. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @default {"className": "highcharts-label-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + labelAnnotation: { + /** @ignore-option */ + className: 'highcharts-label-annotation', + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), + navigation = this.chart.options.navigation; + return this.chart.addAnnotation(merge({ + langKey: 'label', + type: 'basicAnnotation', + labelOptions: { + format: '{y:.2f}' + }, + labels: [{ + point: { + xAxis: 0, + yAxis: 0, + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, + overflow: 'none', + crop: true + }] + }, navigation + .annotationsOptions, navigation + .bindings + .labelAnnotation + .annotationsOptions)); + } + } + }, + /** + * Path where Highcharts will look for icons. Change this to use icons + * from a different server. + * + * @type {string} + * @default https://code.highcharts.com/8.2.0/gfx/stock-icons/ + * @since 7.1.3 + * @apioption navigation.iconsURL + */ + /** + * A `showPopup` event. Fired when selecting for example an annotation. + * + * @type {Function} + * @apioption navigation.events.showPopup + */ + /** + * A `closePopup` event. Fired when Popup should be hidden, for example + * when clicking on an annotation again. + * + * @type {Function} + * @apioption navigation.events.closePopup + */ + /** + * Event fired on a button click. + * + * @type {Function} + * @sample highcharts/annotations/gui/ + * Change icon in a dropddown on event + * @sample highcharts/annotations/gui-buttons/ + * Change button class on event + * @apioption navigation.events.selectButton + */ + /** + * Event fired when button state should change, for example after + * adding an annotation. + * + * @type {Function} + * @sample highcharts/annotations/gui/ + * Change icon in a dropddown on event + * @sample highcharts/annotations/gui-buttons/ + * Change button class on event + * @apioption navigation.events.deselectButton + */ + /** + * Events to communicate between Stock Tools and custom GUI. + * + * @since 7.0.0 + * @product highcharts highstock + * @optionparent navigation.events + */ + events: {}, + /** + * Additional options to be merged into all annotations. + * + * @sample stock/stocktools/navigation-annotation-options + * Set red color of all line annotations + * + * @type {Highcharts.AnnotationsOptions} + * @extends annotations + * @exclude crookedLine, elliottWave, fibonacci, infinityLine, + * measure, pitchfork, tunnel, verticalLine, basicAnnotation + * @apioption navigation.annotationsOptions + */ + annotationsOptions: { + animation: { + defer: 0 + } + } + } + }); + + return NavigationBindings; + }); + _registerModule(_modules, 'Extensions/Annotations/Popup.js', [_modules['Core/Globals.js'], _modules['Extensions/Annotations/NavigationBindings.js'], _modules['Core/Pointer.js'], _modules['Core/Utilities.js']], function (H, NavigationBindings, Pointer, U) { + /* * + * + * Popup generator for Stock tools + * + * (c) 2009-2017 Sebastian Bochan + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + createElement = U.createElement, + defined = U.defined, + getOptions = U.getOptions, + isArray = U.isArray, + isObject = U.isObject, + isString = U.isString, + objectEach = U.objectEach, + pick = U.pick, + wrap = U.wrap; + var indexFilter = /\d/g, PREFIX = 'highcharts-', DIV = 'div', INPUT = 'input', LABEL = 'label', BUTTON = 'button', SELECT = 'select', OPTION = 'option', SPAN = 'span', UL = 'ul', LI = 'li', H3 = 'h3'; + /* eslint-disable no-invalid-this, valid-jsdoc */ + // onContainerMouseDown blocks internal popup events, due to e.preventDefault. + // Related issue #4606 + wrap(Pointer.prototype, 'onContainerMouseDown', function (proceed, e) { + var popupClass = e.target && e.target.className; + // elements is not in popup + if (!(isString(popupClass) && + popupClass.indexOf(PREFIX + 'popup-field') >= 0)) { + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + } + }); + H.Popup = function (parentDiv, iconsURL) { + this.init(parentDiv, iconsURL); + }; + H.Popup.prototype = { + /** + * Initialize the popup. Create base div and add close button. + * @private + * @param {Highcharts.HTMLDOMElement} parentDiv + * Container where popup should be placed + * @param {string} iconsURL + * Icon URL + */ + init: function (parentDiv, iconsURL) { + // create popup div + this.container = createElement(DIV, { + className: PREFIX + 'popup' + }, null, parentDiv); + this.lang = this.getLangpack(); + this.iconsURL = iconsURL; + // add close button + this.addCloseBtn(); + }, + /** + * Create HTML element and attach click event (close popup). + * @private + */ + addCloseBtn: function () { + var _self = this, + closeBtn; + // create close popup btn + closeBtn = createElement(DIV, { + className: PREFIX + 'popup-close' + }, null, this.container); + closeBtn.style['background-image'] = 'url(' + + this.iconsURL + 'close.svg)'; + ['click', 'touchstart'].forEach(function (eventName) { + addEvent(closeBtn, eventName, function () { + _self.closePopup(); + }); + }); + }, + /** + * Create two columns (divs) in HTML. + * @private + * @param {Highcharts.HTMLDOMElement} container + * Container of columns + * @return {Highcharts.Dictionary} + * Reference to two HTML columns (lhsCol, rhsCol) + */ + addColsContainer: function (container) { + var rhsCol, + lhsCol; + // left column + lhsCol = createElement(DIV, { + className: PREFIX + 'popup-lhs-col' + }, null, container); + // right column + rhsCol = createElement(DIV, { + className: PREFIX + 'popup-rhs-col' + }, null, container); + // wrapper content + createElement(DIV, { + className: PREFIX + 'popup-rhs-col-wrapper' + }, null, rhsCol); + return { + lhsCol: lhsCol, + rhsCol: rhsCol + }; + }, + /** + * Create input with label. + * @private + * @param {string} option + * Chain of fields i.e params.styles.fontSize + * @param {string} type + * Indicator type + * @param {Highhcharts.HTMLDOMElement} + * Container where elements should be added + * @param {string} value + * Default value of input i.e period value is 14, extracted from + * defaultOptions (ADD mode) or series options (EDIT mode) + */ + addInput: function (option, type, parentDiv, value) { + var optionParamList = option.split('.'), optionName = optionParamList[optionParamList.length - 1], lang = this.lang, inputName = PREFIX + type + '-' + optionName; + if (!inputName.match(indexFilter)) { + // add label + createElement(LABEL, { + innerHTML: lang[optionName] || optionName, + htmlFor: inputName + }, null, parentDiv); + } + // add input + createElement(INPUT, { + name: inputName, + value: value[0], + type: value[1], + className: PREFIX + 'popup-field' + }, null, parentDiv).setAttribute(PREFIX + 'data-name', option); + }, + /** + * Create button. + * @private + * @param {Highcharts.HTMLDOMElement} parentDiv + * Container where elements should be added + * @param {string} label + * Text placed as button label + * @param {string} type + * add | edit | remove + * @param {Function} callback + * On click callback + * @param {Highcharts.HTMLDOMElement} fieldsDiv + * Container where inputs are generated + * @return {Highcharts.HTMLDOMElement} + * HTML button + */ + addButton: function (parentDiv, label, type, callback, fieldsDiv) { + var _self = this, + closePopup = this.closePopup, + getFields = this.getFields, + button; + button = createElement(BUTTON, { + innerHTML: label + }, null, parentDiv); + ['click', 'touchstart'].forEach(function (eventName) { + addEvent(button, eventName, function () { + closePopup.call(_self); + return callback(getFields(fieldsDiv, type)); + }); + }); + return button; + }, + /** + * Get values from all inputs and create JSON. + * @private + * @param {Highcharts.HTMLDOMElement} - container where inputs are created + * @param {string} - add | edit | remove + * @return {Highcharts.PopupFieldsObject} - fields + */ + getFields: function (parentDiv, type) { + var inputList = parentDiv.querySelectorAll('input'), optionSeries = '#' + PREFIX + 'select-series > option:checked', optionVolume = '#' + PREFIX + 'select-volume > option:checked', linkedTo = parentDiv.querySelectorAll(optionSeries)[0], volumeTo = parentDiv.querySelectorAll(optionVolume)[0], seriesId, param, fieldsOutput; + fieldsOutput = { + actionType: type, + linkedTo: linkedTo && linkedTo.getAttribute('value'), + fields: {} + }; + [].forEach.call(inputList, function (input) { + param = input.getAttribute(PREFIX + 'data-name'); + seriesId = input.getAttribute(PREFIX + 'data-series-id'); + // params + if (seriesId) { + fieldsOutput.seriesId = input.value; + } + else if (param) { + fieldsOutput.fields[param] = input.value; + } + else { + // type like sma / ema + fieldsOutput.type = input.value; + } + }); + if (volumeTo) { + fieldsOutput.fields['params.volumeSeriesID'] = volumeTo.getAttribute('value'); + } + return fieldsOutput; + }, + /** + * Reset content of the current popup and show. + * @private + */ + showPopup: function () { + var popupDiv = this.container, + toolbarClass = PREFIX + 'annotation-toolbar', + popupCloseBtn = popupDiv + .querySelectorAll('.' + PREFIX + 'popup-close')[0]; + // reset content + popupDiv.innerHTML = ''; + // reset toolbar styles if exists + if (popupDiv.className.indexOf(toolbarClass) >= 0) { + popupDiv.classList.remove(toolbarClass); + // reset toolbar inline styles + popupDiv.removeAttribute('style'); + } + // add close button + popupDiv.appendChild(popupCloseBtn); + popupDiv.style.display = 'block'; + }, + /** + * Hide popup. + * @private + */ + closePopup: function () { + this.popup.container.style.display = 'none'; + }, + /** + * Create content and show popup. + * @private + * @param {string} - type of popup i.e indicators + * @param {Highcharts.Chart} - chart + * @param {Highcharts.AnnotationsOptions} - options + * @param {Function} - on click callback + */ + showForm: function (type, chart, options, callback) { + this.popup = chart.navigationBindings.popup; + // show blank popup + this.showPopup(); + // indicator form + if (type === 'indicators') { + this.indicators.addForm.call(this, chart, options, callback); + } + // annotation small toolbar + if (type === 'annotation-toolbar') { + this.annotations.addToolbar.call(this, chart, options, callback); + } + // annotation edit form + if (type === 'annotation-edit') { + this.annotations.addForm.call(this, chart, options, callback); + } + // flags form - add / edit + if (type === 'flag') { + this.annotations.addForm.call(this, chart, options, callback, true); + } + }, + /** + * Return lang definitions for popup. + * @private + * @return {Highcharts.Dictionary} - elements translations. + */ + getLangpack: function () { + return getOptions().lang.navigation.popup; + }, + annotations: { + /** + * Create annotation simple form. It contains two buttons + * (edit / remove) and text label. + * @private + * @param {Highcharts.Chart} - chart + * @param {Highcharts.AnnotationsOptions} - options + * @param {Function} - on click callback + */ + addToolbar: function (chart, options, callback) { + var _self = this, + lang = this.lang, + popupDiv = this.popup.container, + showForm = this.showForm, + toolbarClass = PREFIX + 'annotation-toolbar', + button; + // set small size + if (popupDiv.className.indexOf(toolbarClass) === -1) { + popupDiv.className += ' ' + toolbarClass; + } + // set position + popupDiv.style.top = chart.plotTop + 10 + 'px'; + // create label + createElement(SPAN, { + innerHTML: pick( + // Advanced annotations: + lang[options.langKey] || options.langKey, + // Basic shapes: + options.shapes && options.shapes[0].type) + }, null, popupDiv); + // add buttons + button = this.addButton(popupDiv, lang.removeButton || 'remove', 'remove', callback, popupDiv); + button.className += ' ' + PREFIX + 'annotation-remove-button'; + button.style['background-image'] = 'url(' + + this.iconsURL + 'destroy.svg)'; + button = this.addButton(popupDiv, lang.editButton || 'edit', 'edit', function () { + showForm.call(_self, 'annotation-edit', chart, options, callback); + }, popupDiv); + button.className += ' ' + PREFIX + 'annotation-edit-button'; + button.style['background-image'] = 'url(' + + this.iconsURL + 'edit.svg)'; + }, + /** + * Create annotation simple form. + * It contains fields with param names. + * @private + * @param {Highcharts.Chart} chart + * Chart + * @param {Object} options + * Options + * @param {Function} callback + * On click callback + * @param {boolean} [isInit] + * If it is a form declared for init annotation + */ + addForm: function (chart, options, callback, isInit) { + var popupDiv = this.popup.container, + lang = this.lang, + bottomRow, + lhsCol; + // create title of annotations + lhsCol = createElement('h2', { + innerHTML: lang[options.langKey] || options.langKey, + className: PREFIX + 'popup-main-title' + }, null, popupDiv); + // left column + lhsCol = createElement(DIV, { + className: PREFIX + 'popup-lhs-col ' + PREFIX + 'popup-lhs-full' + }, null, popupDiv); + bottomRow = createElement(DIV, { + className: PREFIX + 'popup-bottom-row' + }, null, popupDiv); + this.annotations.addFormFields.call(this, lhsCol, chart, '', options, [], true); + this.addButton(bottomRow, isInit ? + (lang.addButton || 'add') : + (lang.saveButton || 'save'), isInit ? 'add' : 'save', callback, popupDiv); + }, + /** + * Create annotation's form fields. + * @private + * @param {Highcharts.HTMLDOMElement} parentDiv + * Div where inputs are placed + * @param {Highcharts.Chart} chart + * Chart + * @param {string} parentNode + * Name of parent to create chain of names + * @param {Highcharts.AnnotationsOptions} options + * Options + * @param {Array} storage + * Array where all items are stored + * @param {boolean} [isRoot] + * Recursive flag for root + */ + addFormFields: function (parentDiv, chart, parentNode, options, storage, isRoot) { + var _self = this, + addFormFields = this.annotations.addFormFields, + addInput = this.addInput, + lang = this.lang, + parentFullName, + titleName; + objectEach(options, function (value, option) { + // create name like params.styles.fontSize + parentFullName = parentNode !== '' ? + parentNode + '.' + option : option; + if (isObject(value)) { + if ( + // value is object of options + !isArray(value) || + // array of objects with params. i.e labels in Fibonacci + (isArray(value) && isObject(value[0]))) { + titleName = lang[option] || option; + if (!titleName.match(indexFilter)) { + storage.push([ + true, + titleName, + parentDiv + ]); + } + addFormFields.call(_self, parentDiv, chart, parentFullName, value, storage, false); + } + else { + storage.push([ + _self, + parentFullName, + 'annotation', + parentDiv, + value + ]); + } + } + }); + if (isRoot) { + storage = storage.sort(function (a) { + return a[1].match(/format/g) ? -1 : 1; + }); + storage.forEach(function (genInput) { + if (genInput[0] === true) { + createElement(SPAN, { + className: PREFIX + 'annotation-title', + innerHTML: genInput[1] + }, null, genInput[2]); + } + else { + addInput.apply(genInput[0], genInput.splice(1)); + } + }); + } + } + }, + indicators: { + /** + * Create indicator's form. It contains two tabs (ADD and EDIT) with + * content. + * @private + */ + addForm: function (chart, _options, callback) { + var tabsContainers, + indicators = this.indicators, + lang = this.lang, + buttonParentDiv; + // add tabs + this.tabs.init.call(this, chart); + // get all tabs content divs + tabsContainers = this.popup.container + .querySelectorAll('.' + PREFIX + 'tab-item-content'); + // ADD tab + this.addColsContainer(tabsContainers[0]); + indicators.addIndicatorList.call(this, chart, tabsContainers[0], 'add'); + buttonParentDiv = tabsContainers[0] + .querySelectorAll('.' + PREFIX + 'popup-rhs-col')[0]; + this.addButton(buttonParentDiv, lang.addButton || 'add', 'add', callback, buttonParentDiv); + // EDIT tab + this.addColsContainer(tabsContainers[1]); + indicators.addIndicatorList.call(this, chart, tabsContainers[1], 'edit'); + buttonParentDiv = tabsContainers[1] + .querySelectorAll('.' + PREFIX + 'popup-rhs-col')[0]; + this.addButton(buttonParentDiv, lang.saveButton || 'save', 'edit', callback, buttonParentDiv); + this.addButton(buttonParentDiv, lang.removeButton || 'remove', 'remove', callback, buttonParentDiv); + }, + /** + * Create HTML list of all indicators (ADD mode) or added indicators + * (EDIT mode). + * @private + */ + addIndicatorList: function (chart, parentDiv, listType) { + var _self = this, lhsCol = parentDiv.querySelectorAll('.' + PREFIX + 'popup-lhs-col')[0], rhsCol = parentDiv.querySelectorAll('.' + PREFIX + 'popup-rhs-col')[0], isEdit = listType === 'edit', series = (isEdit ? + chart.series : // EDIT mode + chart.options.plotOptions // ADD mode + ), addFormFields = this.indicators.addFormFields, rhsColWrapper, indicatorList, item; + // create wrapper for list + indicatorList = createElement(UL, { + className: PREFIX + 'indicator-list' + }, null, lhsCol); + rhsColWrapper = rhsCol + .querySelectorAll('.' + PREFIX + 'popup-rhs-col-wrapper')[0]; + objectEach(series, function (serie, value) { + var seriesOptions = serie.options; + if (serie.params || + seriesOptions && seriesOptions.params) { + var indicatorNameType = _self.indicators.getNameType(serie, + value), + indicatorType = indicatorNameType.type; + item = createElement(LI, { + className: PREFIX + 'indicator-list', + innerHTML: indicatorNameType.name + }, null, indicatorList); + ['click', 'touchstart'].forEach(function (eventName) { + addEvent(item, eventName, function () { + addFormFields.call(_self, chart, isEdit ? serie : series[indicatorType], indicatorNameType.type, rhsColWrapper); + // add hidden input with series.id + if (isEdit && serie.options) { + createElement(INPUT, { + type: 'hidden', + name: PREFIX + 'id-' + indicatorType, + value: serie.options.id + }, null, rhsColWrapper) + .setAttribute(PREFIX + 'data-series-id', serie.options.id); + } + }); + }); + } + }); + // select first item from the list + if (indicatorList.childNodes.length > 0) { + indicatorList.childNodes[0].click(); + } + }, + /** + * Extract full name and type of requested indicator. + * @private + * @param {Highcharts.Series} series + * Series which name is needed. (EDIT mode - defaultOptions.series, ADD + * mode - indicator series). + * @param {string} - indicator type like: sma, ema, etc. + * @return {Object} - series name and type like: sma, ema, etc. + */ + getNameType: function (series, type) { + var options = series.options, + seriesTypes = H.seriesTypes, + // add mode + seriesName = seriesTypes[type] && + seriesTypes[type].prototype.nameBase || type.toUpperCase(), + seriesType = type; + // edit + if (options && options.type) { + seriesType = series.options.type; + seriesName = series.name; + } + return { + name: seriesName, + type: seriesType + }; + }, + /** + * List all series with unique ID. Its mandatory for indicators to set + * correct linking. + * @private + * @param {string} type + * Indicator type like: sma, ema, etc. + * @param {string} optionName + * Type of select i.e series or volume. + * @param {Highcharts.Chart} chart + * Chart + * @param {Highcharts.HTMLDOMElement} parentDiv + * Element where created HTML list is added + * @param {string} selectedOption + * optional param for default value in dropdown + */ + listAllSeries: function (type, optionName, chart, parentDiv, selectedOption) { + var selectName = PREFIX + optionName + '-type-' + type, + lang = this.lang, + selectBox, + seriesOptions; + createElement(LABEL, { + innerHTML: lang[optionName] || optionName, + htmlFor: selectName + }, null, parentDiv); + // select type + selectBox = createElement(SELECT, { + name: selectName, + className: PREFIX + 'popup-field' + }, null, parentDiv); + selectBox.setAttribute('id', PREFIX + 'select-' + optionName); + // list all series which have id - mandatory for creating indicator + chart.series.forEach(function (serie) { + seriesOptions = serie.options; + if (!seriesOptions.params && + seriesOptions.id && + seriesOptions.id !== PREFIX + 'navigator-series') { + createElement(OPTION, { + innerHTML: seriesOptions.name || seriesOptions.id, + value: seriesOptions.id + }, null, selectBox); + } + }); + if (defined(selectedOption)) { + selectBox.value = selectedOption; + } + }, + /** + * Create typical inputs for chosen indicator. Fields are extracted from + * defaultOptions (ADD mode) or current indicator (ADD mode). Two extra + * fields are added: + * - hidden input - contains indicator type (required for callback) + * - select - list of series which can be linked with indicator + * @private + * @param {Highcharts.Chart} chart + * Chart + * @param {Highcharts.Series} series + * Indicator + * @param {string} seriesType + * Indicator type like: sma, ema, etc. + * @param {Highcharts.HTMLDOMElement} rhsColWrapper + * Element where created HTML list is added + */ + addFormFields: function (chart, series, seriesType, rhsColWrapper) { + var fields = series.params || series.options.params, + getNameType = this.indicators.getNameType; + // reset current content + rhsColWrapper.innerHTML = ''; + // create title (indicator name in the right column) + createElement(H3, { + className: PREFIX + 'indicator-title', + innerHTML: getNameType(series, seriesType).name + }, null, rhsColWrapper); + // input type + createElement(INPUT, { + type: 'hidden', + name: PREFIX + 'type-' + seriesType, + value: seriesType + }, null, rhsColWrapper); + // list all series with id + this.indicators.listAllSeries.call(this, seriesType, 'series', chart, rhsColWrapper, series.linkedParent && fields.volumeSeriesID); + if (fields.volumeSeriesID) { + this.indicators.listAllSeries.call(this, seriesType, 'volume', chart, rhsColWrapper, series.linkedParent && series.linkedParent.options.id); + } + // add param fields + this.indicators.addParamInputs.call(this, chart, 'params', fields, seriesType, rhsColWrapper); + }, + /** + * Recurent function which lists all fields, from params object and + * create them as inputs. Each input has unique `data-name` attribute, + * which keeps chain of fields i.e params.styles.fontSize. + * @private + * @param {Highcharts.Chart} chart + * Chart + * @param {string} parentNode + * Name of parent to create chain of names + * @param {Highcharts.PopupFieldsDictionary} fields + * Params which are based for input create + * @param {string} type + * Indicator type like: sma, ema, etc. + * @param {Highcharts.HTMLDOMElement} parentDiv + * Element where created HTML list is added + */ + addParamInputs: function (chart, parentNode, fields, type, parentDiv) { + var _self = this, + addParamInputs = this.indicators.addParamInputs, + addInput = this.addInput, + parentFullName; + objectEach(fields, function (value, fieldName) { + // create name like params.styles.fontSize + parentFullName = parentNode + '.' + fieldName; + if (isObject(value)) { + addParamInputs.call(_self, chart, parentFullName, value, type, parentDiv); + } + else if ( + // skip volume field which is created by addFormFields + parentFullName !== 'params.volumeSeriesID') { + addInput.call(_self, parentFullName, type, parentDiv, [value, 'text'] // all inputs are text type + ); + } + }); + }, + /** + * Get amount of indicators added to chart. + * @private + * @return {number} - Amount of indicators + */ + getAmount: function () { + var series = this.series, + counter = 0; + series.forEach(function (serie) { + var seriesOptions = serie.options; + if (serie.params || + seriesOptions && seriesOptions.params) { + counter++; + } + }); + return counter; + } + }, + tabs: { + /** + * Init tabs. Create tab menu items, tabs containers + * @private + * @param {Highcharts.Chart} chart + * Reference to current chart + */ + init: function (chart) { + var tabs = this.tabs, + indicatorsCount = this.indicators.getAmount.call(chart), + firstTab; // run by default + // create menu items + firstTab = tabs.addMenuItem.call(this, 'add'); + tabs.addMenuItem.call(this, 'edit', indicatorsCount); + // create tabs containers + tabs.addContentItem.call(this, 'add'); + tabs.addContentItem.call(this, 'edit'); + tabs.switchTabs.call(this, indicatorsCount); + // activate first tab + tabs.selectTab.call(this, firstTab, 0); + }, + /** + * Create tab menu item + * @private + * @param {string} tabName + * `add` or `edit` + * @param {number} [disableTab] + * Disable tab when 0 + * @return {Highcharts.HTMLDOMElement} + * Created HTML tab-menu element + */ + addMenuItem: function (tabName, disableTab) { + var popupDiv = this.popup.container, + className = PREFIX + 'tab-item', + lang = this.lang, + menuItem; + if (disableTab === 0) { + className += ' ' + PREFIX + 'tab-disabled'; + } + // tab 1 + menuItem = createElement(SPAN, { + innerHTML: lang[tabName + 'Button'] || tabName, + className: className + }, null, popupDiv); + menuItem.setAttribute(PREFIX + 'data-tab-type', tabName); + return menuItem; + }, + /** + * Create tab content + * @private + * @return {HTMLDOMElement} - created HTML tab-content element + */ + addContentItem: function () { + var popupDiv = this.popup.container; + return createElement(DIV, { + className: PREFIX + 'tab-item-content' + }, null, popupDiv); + }, + /** + * Add click event to each tab + * @private + * @param {number} disableTab + * Disable tab when 0 + */ + switchTabs: function (disableTab) { + var _self = this, + popupDiv = this.popup.container, + tabs = popupDiv.querySelectorAll('.' + PREFIX + 'tab-item'), + dataParam; + tabs.forEach(function (tab, i) { + dataParam = tab.getAttribute(PREFIX + 'data-tab-type'); + if (dataParam === 'edit' && disableTab === 0) { + return; + } + ['click', 'touchstart'].forEach(function (eventName) { + addEvent(tab, eventName, function () { + // reset class on other elements + _self.tabs.deselectAll.call(_self); + _self.tabs.selectTab.call(_self, this, i); + }); + }); + }); + }, + /** + * Set tab as visible + * @private + * @param {globals.Element} - current tab + * @param {number} - Index of tab in menu + */ + selectTab: function (tab, index) { + var allTabs = this.popup.container + .querySelectorAll('.' + PREFIX + 'tab-item-content'); + tab.className += ' ' + PREFIX + 'tab-item-active'; + allTabs[index].className += ' ' + PREFIX + 'tab-item-show'; + }, + /** + * Set all tabs as invisible. + * @private + */ + deselectAll: function () { + var popupDiv = this.popup.container, + tabs = popupDiv + .querySelectorAll('.' + PREFIX + 'tab-item'), + tabsContent = popupDiv + .querySelectorAll('.' + PREFIX + 'tab-item-content'), + i; + for (i = 0; i < tabs.length; i++) { + tabs[i].classList.remove(PREFIX + 'tab-item-active'); + tabsContent[i].classList.remove(PREFIX + 'tab-item-show'); + } + } + } + }; + addEvent(NavigationBindings, 'showPopup', function (config) { + if (!this.popup) { + // Add popup to main container + this.popup = new H.Popup(this.chart.container, (this.chart.options.navigation.iconsURL || + (this.chart.options.stockTools && + this.chart.options.stockTools.gui.iconsURL) || + 'https://code.highcharts.com/8.2.0/gfx/stock-icons/')); + } + this.popup.showForm(config.formType, this.chart, config.options, config.onSubmit); + }); + addEvent(NavigationBindings, 'closePopup', function () { + if (this.popup) { + this.popup.closePopup(); + } + }); + + }); + _registerModule(_modules, 'masters/modules/annotations-advanced.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/annotations.js b/highcharts/modules/annotations.js new file mode 100644 index 0000000..d10e61c --- /dev/null +++ b/highcharts/modules/annotations.js @@ -0,0 +1,114 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Annotations module + + (c) 2009-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/annotations",["highcharts"],function(v){a(v);a.Highcharts=v;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function v(c,a,p,g){c.hasOwnProperty(a)||(c[a]=g.apply(null,p))}a=a?a._modules:{};v(a,"Extensions/Annotations/Mixins/EventEmitterMixin.js",[a["Core/Globals.js"],a["Core/Utilities.js"]],function(c,a){var k=a.addEvent, +g=a.fireEvent,z=a.objectEach,b=a.pick,A=a.removeEvent;return{addEvents:function(){var b=this,d=function(d){k(d,c.isTouchDevice?"touchstart":"mousedown",function(d){b.onMouseDown(d)})};d(this.graphic.element);(b.labels||[]).forEach(function(b){b.options.useHTML&&b.graphic.text&&d(b.graphic.text.element)});z(b.options.events,function(d,e){var l=function(l){"click"===e&&b.cancelClick||d.call(b,b.chart.pointer.normalize(l),b.target)};if(-1===(b.nonDOMEvents||[]).indexOf(e))b.graphic.on(e,l);else k(b, +e,l)});if(b.options.draggable&&(k(b,"drag",b.onDrag),!b.graphic.renderer.styledMode)){var e={cursor:{x:"ew-resize",y:"ns-resize",xy:"move"}[b.options.draggable]};b.graphic.css(e);(b.labels||[]).forEach(function(d){d.options.useHTML&&d.graphic.text&&d.graphic.text.css(e)})}b.isUpdating||g(b,"add")},removeDocEvents:function(){this.removeDrag&&(this.removeDrag=this.removeDrag());this.removeMouseUp&&(this.removeMouseUp=this.removeMouseUp())},onMouseDown:function(t){var d=this,e=d.chart.pointer;t.preventDefault&& +t.preventDefault();if(2!==t.button){t=e.normalize(t);var u=t.chartX;var l=t.chartY;d.cancelClick=!1;d.chart.hasDraggedAnnotation=!0;d.removeDrag=k(c.doc,c.isTouchDevice?"touchmove":"mousemove",function(b){d.hasDragged=!0;b=e.normalize(b);b.prevChartX=u;b.prevChartY=l;g(d,"drag",b);u=b.chartX;l=b.chartY});d.removeMouseUp=k(c.doc,c.isTouchDevice?"touchend":"mouseup",function(e){d.cancelClick=d.hasDragged;d.hasDragged=!1;d.chart.hasDraggedAnnotation=!1;g(b(d.target,d),"afterUpdate");d.onMouseUp(e)})}}, +onMouseUp:function(b){var d=this.chart;b=this.target||this;var e=d.options.annotations;d=d.annotations.indexOf(b);this.removeDocEvents();e[d]=b.options},onDrag:function(b){if(this.chart.isInsidePlot(b.chartX-this.chart.plotLeft,b.chartY-this.chart.plotTop)){var d=this.mouseMoveToTranslation(b);"x"===this.options.draggable&&(d.y=0);"y"===this.options.draggable&&(d.x=0);this.points.length?this.translate(d.x,d.y):(this.shapes.forEach(function(b){b.translate(d.x,d.y)}),this.labels.forEach(function(b){b.translate(d.x, +d.y)}));this.redraw(!1)}},mouseMoveToRadians:function(b,d,e){var c=b.prevChartY-e,l=b.prevChartX-d;e=b.chartY-e;b=b.chartX-d;this.chart.inverted&&(d=l,l=c,c=d,d=b,b=e,e=d);return Math.atan2(e,b)-Math.atan2(c,l)},mouseMoveToTranslation:function(b){var d=b.chartX-b.prevChartX;b=b.chartY-b.prevChartY;if(this.chart.inverted){var e=b;b=d;d=e}return{x:d,y:b}},mouseMoveToScale:function(b,d,e){d=(b.chartX-d||1)/(b.prevChartX-d||1);b=(b.chartY-e||1)/(b.prevChartY-e||1);this.chart.inverted&&(e=b,b=d,d=e);return{x:d, +y:b}},destroy:function(){this.removeDocEvents();A(this);this.hcEvents=null}}});v(a,"Extensions/Annotations/ControlPoint.js",[a["Core/Utilities.js"],a["Extensions/Annotations/Mixins/EventEmitterMixin.js"]],function(c,a){var k=c.merge,g=c.pick;return function(){function c(b,c,t,d){this.addEvents=a.addEvents;this.graphic=void 0;this.mouseMoveToRadians=a.mouseMoveToRadians;this.mouseMoveToScale=a.mouseMoveToScale;this.mouseMoveToTranslation=a.mouseMoveToTranslation;this.onDrag=a.onDrag;this.onMouseDown= +a.onMouseDown;this.onMouseUp=a.onMouseUp;this.removeDocEvents=a.removeDocEvents;this.nonDOMEvents=["drag"];this.chart=b;this.target=c;this.options=t;this.index=g(t.index,d)}c.prototype.setVisibility=function(b){this.graphic.attr("visibility",b?"visible":"hidden");this.options.visible=b};c.prototype.render=function(){var b=this.chart,c=this.options;this.graphic=b.renderer.symbol(c.symbol,0,0,c.width,c.height).add(b.controlPointsGroup).css(c.style);this.setVisibility(c.visible);this.addEvents()};c.prototype.redraw= +function(b){this.graphic[b?"animate":"attr"](this.options.positioner.call(this,this.target))};c.prototype.destroy=function(){a.destroy.call(this);this.graphic&&(this.graphic=this.graphic.destroy());this.options=this.target=this.chart=null};c.prototype.update=function(b){var c=this.chart,a=this.target,d=this.index;b=k(!0,this.options,b);this.destroy();this.constructor(c,a,b,d);this.render(c.controlPointsGroup);this.redraw()};return c}()});v(a,"Extensions/Annotations/MockPoint.js",[a["Core/Globals.js"], +a["Core/Utilities.js"]],function(c,a){var k=a.defined,g=a.fireEvent;return function(){function a(b,a,t){this.y=this.x=this.plotY=this.plotX=this.isInside=void 0;this.mock=!0;this.series={visible:!0,chart:b,getPlotBox:c.Series.prototype.getPlotBox};this.target=a||null;this.options=t;this.applyOptions(this.getOptions())}a.fromPoint=function(b){return new a(b.series.chart,null,{x:b.x,y:b.y,xAxis:b.series.xAxis,yAxis:b.series.yAxis})};a.pointToPixels=function(b,c){var a=b.series,d=a.chart,e=b.plotX,u= +b.plotY;d.inverted&&(b.mock?(e=b.plotY,u=b.plotX):(e=d.plotWidth-b.plotY,u=d.plotHeight-b.plotX));a&&!c&&(b=a.getPlotBox(),e+=b.translateX,u+=b.translateY);return{x:e,y:u}};a.pointToOptions=function(b){return{x:b.x,y:b.y,xAxis:b.series.xAxis,yAxis:b.series.yAxis}};a.prototype.hasDynamicOptions=function(){return"function"===typeof this.options};a.prototype.getOptions=function(){return this.hasDynamicOptions()?this.options(this.target):this.options};a.prototype.applyOptions=function(b){this.command= +b.command;this.setAxis(b,"x");this.setAxis(b,"y");this.refresh()};a.prototype.setAxis=function(b,a){a+="Axis";b=b[a];var t=this.series.chart;this.series[a]=b instanceof c.Axis?b:k(b)?t[a][b]||t.get(b):null};a.prototype.toAnchor=function(){var b=[this.plotX,this.plotY,0,0];this.series.chart.inverted&&(b[0]=this.plotY,b[1]=this.plotX);return b};a.prototype.getLabelConfig=function(){return{x:this.x,y:this.y,point:this}};a.prototype.isInsidePlot=function(){var b=this.plotX,c=this.plotY,a=this.series.xAxis, +d=this.series.yAxis,e={x:b,y:c,isInsidePlot:!0};a&&(e.isInsidePlot=k(b)&&0<=b&&b<=a.len);d&&(e.isInsidePlot=e.isInsidePlot&&k(c)&&0<=c&&c<=d.len);g(this.series.chart,"afterIsInsidePlot",e);return e.isInsidePlot};a.prototype.refresh=function(){var b=this.series,c=b.xAxis;b=b.yAxis;var a=this.getOptions();c?(this.x=a.x,this.plotX=c.toPixels(a.x,!0)):(this.x=null,this.plotX=a.x);b?(this.y=a.y,this.plotY=b.toPixels(a.y,!0)):(this.y=null,this.plotY=a.y);this.isInside=this.isInsidePlot()};a.prototype.translate= +function(b,c,a,d){this.hasDynamicOptions()||(this.plotX+=a,this.plotY+=d,this.refreshOptions())};a.prototype.scale=function(b,c,a,d){if(!this.hasDynamicOptions()){var e=this.plotY*d;this.plotX=(1-a)*b+this.plotX*a;this.plotY=(1-d)*c+e;this.refreshOptions()}};a.prototype.rotate=function(b,c,a){if(!this.hasDynamicOptions()){var d=Math.cos(a);a=Math.sin(a);var e=this.plotX,u=this.plotY;e-=b;u-=c;this.plotX=e*d-u*a+b;this.plotY=e*a+u*d+c;this.refreshOptions()}};a.prototype.refreshOptions=function(){var b= +this.series,c=b.xAxis;b=b.yAxis;this.x=this.options.x=c?this.options.x=c.toValue(this.plotX,!0):this.plotX;this.y=this.options.y=b?b.toValue(this.plotY,!0):this.plotY};return a}()});v(a,"Extensions/Annotations/Mixins/ControllableMixin.js",[a["Extensions/Annotations/ControlPoint.js"],a["Extensions/Annotations/MockPoint.js"],a["Core/Tooltip.js"],a["Core/Utilities.js"]],function(c,a,p,g){var k=g.isObject,b=g.isString,A=g.merge,t=g.splat;return{init:function(b,c,a){this.annotation=b;this.chart=b.chart; +this.options=c;this.points=[];this.controlPoints=[];this.index=a;this.linkPoints();this.addControlPoints()},attr:function(){this.graphic.attr.apply(this.graphic,arguments)},getPointsOptions:function(){var b=this.options;return b.points||b.point&&t(b.point)},attrsFromOptions:function(b){var c=this.constructor.attrsMap,d={},a,m=this.chart.styledMode;for(a in b){var q=c[a];!q||m&&-1!==["fill","stroke","stroke-width"].indexOf(q)||(d[q]=b[a])}return d},anchor:function(b){var c=b.series.getPlotBox();b= +b.mock?b.toAnchor():p.prototype.getAnchor.call({chart:b.series.chart},b);b={x:b[0]+(this.options.x||0),y:b[1]+(this.options.y||0),height:b[2]||0,width:b[3]||0};return{relativePosition:b,absolutePosition:A(b,{x:b.x+c.translateX,y:b.y+c.translateY})}},point:function(c,e){if(c&&c.series)return c;e&&null!==e.series||(k(c)?e=new a(this.chart,this,c):b(c)?e=this.chart.get(c)||null:"function"===typeof c&&(e=c.call(e,this),e=e.series?e:new a(this.chart,this,c)));return e},linkPoints:function(){var b=this.getPointsOptions(), +c=this.points,a=b&&b.length||0,l;for(l=0;ld&&("right"===f?a.align="left":a.x=-d);d=c+l.width-e;d>b.plotWidth&&("left"===f?a.align="right":a.x=b.plotWidth-d);d=g+e;0>d&&("bottom"=== +h?a.verticalAlign="top":a.y=-d);d=g+l.height-e;d>b.plotHeight&&("top"===h?a.verticalAlign="bottom":a.y=b.plotHeight-d);return a};e.prototype.translatePoint=function(b,c){a.translatePoint.call(this,b,c,0)};e.prototype.translate=function(b,a){var c=this.annotation.chart,d=this.annotation.userOptions,f=c.annotations.indexOf(this.annotation);f=c.options.annotations[f];c.inverted&&(c=b,b=a,a=c);this.options.x+=b;this.options.y+=a;f[this.collection][this.index].x=this.options.x;f[this.collection][this.index].y= +this.options.y;d[this.collection][this.index].x=this.options.x;d[this.collection][this.index].y=this.options.y};e.prototype.render=function(b){var c=this.options,d=this.attrsFromOptions(c),g=c.style;this.graphic=this.annotation.chart.renderer.label("",0,-9999,c.shape,null,null,c.useHTML,null,"annotation-label").attr(d).add(b);this.annotation.chart.styledMode||("contrast"===g.color&&(g.color=this.annotation.chart.renderer.getContrast(-1r&&(r=-d-r);ra+d?e.push(["L",b+h,a+d]):gb+c&&e.push(["L",b+c,a+d/2])}return e||[]};return z});v(a,"Extensions/Annotations/Controllables/ControllableImage.js", +[a["Extensions/Annotations/Controllables/ControllableLabel.js"],a["Extensions/Annotations/Mixins/ControllableMixin.js"]],function(a,k){return function(){function c(a,c,b){this.addControlPoints=k.addControlPoints;this.anchor=k.anchor;this.attr=k.attr;this.attrsFromOptions=k.attrsFromOptions;this.destroy=k.destroy;this.getPointsOptions=k.getPointsOptions;this.init=k.init;this.linkPoints=k.linkPoints;this.point=k.point;this.rotate=k.rotate;this.scale=k.scale;this.setControlPointsVisibility=k.setControlPointsVisibility; +this.shouldBeDrawn=k.shouldBeDrawn;this.transform=k.transform;this.transformPoint=k.transformPoint;this.translatePoint=k.translatePoint;this.translateShape=k.translateShape;this.update=k.update;this.type="image";this.translate=k.translateShape;this.init(a,c,b);this.collection="shapes"}c.prototype.render=function(a){var c=this.attrsFromOptions(this.options),b=this.options;this.graphic=this.annotation.chart.renderer.image(b.src,0,-9E9,b.width,b.height).attr(c).add(a);this.graphic.width=b.width;this.graphic.height= +b.height;k.render.call(this)};c.prototype.redraw=function(c){var g=this.anchor(this.points[0]);if(g=a.prototype.position.call(this,g))this.graphic[c?"animate":"attr"]({x:g.x,y:g.y});else this.graphic.attr({x:0,y:-9E9});this.graphic.placed=!!g;k.redraw.call(this,c)};c.attrsMap={width:"width",height:"height",zIndex:"zIndex"};return c}()});v(a,"Extensions/Annotations/Annotations.js",[a["Core/Chart/Chart.js"],a["Extensions/Annotations/Mixins/ControllableMixin.js"],a["Extensions/Annotations/Controllables/ControllableRect.js"], +a["Extensions/Annotations/Controllables/ControllableCircle.js"],a["Extensions/Annotations/Controllables/ControllablePath.js"],a["Extensions/Annotations/Controllables/ControllableImage.js"],a["Extensions/Annotations/Controllables/ControllableLabel.js"],a["Extensions/Annotations/ControlPoint.js"],a["Extensions/Annotations/Mixins/EventEmitterMixin.js"],a["Core/Globals.js"],a["Extensions/Annotations/MockPoint.js"],a["Core/Pointer.js"],a["Core/Utilities.js"]],function(a,k,p,g,z,b,v,t,d,e,u,l,m){a=a.prototype; +var c=m.addEvent,f=m.defined,h=m.destroyObjectProperties,w=m.erase,r=m.extend,B=m.find,n=m.fireEvent,y=m.getDeferredAnimation,x=m.merge,C=m.pick,E=m.splat;m=m.wrap;var D=function(){function a(a,b){this.annotation=void 0;this.coll="annotations";this.shapesGroup=this.labelsGroup=this.labelCollector=this.group=this.graphic=this.animationConfig=this.collection=void 0;this.chart=a;this.points=[];this.controlPoints=[];this.coll="annotations";this.labels=[];this.shapes=[];this.options=x(this.defaultOptions, +b);this.userOptions=b;b=this.getLabelsAndShapesOptions(this.options,b);this.options.labels=b.labels;this.options.shapes=b.shapes;this.init(a,this.options)}a.prototype.init=function(){var a=this.chart,b=this.options.animation;this.linkPoints();this.addControlPoints();this.addShapes();this.addLabels();this.setLabelCollector();this.animationConfig=y(a,b)};a.prototype.getLabelsAndShapesOptions=function(a,b){var c={};["labels","shapes"].forEach(function(d){a[d]&&(c[d]=E(b[d]).map(function(b,c){return x(a[d][c], +b)}))});return c};a.prototype.addShapes=function(){(this.options.shapes||[]).forEach(function(a,b){a=this.initShape(a,b);x(!0,this.options.shapes[b],a.options)},this)};a.prototype.addLabels=function(){(this.options.labels||[]).forEach(function(a,b){a=this.initLabel(a,b);x(!0,this.options.labels[b],a.options)},this)};a.prototype.addClipPaths=function(){this.setClipAxes();this.clipXAxis&&this.clipYAxis&&(this.clipRect=this.chart.renderer.clipRect(this.getClipBox()))};a.prototype.setClipAxes=function(){var a= +this.chart.xAxis,b=this.chart.yAxis,c=(this.options.labels||[]).concat(this.options.shapes||[]).reduce(function(c,d){return[a[d&&d.point&&d.point.xAxis]||c[0],b[d&&d.point&&d.point.yAxis]||c[1]]},[]);this.clipXAxis=c[0];this.clipYAxis=c[1]};a.prototype.getClipBox=function(){if(this.clipXAxis&&this.clipYAxis)return{x:this.clipXAxis.left,y:this.clipYAxis.top,width:this.clipXAxis.width,height:this.clipYAxis.height}};a.prototype.setLabelCollector=function(){var a=this;a.labelCollector=function(){return a.labels.reduce(function(a, +b){b.options.allowOverlap||a.push(b.graphic);return a},[])};a.chart.labelCollectors.push(a.labelCollector)};a.prototype.setOptions=function(a){this.options=x(this.defaultOptions,a)};a.prototype.redraw=function(a){this.linkPoints();this.graphic||this.render();this.clipRect&&this.clipRect.animate(this.getClipBox());this.redrawItems(this.shapes,a);this.redrawItems(this.labels,a);k.redraw.call(this,a)};a.prototype.redrawItems=function(a,b){for(var c=a.length;c--;)this.redrawItem(a[c],b)};a.prototype.renderItems= +function(a){for(var b=a.length;b--;)this.renderItem(a[b])};a.prototype.render=function(){var a=this.chart.renderer;this.graphic=a.g("annotation").attr({opacity:0,zIndex:this.options.zIndex,visibility:this.options.visible?"visible":"hidden"}).add();this.shapesGroup=a.g("annotation-shapes").add(this.graphic).clip(this.chart.plotBoxClip);this.labelsGroup=a.g("annotation-labels").attr({translateX:0,translateY:0}).add(this.graphic);this.addClipPaths();this.clipRect&&this.graphic.clip(this.clipRect);this.renderItems(this.shapes); +this.renderItems(this.labels);this.addEvents();k.render.call(this)};a.prototype.setVisibility=function(a){var b=this.options;a=C(a,!b.visible);this.graphic.attr("visibility",a?"visible":"hidden");a||this.setControlPointsVisibility(!1);b.visible=a};a.prototype.setControlPointsVisibility=function(a){var b=function(b){b.setControlPointsVisibility(a)};k.setControlPointsVisibility.call(this,a);this.shapes.forEach(b);this.labels.forEach(b)};a.prototype.destroy=function(){var a=this.chart,b=function(a){a.destroy()}; +this.labels.forEach(b);this.shapes.forEach(b);this.clipYAxis=this.clipXAxis=null;w(a.labelCollectors,this.labelCollector);d.destroy.call(this);k.destroy.call(this);h(this,a)};a.prototype.remove=function(){return this.chart.removeAnnotation(this)};a.prototype.update=function(a,b){var c=this.chart,d=this.getLabelsAndShapesOptions(this.userOptions,a),f=c.annotations.indexOf(this);a=x(!0,this.userOptions,a);a.labels=d.labels;a.shapes=d.shapes;this.destroy();this.constructor(c,a);c.options.annotations[f]= +a;this.isUpdating=!0;C(b,!0)&&c.redraw();n(this,"afterUpdate");this.isUpdating=!1};a.prototype.initShape=function(b,c){b=x(this.options.shapeOptions,{controlPointOptions:this.options.controlPointOptions},b);c=new a.shapesMap[b.type](this,b,c);c.itemType="shape";this.shapes.push(c);return c};a.prototype.initLabel=function(a,b){a=x(this.options.labelOptions,{controlPointOptions:this.options.controlPointOptions},a);b=new v(this,a,b);b.itemType="label";this.labels.push(b);return b};a.prototype.redrawItem= +function(a,b){a.linkPoints();a.shouldBeDrawn()?(a.graphic||this.renderItem(a),a.redraw(C(b,!0)&&a.graphic.placed),a.points.length&&this.adjustVisibility(a)):this.destroyItem(a)};a.prototype.adjustVisibility=function(a){var b=!1,c=a.graphic;a.points.forEach(function(a){!1!==a.series.visible&&!1!==a.visible&&(b=!0)});b?"hidden"===c.visibility&&c.show():c.hide()};a.prototype.destroyItem=function(a){w(this[a.itemType+"s"],a);a.destroy()};a.prototype.renderItem=function(a){a.render("label"===a.itemType? +this.labelsGroup:this.shapesGroup)};a.ControlPoint=t;a.MockPoint=u;a.shapesMap={rect:p,circle:g,path:z,image:b};a.types={};return a}();x(!0,D.prototype,k,d,x(D.prototype,{nonDOMEvents:["add","afterUpdate","drag","remove"],defaultOptions:{visible:!0,animation:{},draggable:"xy",labelOptions:{align:"center",allowOverlap:!1,backgroundColor:"rgba(0, 0, 0, 0.75)",borderColor:"black",borderRadius:3,borderWidth:1,className:"",crop:!1,formatter:function(){return f(this.y)?this.y:"Annotation label"},includeInDataExport:!0, +overflow:"justify",padding:5,shadow:!1,shape:"callout",style:{fontSize:"11px",fontWeight:"normal",color:"contrast"},useHTML:!1,verticalAlign:"bottom",x:0,y:-16},shapeOptions:{stroke:"rgba(0, 0, 0, 0.75)",strokeWidth:1,fill:"rgba(0, 0, 0, 0.75)",r:0,snap:2},controlPointOptions:{symbol:"circle",width:10,height:10,style:{stroke:"black","stroke-width":2,fill:"white"},visible:!1,events:{}},events:{},zIndex:6}}));e.extendAnnotation=function(a,b,c,d){b=b||D;x(!0,a.prototype,b.prototype,c);a.prototype.defaultOptions= +x(a.prototype.defaultOptions,d||{})};r(a,{initAnnotation:function(a){a=new (D.types[a.type]||D)(this,a);this.annotations.push(a);return a},addAnnotation:function(a,b){a=this.initAnnotation(a);this.options.annotations.push(a.options);C(b,!0)&&(a.redraw(),a.graphic.attr({opacity:1}));return a},removeAnnotation:function(a){var b=this.annotations,c="annotations"===a.coll?a:B(b,function(b){return b.options.id===a});c&&(n(c,"remove"),w(this.options.annotations,c.options),w(b,c),c.destroy())},drawAnnotations:function(){this.plotBoxClip.attr(this.plotBox); +this.annotations.forEach(function(a){a.redraw();a.graphic.animate({opacity:1},a.animationConfig)})}});a.collectionsWithUpdate.push("annotations");a.collectionsWithInit.annotations=[a.addAnnotation];a.callbacks.push(function(a){a.annotations=[];a.options.annotations||(a.options.annotations=[]);a.plotBoxClip=this.renderer.clipRect(this.plotBox);a.controlPointsGroup=a.renderer.g("control-points").attr({zIndex:99}).clip(a.plotBoxClip).add();a.options.annotations.forEach(function(b,c){b=a.initAnnotation(b); +a.options.annotations[c]=b.options});a.drawAnnotations();c(a,"redraw",a.drawAnnotations);c(a,"destroy",function(){a.plotBoxClip.destroy();a.controlPointsGroup.destroy()});c(a,"exportData",function(b){var c,d,f,e,h,n,x,y,g=a.annotations,C=(this.options.exporting&&this.options.exporting.csv||{}).columnHeaderFormatter,w=!b.dataRows[1].xValues,r=null===(d=null===(c=a.options.lang)||void 0===c?void 0:c.exportData)||void 0===d?void 0:d.annotationHeader;c=function(a){if(C){var b=C(a);if(!1!==b)return b}b= +r+" "+a;return w?{columnTitle:b,topLevelColumnTitle:b}:b};var k=b.dataRows[0].length,E=null===(h=null===(e=null===(f=a.options.exporting)||void 0===f?void 0:f.csv)||void 0===e?void 0:e.annotations)||void 0===h?void 0:h.itemDelimiter,B=null===(y=null===(x=null===(n=a.options.exporting)||void 0===n?void 0:n.csv)||void 0===x?void 0:x.annotations)||void 0===y?void 0:y.join;g.forEach(function(a){a.options.labelOptions.includeInDataExport&&a.labels.forEach(function(a){if(a.options.text){var c=a.options.text; +a.points.forEach(function(a){var d=a.x,f=a.series.xAxis?a.series.xAxis.options.index:-1,e=!1;if(-1===f){a=b.dataRows[0].length;for(var h=Array(a),n=0;nk?a[a.length-1]+=E+c:a.push(c),e=!0)});if(!e){a=b.dataRows[0].length;h=Array(a);for(n=0;n option:checked")[0];a=a.querySelectorAll("#highcharts-select-volume > option:checked")[0]; +var f,e;var h={actionType:b,linkedTo:d&&d.getAttribute("value"),fields:{}};[].forEach.call(c,function(a){e=a.getAttribute("highcharts-data-name");(f=a.getAttribute("highcharts-data-series-id"))?h.seriesId=a.value:e?h.fields[e]=a.value:h.type=a.value});a&&(h.fields["params.volumeSeriesID"]=a.getAttribute("value"));return h},showPopup:function(){var a=this.container,b=a.querySelectorAll(".highcharts-popup-close")[0];a.innerHTML="";0<=a.className.indexOf("highcharts-annotation-toolbar")&&(a.classList.remove("highcharts-annotation-toolbar"), +a.removeAttribute("style"));a.appendChild(b);a.style.display="block"},closePopup:function(){this.popup.container.style.display="none"},showForm:function(a,b,c,d){this.popup=b.navigationBindings.popup;this.showPopup();"indicators"===a&&this.indicators.addForm.call(this,b,c,d);"annotation-toolbar"===a&&this.annotations.addToolbar.call(this,b,c,d);"annotation-edit"===a&&this.annotations.addForm.call(this,b,c,d);"flag"===a&&this.annotations.addForm.call(this,b,c,d,!0)},getLangpack:function(){return t().lang.navigation.popup}, +annotations:{addToolbar:function(a,c,d){var f=this,e=this.lang,h=this.popup.container,g=this.showForm;-1===h.className.indexOf("highcharts-annotation-toolbar")&&(h.className+=" highcharts-annotation-toolbar");h.style.top=a.plotTop+10+"px";b("span",{innerHTML:m(e[c.langKey]||c.langKey,c.shapes&&c.shapes[0].type)},null,h);var k=this.addButton(h,e.removeButton||"remove","remove",d,h);k.className+=" highcharts-annotation-remove-button";k.style["background-image"]="url("+this.iconsURL+"destroy.svg)";k= +this.addButton(h,e.editButton||"edit","edit",function(){g.call(f,"annotation-edit",a,c,d)},h);k.className+=" highcharts-annotation-edit-button";k.style["background-image"]="url("+this.iconsURL+"edit.svg)"},addForm:function(a,c,d,e){var f=this.popup.container,h=this.lang;b("h2",{innerHTML:h[c.langKey]||c.langKey,className:"highcharts-popup-main-title"},null,f);var g=b("div",{className:"highcharts-popup-lhs-col highcharts-popup-lhs-full"},null,f);var k=b("div",{className:"highcharts-popup-bottom-row"}, +null,f);this.annotations.addFormFields.call(this,g,a,"",c,[],!0);this.addButton(k,e?h.addButton||"add":h.saveButton||"save",e?"add":"save",d,f)},addFormFields:function(a,c,g,k,m,n){var f=this,h=this.annotations.addFormFields,r=this.addInput,w=this.lang,p,t;l(k,function(b,k){p=""!==g?g+"."+k:k;e(b)&&(!d(b)||d(b)&&e(b[0])?(t=w[k]||k,t.match(q)||m.push([!0,t,a]),h.call(f,a,c,p,b,m,!1)):m.push([f,p,"annotation",a,b]))});n&&(m=m.sort(function(a){return a[1].match(/format/g)?-1:1}),m.forEach(function(a){!0=== +a[0]?b("span",{className:"highcharts-annotation-title",innerHTML:a[1]},null,a[2]):r.apply(a[0],a.splice(1))}))}},indicators:{addForm:function(a,b,c){var d=this.indicators,f=this.lang;this.tabs.init.call(this,a);b=this.popup.container.querySelectorAll(".highcharts-tab-item-content");this.addColsContainer(b[0]);d.addIndicatorList.call(this,a,b[0],"add");var e=b[0].querySelectorAll(".highcharts-popup-rhs-col")[0];this.addButton(e,f.addButton||"add","add",c,e);this.addColsContainer(b[1]);d.addIndicatorList.call(this, +a,b[1],"edit");e=b[1].querySelectorAll(".highcharts-popup-rhs-col")[0];this.addButton(e,f.saveButton||"save","edit",c,e);this.addButton(e,f.removeButton||"remove","remove",c,e)},addIndicatorList:function(a,d,e){var f=this,h=d.querySelectorAll(".highcharts-popup-lhs-col")[0];d=d.querySelectorAll(".highcharts-popup-rhs-col")[0];var g="edit"===e,k=g?a.series:a.options.plotOptions,w=this.indicators.addFormFields,m;var p=b("ul",{className:"highcharts-indicator-list"},null,h);var q=d.querySelectorAll(".highcharts-popup-rhs-col-wrapper")[0]; +l(k,function(d,e){var h=d.options;if(d.params||h&&h.params){var r=f.indicators.getNameType(d,e),l=r.type;m=b("li",{className:"highcharts-indicator-list",innerHTML:r.name},null,p);["click","touchstart"].forEach(function(e){c(m,e,function(){w.call(f,a,g?d:k[l],r.type,q);g&&d.options&&b("input",{type:"hidden",name:"highcharts-id-"+l,value:d.options.id},null,q).setAttribute("highcharts-data-series-id",d.options.id)})})}});0} + */ + this.nonDOMEvents = ['drag']; + this.chart = chart; + this.target = target; + this.options = options; + this.index = pick(options.index, index); + } + /** + * Set the visibility of the control point. + * + * @function Highcharts.AnnotationControlPoint#setVisibility + * + * @param {boolean} visible + * Visibility of the control point. + * + * @return {void} + */ + ControlPoint.prototype.setVisibility = function (visible) { + this.graphic.attr('visibility', visible ? 'visible' : 'hidden'); + this.options.visible = visible; + }; + /** + * Render the control point. + * @private + */ + ControlPoint.prototype.render = function () { + var chart = this.chart, + options = this.options; + this.graphic = chart.renderer + .symbol(options.symbol, 0, 0, options.width, options.height) + .add(chart.controlPointsGroup) + .css(options.style); + this.setVisibility(options.visible); + // npm test -- --tests "highcharts/annotations-advanced/*" + this.addEvents(); + }; + /** + * Redraw the control point. + * @private + * @param {boolean} [animation] + */ + ControlPoint.prototype.redraw = function (animation) { + this.graphic[animation ? 'animate' : 'attr'](this.options.positioner.call(this, this.target)); + }; + /** + * Destroy the control point. + * @private + */ + ControlPoint.prototype.destroy = function () { + eventEmitterMixin.destroy.call(this); + if (this.graphic) { + this.graphic = this.graphic.destroy(); + } + this.chart = null; + this.target = null; + this.options = null; + }; + /** + * Update the control point. + * + * @function Highcharts.AnnotationControlPoint#update + * + * @param {Partial} userOptions + * New options for the control point. + * + * @return {void} + */ + ControlPoint.prototype.update = function (userOptions) { + var chart = this.chart, + target = this.target, + index = this.index, + options = merge(true, + this.options, + userOptions); + this.destroy(); + this.constructor(chart, target, options, index); + this.render(chart.controlPointsGroup); + this.redraw(); + }; + return ControlPoint; + }()); + + return ControlPoint; + }); + _registerModule(_modules, 'Extensions/Annotations/MockPoint.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * @private + * @interface Highcharts.AnnotationMockLabelOptionsObject + */ /** + * Point instance of the point. + * @name Highcharts.AnnotationMockLabelOptionsObject#point + * @type {Highcharts.AnnotationMockPoint} + */ /** + * X value translated to x axis scale. + * @name Highcharts.AnnotationMockLabelOptionsObject#x + * @type {number|null} + */ /** + * Y value translated to y axis scale. + * @name Highcharts.AnnotationMockLabelOptionsObject#y + * @type {number|null} + */ + /** + * A mock series instance imitating a real series from a real point. + * @private + * @interface Highcharts.AnnotationMockSeries + */ /** + * Whether a series is visible. + * @name Highcharts.AnnotationMockSeries#visible + * @type {boolean} + */ /** + * A chart instance. + * @name Highcharts.AnnotationMockSeries#chart + * @type {Highcharts.Chart} + */ /** + * @name Highcharts.AnnotationMockSeries#getPlotBox + * @type {Function} + */ + /** + * Indicates if this is a mock point for an annotation. + * @name Highcharts.Point#mock + * @type {boolean|undefined} + */ + var defined = U.defined, + extend = U.extend, + fireEvent = U.fireEvent; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * A trimmed point object which imitates {@link Highchart.Point} class. It is + * created when there is a need of pointing to some chart's position using axis + * values or pixel values + * + * @requires modules/annotations + * + * @private + * @class + * @name Highcharts.AnnotationMockPoint + * + * @hideconstructor + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.AnnotationControllable|null} target + * The related controllable. + * + * @param {Highcharts.AnnotationMockPointOptionsObject|Function} options + * The options object. + */ + var MockPoint = /** @class */ (function () { + function MockPoint(chart, target, options) { + this.isInside = void 0; + this.plotX = void 0; + this.plotY = void 0; + this.x = void 0; + this.y = void 0; + /* * + * + * Functions + * + * */ + /** + * A flag indicating that a point is not the real one. + * + * @type {boolean} + * @default true + */ + this.mock = true; + /** + * A mock series instance imitating a real series from a real point. + * + * @name Annotation.AnnotationMockPoint#series + * @type {Highcharts.AnnotationMockSeries} + */ + this.series = { + visible: true, + chart: chart, + getPlotBox: H.Series.prototype.getPlotBox + }; + /** + * @name Annotation.AnnotationMockPoint#target + * @type {Highcharts.AnnotationControllable|null} + */ + this.target = target || null; + /** + * Options for the mock point. + * + * @name Annotation.AnnotationMockPoint#options + * @type {Highcharts.AnnotationsMockPointOptionsObject} + */ + this.options = options; + /** + * If an xAxis is set it represents the point's value in terms of the + * xAxis. + * + * @name Annotation.AnnotationMockPoint#x + * @type {number|undefined} + */ + /** + * If an yAxis is set it represents the point's value in terms of the + * yAxis. + * + * @name Annotation.AnnotationMockPoint#y + * @type {number|undefined} + */ + /** + * It represents the point's pixel x coordinate relative to its plot + * box. + * + * @name Annotation.AnnotationMockPoint#plotX + * @type {number|undefined} + */ + /** + * It represents the point's pixel y position relative to its plot box. + * + * @name Annotation.AnnotationMockPoint#plotY + * @type {number|undefined} + */ + /** + * Whether the point is inside the plot box. + * + * @name Annotation.AnnotationMockPoint#isInside + * @type {boolean|undefined} + */ + this.applyOptions(this.getOptions()); + } + /** + * Create a mock point from a real Highcharts point. + * + * @private + * @static + * + * @param {Highcharts.Point} point + * + * @return {Highcharts.AnnotationMockPoint} + * A mock point instance. + */ + MockPoint.fromPoint = function (point) { + return new MockPoint(point.series.chart, null, { + x: point.x, + y: point.y, + xAxis: point.series.xAxis, + yAxis: point.series.yAxis + }); + }; + /** + * Get the pixel position from the point like object. + * + * @private + * @static + * + * @param {Highcharts.AnnotationPointType} point + * + * @param {boolean} [paneCoordinates] + * whether the pixel position should be relative + * + * @return {Highcharts.PositionObject} pixel position + */ + MockPoint.pointToPixels = function (point, paneCoordinates) { + var series = point.series, + chart = series.chart, + x = point.plotX, + y = point.plotY, + plotBox; + if (chart.inverted) { + if (point.mock) { + x = point.plotY; + y = point.plotX; + } + else { + x = chart.plotWidth - point.plotY; + y = chart.plotHeight - point.plotX; + } + } + if (series && !paneCoordinates) { + plotBox = series.getPlotBox(); + x += plotBox.translateX; + y += plotBox.translateY; + } + return { + x: x, + y: y + }; + }; + /** + * Get fresh mock point options from the point like object. + * + * @private + * @static + * + * @param {Highcharts.AnnotationPointType} point + * + * @return {Highcharts.AnnotationMockPointOptionsObject} + * A mock point's options. + */ + MockPoint.pointToOptions = function (point) { + return { + x: point.x, + y: point.y, + xAxis: point.series.xAxis, + yAxis: point.series.yAxis + }; + }; + /** + * Check if the point has dynamic options. + * @private + * @return {boolean} + * A positive flag if the point has dynamic options. + */ + MockPoint.prototype.hasDynamicOptions = function () { + return typeof this.options === 'function'; + }; + /** + * Get the point's options. + * @private + * @return {Highcharts.AnnotationMockPointOptionsObject} + * The mock point's options. + */ + MockPoint.prototype.getOptions = function () { + return this.hasDynamicOptions() ? + this.options(this.target) : + this.options; + }; + /** + * Apply options for the point. + * @private + * @param {Highcharts.AnnotationMockPointOptionsObject} options + */ + MockPoint.prototype.applyOptions = function (options) { + this.command = options.command; + this.setAxis(options, 'x'); + this.setAxis(options, 'y'); + this.refresh(); + }; + /** + * Set x or y axis. + * @private + * @param {Highcharts.AnnotationMockPointOptionsObject} options + * @param {string} xOrY + * 'x' or 'y' string literal + */ + MockPoint.prototype.setAxis = function (options, xOrY) { + var axisName = (xOrY + 'Axis'), + axisOptions = options[axisName], + chart = this.series.chart; + this.series[axisName] = + axisOptions instanceof H.Axis ? + axisOptions : + defined(axisOptions) ? + (chart[axisName][axisOptions] || + chart.get(axisOptions)) : + null; + }; + /** + * Transform the mock point to an anchor (relative position on the chart). + * @private + * @return {Array} + * A quadruple of numbers which denotes x, y, width and height of the box + **/ + MockPoint.prototype.toAnchor = function () { + var anchor = [this.plotX, + this.plotY, 0, 0]; + if (this.series.chart.inverted) { + anchor[0] = this.plotY; + anchor[1] = this.plotX; + } + return anchor; + }; + /** + * Returns a label config object - the same as + * Highcharts.Point.prototype.getLabelConfig + * @private + * @return {Highcharts.AnnotationMockLabelOptionsObject} the point's label config + */ + MockPoint.prototype.getLabelConfig = function () { + return { + x: this.x, + y: this.y, + point: this + }; + }; + /** + * Check if the point is inside its pane. + * @private + * @return {boolean} A flag indicating whether the point is inside the pane. + */ + MockPoint.prototype.isInsidePlot = function () { + var plotX = this.plotX, + plotY = this.plotY, + xAxis = this.series.xAxis, + yAxis = this.series.yAxis, + e = { + x: plotX, + y: plotY, + isInsidePlot: true + }; + if (xAxis) { + e.isInsidePlot = defined(plotX) && plotX >= 0 && plotX <= xAxis.len; + } + if (yAxis) { + e.isInsidePlot = + e.isInsidePlot && + defined(plotY) && + plotY >= 0 && plotY <= yAxis.len; + } + fireEvent(this.series.chart, 'afterIsInsidePlot', e); + return e.isInsidePlot; + }; + /** + * Refresh point values and coordinates based on its options. + * @private + */ + MockPoint.prototype.refresh = function () { + var series = this.series, + xAxis = series.xAxis, + yAxis = series.yAxis, + options = this.getOptions(); + if (xAxis) { + this.x = options.x; + this.plotX = xAxis.toPixels(options.x, true); + } + else { + this.x = null; + this.plotX = options.x; + } + if (yAxis) { + this.y = options.y; + this.plotY = yAxis.toPixels(options.y, true); + } + else { + this.y = null; + this.plotY = options.y; + } + this.isInside = this.isInsidePlot(); + }; + /** + * Translate the point. + * + * @private + * + * @param {number|undefined} cx + * Origin x transformation. + * + * @param {number|undefined} cy + * Origin y transformation. + * + * @param {number} dx + * Translation for x coordinate. + * + * @param {number} dy + * Translation for y coordinate. + **/ + MockPoint.prototype.translate = function (_cx, _cy, dx, dy) { + if (!this.hasDynamicOptions()) { + this.plotX += dx; + this.plotY += dy; + this.refreshOptions(); + } + }; + /** + * Scale the point. + * + * @private + * + * @param {number} cx + * Origin x transformation. + * + * @param {number} cy + * Origin y transformation. + * + * @param {number} sx + * Scale factor x. + * + * @param {number} sy + * Scale factor y. + */ + MockPoint.prototype.scale = function (cx, cy, sx, sy) { + if (!this.hasDynamicOptions()) { + var x = this.plotX * sx, + y = this.plotY * sy, + tx = (1 - sx) * cx, + ty = (1 - sy) * cy; + this.plotX = tx + x; + this.plotY = ty + y; + this.refreshOptions(); + } + }; + /** + * Rotate the point. + * @private + * @param {number} cx origin x rotation + * @param {number} cy origin y rotation + * @param {number} radians + */ + MockPoint.prototype.rotate = function (cx, cy, radians) { + if (!this.hasDynamicOptions()) { + var cos = Math.cos(radians), + sin = Math.sin(radians), + x = this.plotX, + y = this.plotY, + tx, + ty; + x -= cx; + y -= cy; + tx = x * cos - y * sin; + ty = x * sin + y * cos; + this.plotX = tx + cx; + this.plotY = ty + cy; + this.refreshOptions(); + } + }; + /** + * Refresh point options based on its plot coordinates. + * @private + */ + MockPoint.prototype.refreshOptions = function () { + var series = this.series, + xAxis = series.xAxis, + yAxis = series.yAxis; + this.x = this.options.x = xAxis ? + this.options.x = xAxis.toValue(this.plotX, true) : + this.plotX; + this.y = this.options.y = yAxis ? + yAxis.toValue(this.plotY, true) : + this.plotY; + }; + return MockPoint; + }()); + + return MockPoint; + }); + _registerModule(_modules, 'Extensions/Annotations/Mixins/ControllableMixin.js', [_modules['Extensions/Annotations/ControlPoint.js'], _modules['Extensions/Annotations/MockPoint.js'], _modules['Core/Tooltip.js'], _modules['Core/Utilities.js']], function (ControlPoint, MockPoint, Tooltip, U) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var isObject = U.isObject, + isString = U.isString, + merge = U.merge, + splat = U.splat; + /** + * An object which denots a controllable's anchor positions - relative and + * absolute. + * + * @private + * @interface Highcharts.AnnotationAnchorObject + */ /** + * Relative to the plot area position + * @name Highcharts.AnnotationAnchorObject#relativePosition + * @type {Highcharts.BBoxObject} + */ /** + * Absolute position + * @name Highcharts.AnnotationAnchorObject#absolutePosition + * @type {Highcharts.BBoxObject} + */ + /** + * @interface Highcharts.AnnotationControllable + */ /** + * @name Highcharts.AnnotationControllable#annotation + * @type {Highcharts.Annotation} + */ /** + * @name Highcharts.AnnotationControllable#chart + * @type {Highcharts.Chart} + */ /** + * @name Highcharts.AnnotationControllable#collection + * @type {string} + */ /** + * @private + * @name Highcharts.AnnotationControllable#controlPoints + * @type {Array} + */ /** + * @name Highcharts.AnnotationControllable#points + * @type {Array} + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * It provides methods for handling points, control points + * and points transformations. + * + * @private + * @mixin + * @name Highcharts.AnnotationControllableMixin + */ + var controllableMixin = { + /** + * Init the controllable + */ + init: function (annotation, + options, + index) { + this.annotation = annotation; + this.chart = annotation.chart; + this.options = options; + this.points = []; + this.controlPoints = []; + this.index = index; + this.linkPoints(); + this.addControlPoints(); + }, + /** + * Redirect attr usage on the controllable graphic element. + */ + attr: function () { + this.graphic.attr.apply(this.graphic, arguments); + }, + /** + * Get the controllable's points options. + * + * @return {Array} + * An array of points' options. + */ + getPointsOptions: function () { + var options = this.options; + return (options.points || (options.point && splat(options.point))); + }, + /** + * Utility function for mapping item's options + * to element's attribute + * + * @param {Highcharts.AnnotationsLabelsOptions|Highcharts.AnnotationsShapesOptions} options + * + * @return {Highcharts.SVGAttributes} + * Mapped options. + */ + attrsFromOptions: function (options) { + var map = this.constructor.attrsMap, + attrs = {}, + key, + mappedKey, + styledMode = this.chart.styledMode; + for (key in options) { // eslint-disable-line guard-for-in + mappedKey = map[key]; + if (mappedKey && + (!styledMode || + ['fill', 'stroke', 'stroke-width'] + .indexOf(mappedKey) === -1)) { + attrs[mappedKey] = options[key]; + } + } + return attrs; + }, + /** + * Returns object which denotes anchor position - relative and absolute. + * + * @param {Highcharts.AnnotationPointType} point + * A point like object. + * + * @return {Highcharts.AnnotationAnchorObject} a controllable anchor + */ + anchor: function (point) { + var plotBox = point.series.getPlotBox(), + box = point.mock ? + point.toAnchor() : + Tooltip.prototype.getAnchor.call({ + chart: point.series.chart + }, + point), + anchor = { + x: box[0] + (this.options.x || 0), + y: box[1] + (this.options.y || 0), + height: box[2] || 0, + width: box[3] || 0 + }; + return { + relativePosition: anchor, + absolutePosition: merge(anchor, { + x: anchor.x + plotBox.translateX, + y: anchor.y + plotBox.translateY + }) + }; + }, + /** + * Map point's options to a point-like object. + * + * @param {string|Function|Highcharts.AnnotationMockPointOptionsObject|Highcharts.AnnotationPointType} pointOptions + * Point's options. + * + * @param {Highcharts.AnnotationPointType} point + * A point-like instance. + * + * @return {Highcharts.AnnotationPointType|null} + * if the point is found/set returns this point, otherwise null + */ + point: function (pointOptions, point) { + if (pointOptions && pointOptions.series) { + return pointOptions; + } + if (!point || point.series === null) { + if (isObject(pointOptions)) { + point = new MockPoint(this.chart, this, pointOptions); + } + else if (isString(pointOptions)) { + point = this.chart.get(pointOptions) || null; + } + else if (typeof pointOptions === 'function') { + var pointConfig = pointOptions.call(point, + this); + point = pointConfig.series ? + pointConfig : + new MockPoint(this.chart, this, pointOptions); + } + } + return point; + }, + /** + * Find point-like objects based on points options. + * + * @return {Array} an array of point-like objects + */ + linkPoints: function () { + var pointsOptions = this.getPointsOptions(), + points = this.points, + len = (pointsOptions && pointsOptions.length) || 0, + i, + point; + for (i = 0; i < len; i++) { + point = this.point(pointsOptions[i], points[i]); + if (!point) { + points.length = 0; + return; + } + if (point.mock) { + point.refresh(); + } + points[i] = point; + } + return points; + }, + /** + * Add control points to a controllable. + */ + addControlPoints: function () { + var controlPointsOptions = this.options.controlPoints; + (controlPointsOptions || []).forEach(function (controlPointOptions, i) { + var options = merge(this.options.controlPointOptions, + controlPointOptions); + if (!options.index) { + options.index = i; + } + controlPointsOptions[i] = options; + this.controlPoints.push(new ControlPoint(this.chart, this, options)); + }, this); + }, + /** + * Check if a controllable should be rendered/redrawn. + * + * @return {boolean} + * Whether a controllable should be drawn. + */ + shouldBeDrawn: function () { + return Boolean(this.points.length); + }, + /** + * Render a controllable. + */ + render: function (_parentGroup) { + this.controlPoints.forEach(function (controlPoint) { + controlPoint.render(); + }); + }, + /** + * Redraw a controllable. + * + * @param {boolean} [animation] + */ + redraw: function (animation) { + this.controlPoints.forEach(function (controlPoint) { + controlPoint.redraw(animation); + }); + }, + /** + * Transform a controllable with a specific transformation. + * + * @param {string} transformation a transformation name + * @param {number|null} cx origin x transformation + * @param {number|null} cy origin y transformation + * @param {number} p1 param for the transformation + * @param {number} [p2] param for the transformation + */ + transform: function (transformation, cx, cy, p1, p2) { + if (this.chart.inverted) { + var temp = cx; + cx = cy; + cy = temp; + } + this.points.forEach(function (point, i) { + this.transformPoint(transformation, cx, cy, p1, p2, i); + }, this); + }, + /** + * Transform a point with a specific transformation + * If a transformed point is a real point it is replaced with + * the mock point. + * + * @param {string} transformation a transformation name + * @param {number|null} cx origin x transformation + * @param {number|null} cy origin y transformation + * @param {number} p1 param for the transformation + * @param {number|undefined} p2 param for the transformation + * @param {number} i index of the point + */ + transformPoint: function (transformation, cx, cy, p1, p2, i) { + var point = this.points[i]; + if (!point.mock) { + point = this.points[i] = MockPoint.fromPoint(point); + } + point[transformation](cx, cy, p1, p2); + }, + /** + * Translate a controllable. + * + * @param {number} dx translation for x coordinate + * @param {number} dy translation for y coordinate + **/ + translate: function (dx, dy) { + this.transform('translate', null, null, dx, dy); + }, + /** + * Translate a specific point within a controllable. + * + * @param {number} dx translation for x coordinate + * @param {number} dy translation for y coordinate + * @param {number} i index of the point + **/ + translatePoint: function (dx, dy, i) { + this.transformPoint('translate', null, null, dx, dy, i); + }, + /** + * Translate shape within controllable item. + * Replaces `controllable.translate` method. + * + * @param {number} dx translation for x coordinate + * @param {number} dy translation for y coordinate + */ + translateShape: function (dx, dy) { + var chart = this.annotation.chart, + // Annotation.options + shapeOptions = this.annotation.userOptions, + // Chart.options.annotations + annotationIndex = chart.annotations.indexOf(this.annotation), + chartOptions = chart.options.annotations[annotationIndex]; + this.translatePoint(dx, dy, 0); + // Options stored in: + // - chart (for exporting) + // - current config (for redraws) + chartOptions[this.collection][this.index].point = this.options.point; + shapeOptions[this.collection][this.index].point = this.options.point; + }, + /** + * Rotate a controllable. + * + * @param {number} cx origin x rotation + * @param {number} cy origin y rotation + * @param {number} radians + **/ + rotate: function (cx, cy, radians) { + this.transform('rotate', cx, cy, radians); + }, + /** + * Scale a controllable. + * + * @param {number} cx origin x rotation + * @param {number} cy origin y rotation + * @param {number} sx scale factor x + * @param {number} sy scale factor y + */ + scale: function (cx, cy, sx, sy) { + this.transform('scale', cx, cy, sx, sy); + }, + /** + * Set control points' visibility. + * + * @param {boolean} visible + */ + setControlPointsVisibility: function (visible) { + this.controlPoints.forEach(function (controlPoint) { + controlPoint.setVisibility(visible); + }); + }, + /** + * Destroy a controllable. + */ + destroy: function () { + if (this.graphic) { + this.graphic = this.graphic.destroy(); + } + if (this.tracker) { + this.tracker = this.tracker.destroy(); + } + this.controlPoints.forEach(function (controlPoint) { + controlPoint.destroy(); + }); + this.chart = null; + this.points = null; + this.controlPoints = null; + this.options = null; + if (this.annotation) { + this.annotation = null; + } + }, + /** + * Update a controllable. + * + * @param {Object} newOptions + */ + update: function (newOptions) { + var annotation = this.annotation, + options = merge(true, + this.options, + newOptions), + parentGroup = this.graphic.parentGroup; + this.destroy(); + this.constructor(annotation, options); + this.render(parentGroup); + this.redraw(); + } + }; + + return controllableMixin; + }); + _registerModule(_modules, 'Extensions/Annotations/Mixins/MarkerMixin.js', [_modules['Core/Chart/Chart.js'], _modules['Core/Renderer/SVG/SVGRenderer.js'], _modules['Core/Utilities.js']], function (Chart, SVGRenderer, U) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + defined = U.defined, + merge = U.merge, + objectEach = U.objectEach, + uniqueKey = U.uniqueKey; + /** + * Options for configuring markers for annotations. + * + * An example of the arrow marker: + *
    +         * {
    +         *   arrow: {
    +         *     id: 'arrow',
    +         *     tagName: 'marker',
    +         *     refY: 5,
    +         *     refX: 5,
    +         *     markerWidth: 10,
    +         *     markerHeight: 10,
    +         *     children: [{
    +         *       tagName: 'path',
    +         *       attrs: {
    +         *         d: 'M 0 0 L 10 5 L 0 10 Z',
    +         *         strokeWidth: 0
    +         *       }
    +         *     }]
    +         *   }
    +         * }
    +         * 
    + * + * @sample highcharts/annotations/custom-markers/ + * Define a custom marker for annotations + * + * @sample highcharts/css/annotations-markers/ + * Define markers in a styled mode + * + * @type {Highcharts.Dictionary} + * @since 6.0.0 + * @optionparent defs + */ + var defaultMarkers = { + /** + * @type {Highcharts.SVGDefinitionObject} + */ + arrow: { + tagName: 'marker', + render: false, + id: 'arrow', + refY: 5, + refX: 9, + markerWidth: 10, + markerHeight: 10, + /** + * @type {Array} + */ + children: [{ + tagName: 'path', + d: 'M 0 0 L 10 5 L 0 10 Z', + strokeWidth: 0 + }] + }, + /** + * @type {Highcharts.SVGDefinitionObject} + */ + 'reverse-arrow': { + tagName: 'marker', + render: false, + id: 'reverse-arrow', + refY: 5, + refX: 1, + markerWidth: 10, + markerHeight: 10, + children: [{ + tagName: 'path', + // reverse triangle (used as an arrow) + d: 'M 0 5 L 10 0 L 10 10 Z', + strokeWidth: 0 + }] + } + }; + SVGRenderer.prototype.addMarker = function (id, markerOptions) { + var options = { id: id }; + var attrs = { + stroke: markerOptions.color || 'none', + fill: markerOptions.color || 'rgba(0, 0, 0, 0.75)' + }; + options.children = markerOptions.children.map(function (child) { + return merge(attrs, child); + }); + var marker = this.definition(merge(true, { + markerWidth: 20, + markerHeight: 20, + refX: 0, + refY: 0, + orient: 'auto' + }, + markerOptions, + options)); + marker.id = id; + return marker; + }; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * @private + */ + function createMarkerSetter(markerType) { + return function (value) { + this.attr(markerType, 'url(#' + value + ')'); + }; + } + /** + * @private + * @mixin + * @name Highcharts.AnnotaitonMarkerMixin + */ + var markerMixin = { + markerEndSetter: createMarkerSetter('marker-end'), + markerStartSetter: createMarkerSetter('marker-start'), + /** + * Set markers. + * @private + * @param {Highcharts.AnnotationControllablePath} item + */ + setItemMarkers: function (item) { + var itemOptions = item.options, + chart = item.chart, + defs = chart.options.defs, + fill = itemOptions.fill, + color = defined(fill) && fill !== 'none' ? + fill : + itemOptions.stroke, + setMarker = function (markerType) { + var markerId = itemOptions[markerType], + def, + predefinedMarker, + key, + marker; + if (markerId) { + for (key in defs) { // eslint-disable-line guard-for-in + def = defs[key]; + if (markerId === def.id && + def.tagName === 'marker') { + predefinedMarker = def; + break; + } + } + if (predefinedMarker) { + marker = item[markerType] = chart.renderer + .addMarker((itemOptions.id || uniqueKey()) + '-' + + predefinedMarker.id, merge(predefinedMarker, { color: color })); + item.attr(markerType, marker.attr('id')); + } + } + }; + ['markerStart', 'markerEnd'].forEach(setMarker); + } + }; + addEvent(Chart, 'afterGetContainer', function () { + this.options.defs = merge(defaultMarkers, this.options.defs || {}); + objectEach(this.options.defs, function (def) { + if (def.tagName === 'marker' && def.render !== false) { + this.renderer.addMarker(def.id, def); + } + }, this); + }); + + return markerMixin; + }); + _registerModule(_modules, 'Extensions/Annotations/Controllables/ControllablePath.js', [_modules['Extensions/Annotations/Mixins/ControllableMixin.js'], _modules['Core/Globals.js'], _modules['Extensions/Annotations/Mixins/MarkerMixin.js'], _modules['Core/Utilities.js']], function (ControllableMixin, H, MarkerMixin, U) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend; + // See TRACKER_FILL in highcharts.src.js + var TRACKER_FILL = 'rgba(192,192,192,' + (H.svg ? 0.0001 : 0.002) + ')'; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * A controllable path class. + * + * @requires modules/annotations + * + * @private + * @class + * @name Highcharts.AnnotationControllablePath + * + * @param {Highcharts.Annotation} + * Related annotation. + * + * @param {Highcharts.AnnotationsShapeOptions} options + * A path's options object. + * + * @param {number} index + * Index of the path. + */ + var ControllablePath = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function ControllablePath(annotation, options, index) { + /* * + * + * Properties + * + * */ + this.addControlPoints = ControllableMixin.addControlPoints; + this.anchor = ControllableMixin.anchor; + this.attr = ControllableMixin.attr; + this.attrsFromOptions = ControllableMixin.attrsFromOptions; + this.destroy = ControllableMixin.destroy; + this.getPointsOptions = ControllableMixin.getPointsOptions; + this.init = ControllableMixin.init; + this.linkPoints = ControllableMixin.linkPoints; + this.point = ControllableMixin.point; + this.rotate = ControllableMixin.rotate; + this.scale = ControllableMixin.scale; + this.setControlPointsVisibility = ControllableMixin.setControlPointsVisibility; + this.setMarkers = MarkerMixin.setItemMarkers; + this.transform = ControllableMixin.transform; + this.transformPoint = ControllableMixin.transformPoint; + this.translate = ControllableMixin.translate; + this.translatePoint = ControllableMixin.translatePoint; + this.translateShape = ControllableMixin.translateShape; + this.update = ControllableMixin.update; + /** + * @type 'path' + */ + this.type = 'path'; + this.init(annotation, options, index); + this.collection = 'shapes'; + } + /* * + * + * Functions + * + * */ + /** + * Map the controllable path to 'd' path attribute. + * + * @return {Highcharts.SVGPathArray|null} + * A path's d attribute. + */ + ControllablePath.prototype.toD = function () { + var dOption = this.options.d; + if (dOption) { + return typeof dOption === 'function' ? + dOption.call(this) : + dOption; + } + var points = this.points, + len = points.length, + showPath = len, + point = points[0], + position = showPath && this.anchor(point).absolutePosition, + pointIndex = 0, + command, + d = []; + if (position) { + d.push(['M', position.x, position.y]); + while (++pointIndex < len && showPath) { + point = points[pointIndex]; + command = point.command || 'L'; + position = this.anchor(point).absolutePosition; + if (command === 'M') { + d.push([command, position.x, position.y]); + } + else if (command === 'L') { + d.push([command, position.x, position.y]); + } + else if (command === 'Z') { + d.push([command]); + } + showPath = point.series.visible; + } + } + return showPath ? + this.chart.renderer.crispLine(d, this.graphic.strokeWidth()) : + null; + }; + ControllablePath.prototype.shouldBeDrawn = function () { + return (ControllableMixin.shouldBeDrawn.call(this) || Boolean(this.options.d)); + }; + ControllablePath.prototype.render = function (parent) { + var options = this.options, + attrs = this.attrsFromOptions(options); + this.graphic = this.annotation.chart.renderer + .path([['M', 0, 0]]) + .attr(attrs) + .add(parent); + if (options.className) { + this.graphic.addClass(options.className); + } + this.tracker = this.annotation.chart.renderer + .path([['M', 0, 0]]) + .addClass('highcharts-tracker-line') + .attr({ + zIndex: 2 + }) + .add(parent); + if (!this.annotation.chart.styledMode) { + this.tracker.attr({ + 'stroke-linejoin': 'round', + stroke: TRACKER_FILL, + fill: TRACKER_FILL, + 'stroke-width': this.graphic.strokeWidth() + + options.snap * 2 + }); + } + ControllableMixin.render.call(this); + extend(this.graphic, { + markerStartSetter: MarkerMixin.markerStartSetter, + markerEndSetter: MarkerMixin.markerEndSetter + }); + this.setMarkers(this); + }; + ControllablePath.prototype.redraw = function (animation) { + var d = this.toD(), + action = animation ? 'animate' : 'attr'; + if (d) { + this.graphic[action]({ d: d }); + this.tracker[action]({ d: d }); + } + else { + this.graphic.attr({ d: 'M 0 ' + -9e9 }); + this.tracker.attr({ d: 'M 0 ' + -9e9 }); + } + this.graphic.placed = this.tracker.placed = Boolean(d); + ControllableMixin.redraw.call(this, animation); + }; + /* * + * + * Static Properties + * + * */ + /** + * A map object which allows to map options attributes to element attributes + * + * @name Highcharts.AnnotationControllablePath.attrsMap + * @type {Highcharts.Dictionary} + */ + ControllablePath.attrsMap = { + dashStyle: 'dashstyle', + strokeWidth: 'stroke-width', + stroke: 'stroke', + fill: 'fill', + zIndex: 'zIndex' + }; + return ControllablePath; + }()); + + return ControllablePath; + }); + _registerModule(_modules, 'Extensions/Annotations/Controllables/ControllableRect.js', [_modules['Extensions/Annotations/Mixins/ControllableMixin.js'], _modules['Extensions/Annotations/Controllables/ControllablePath.js'], _modules['Core/Utilities.js']], function (ControllableMixin, ControllablePath, U) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var merge = U.merge; + /** + * @typedef {Annotation.ControllablePath.AttrsMap} + * Annotation.ControllableRect.AttrsMap + * @property {string} width=width + * @property {string} height=height + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * A controllable rect class. + * + * @requires modules/annotations + * + * @private + * @class + * @name Highcharts.AnnotationControllableRect + * + * @param {Highcharts.Annotation} annotation + * An annotation instance. + * + * @param {Highcharts.AnnotationsShapeOptions} options + * A rect's options. + * + * @param {number} index + * Index of the rectangle + */ + var ControllableRect = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function ControllableRect(annotation, options, index) { + /* * + * + * Properties + * + * */ + this.addControlPoints = ControllableMixin.addControlPoints; + this.anchor = ControllableMixin.anchor; + this.attr = ControllableMixin.attr; + this.attrsFromOptions = ControllableMixin.attrsFromOptions; + this.destroy = ControllableMixin.destroy; + this.getPointsOptions = ControllableMixin.getPointsOptions; + this.init = ControllableMixin.init; + this.linkPoints = ControllableMixin.linkPoints; + this.point = ControllableMixin.point; + this.rotate = ControllableMixin.rotate; + this.scale = ControllableMixin.scale; + this.setControlPointsVisibility = ControllableMixin.setControlPointsVisibility; + this.shouldBeDrawn = ControllableMixin.shouldBeDrawn; + this.transform = ControllableMixin.transform; + this.transformPoint = ControllableMixin.transformPoint; + this.translatePoint = ControllableMixin.translatePoint; + this.translateShape = ControllableMixin.translateShape; + this.update = ControllableMixin.update; + /** + * @type 'rect' + */ + this.type = 'rect'; + this.translate = ControllableMixin.translateShape; + this.init(annotation, options, index); + this.collection = 'shapes'; + } + /* * + * + * Functions + * + * */ + ControllableRect.prototype.render = function (parent) { + var attrs = this.attrsFromOptions(this.options); + this.graphic = this.annotation.chart.renderer + .rect(0, -9e9, 0, 0) + .attr(attrs) + .add(parent); + ControllableMixin.render.call(this); + }; + ControllableRect.prototype.redraw = function (animation) { + var position = this.anchor(this.points[0]).absolutePosition; + if (position) { + this.graphic[animation ? 'animate' : 'attr']({ + x: position.x, + y: position.y, + width: this.options.width, + height: this.options.height + }); + } + else { + this.attr({ + x: 0, + y: -9e9 + }); + } + this.graphic.placed = Boolean(position); + ControllableMixin.redraw.call(this, animation); + }; + /* * + * + * Static Properties + * + * */ + /** + * A map object which allows to map options attributes to element attributes + * + * @type {Annotation.ControllableRect.AttrsMap} + */ + ControllableRect.attrsMap = merge(ControllablePath.attrsMap, { + width: 'width', + height: 'height' + }); + return ControllableRect; + }()); + + return ControllableRect; + }); + _registerModule(_modules, 'Extensions/Annotations/Controllables/ControllableCircle.js', [_modules['Extensions/Annotations/Mixins/ControllableMixin.js'], _modules['Extensions/Annotations/Controllables/ControllablePath.js'], _modules['Core/Utilities.js']], function (ControllableMixin, ControllablePath, U) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var merge = U.merge; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * A controllable circle class. + * + * @requires modules/annotations + * + * @private + * @class + * @name Highcharts.AnnotationControllableCircle + * + * @param {Highcharts.Annotation} annotation an annotation instance + * @param {Highcharts.AnnotationsShapeOptions} options a shape's options + * @param {number} index of the circle + */ + var ControllableCircle = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function ControllableCircle(annotation, options, index) { + /* * + * + * Properties + * + * */ + this.addControlPoints = ControllableMixin.addControlPoints; + this.anchor = ControllableMixin.anchor; + this.attr = ControllableMixin.attr; + this.attrsFromOptions = ControllableMixin.attrsFromOptions; + this.destroy = ControllableMixin.destroy; + this.getPointsOptions = ControllableMixin.getPointsOptions; + this.init = ControllableMixin.init; + this.linkPoints = ControllableMixin.linkPoints; + this.point = ControllableMixin.point; + this.rotate = ControllableMixin.rotate; + this.scale = ControllableMixin.scale; + this.setControlPointsVisibility = ControllableMixin.setControlPointsVisibility; + this.shouldBeDrawn = ControllableMixin.shouldBeDrawn; + this.transform = ControllableMixin.transform; + this.transformPoint = ControllableMixin.transformPoint; + this.translatePoint = ControllableMixin.translatePoint; + this.translateShape = ControllableMixin.translateShape; + this.update = ControllableMixin.update; + /** + * @type 'circle' + */ + this.type = 'circle'; + this.translate = ControllableMixin.translateShape; + this.init(annotation, options, index); + this.collection = 'shapes'; + } + /* * + * + * Functions + * + * */ + ControllableCircle.prototype.render = function (parent) { + var attrs = this.attrsFromOptions(this.options); + this.graphic = this.annotation.chart.renderer + .circle(0, -9e9, 0) + .attr(attrs) + .add(parent); + ControllableMixin.render.call(this); + }; + ControllableCircle.prototype.redraw = function (animation) { + var position = this.anchor(this.points[0]).absolutePosition; + if (position) { + this.graphic[animation ? 'animate' : 'attr']({ + x: position.x, + y: position.y, + r: this.options.r + }); + } + else { + this.graphic.attr({ + x: 0, + y: -9e9 + }); + } + this.graphic.placed = Boolean(position); + ControllableMixin.redraw.call(this, animation); + }; + /** + * Set the radius. + * + * @param {number} r a radius to be set + */ + ControllableCircle.prototype.setRadius = function (r) { + this.options.r = r; + }; + /* * + * + * Static Properties + * + * */ + /** + * A map object which allows to map options attributes to element + * attributes. + * + * @name Highcharts.AnnotationControllableCircle.attrsMap + * @type {Highcharts.Dictionary} + */ + ControllableCircle.attrsMap = merge(ControllablePath.attrsMap, { r: 'r' }); + return ControllableCircle; + }()); + + return ControllableCircle; + }); + _registerModule(_modules, 'Extensions/Annotations/Controllables/ControllableLabel.js', [_modules['Extensions/Annotations/Mixins/ControllableMixin.js'], _modules['Extensions/Annotations/MockPoint.js'], _modules['Core/Renderer/SVG/SVGRenderer.js'], _modules['Core/Tooltip.js'], _modules['Core/Utilities.js']], function (ControllableMixin, MockPoint, SVGRenderer, Tooltip, U) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend, + format = U.format, + isNumber = U.isNumber, + pick = U.pick; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * A controllable label class. + * + * @requires modules/annotations + * + * @private + * @class + * @name Highcharts.AnnotationControllableLabel + * + * @param {Highcharts.Annotation} annotation + * An annotation instance. + * @param {Highcharts.AnnotationsLabelOptions} options + * A label's options. + * @param {number} index + * Index of the label. + */ + var ControllableLabel = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function ControllableLabel(annotation, options, index) { + /* * + * + * Properties + * + * */ + this.addControlPoints = ControllableMixin.addControlPoints; + this.attr = ControllableMixin.attr; + this.attrsFromOptions = ControllableMixin.attrsFromOptions; + this.destroy = ControllableMixin.destroy; + this.getPointsOptions = ControllableMixin.getPointsOptions; + this.init = ControllableMixin.init; + this.linkPoints = ControllableMixin.linkPoints; + this.point = ControllableMixin.point; + this.rotate = ControllableMixin.rotate; + this.scale = ControllableMixin.scale; + this.setControlPointsVisibility = ControllableMixin.setControlPointsVisibility; + this.shouldBeDrawn = ControllableMixin.shouldBeDrawn; + this.transform = ControllableMixin.transform; + this.transformPoint = ControllableMixin.transformPoint; + this.translateShape = ControllableMixin.translateShape; + this.update = ControllableMixin.update; + this.init(annotation, options, index); + this.collection = 'labels'; + } + /* * + * + * Static Functions + * + * */ + /** + * Returns new aligned position based alignment options and box to align to. + * It is almost a one-to-one copy from SVGElement.prototype.align + * except it does not use and mutate an element + * + * @param {Highcharts.AnnotationAlignObject} alignOptions + * + * @param {Highcharts.BBoxObject} box + * + * @return {Highcharts.PositionObject} + * Aligned position. + */ + ControllableLabel.alignedPosition = function (alignOptions, box) { + var align = alignOptions.align, + vAlign = alignOptions.verticalAlign, + x = (box.x || 0) + (alignOptions.x || 0), + y = (box.y || 0) + (alignOptions.y || 0), + alignFactor, + vAlignFactor; + if (align === 'right') { + alignFactor = 1; + } + else if (align === 'center') { + alignFactor = 2; + } + if (alignFactor) { + x += (box.width - (alignOptions.width || 0)) / alignFactor; + } + if (vAlign === 'bottom') { + vAlignFactor = 1; + } + else if (vAlign === 'middle') { + vAlignFactor = 2; + } + if (vAlignFactor) { + y += (box.height - (alignOptions.height || 0)) / vAlignFactor; + } + return { + x: Math.round(x), + y: Math.round(y) + }; + }; + /** + * Returns new alignment options for a label if the label is outside the + * plot area. It is almost a one-to-one copy from + * Series.prototype.justifyDataLabel except it does not mutate the label and + * it works with absolute instead of relative position. + */ + ControllableLabel.justifiedOptions = function (chart, label, alignOptions, alignAttr) { + var align = alignOptions.align, + verticalAlign = alignOptions.verticalAlign, + padding = label.box ? 0 : (label.padding || 0), + bBox = label.getBBox(), + off, + // + options = { + align: align, + verticalAlign: verticalAlign, + x: alignOptions.x, + y: alignOptions.y, + width: label.width, + height: label.height + }, + // + x = alignAttr.x - chart.plotLeft, + y = alignAttr.y - chart.plotTop; + // Off left + off = x + padding; + if (off < 0) { + if (align === 'right') { + options.align = 'left'; + } + else { + options.x = -off; + } + } + // Off right + off = x + bBox.width - padding; + if (off > chart.plotWidth) { + if (align === 'left') { + options.align = 'right'; + } + else { + options.x = chart.plotWidth - off; + } + } + // Off top + off = y + padding; + if (off < 0) { + if (verticalAlign === 'bottom') { + options.verticalAlign = 'top'; + } + else { + options.y = -off; + } + } + // Off bottom + off = y + bBox.height - padding; + if (off > chart.plotHeight) { + if (verticalAlign === 'top') { + options.verticalAlign = 'bottom'; + } + else { + options.y = chart.plotHeight - off; + } + } + return options; + }; + /* * + * + * Functions + * + * */ + /** + * Translate the point of the label by deltaX and deltaY translations. + * The point is the label's anchor. + * + * @param {number} dx translation for x coordinate + * @param {number} dy translation for y coordinate + */ + ControllableLabel.prototype.translatePoint = function (dx, dy) { + ControllableMixin.translatePoint.call(this, dx, dy, 0); + }; + /** + * Translate x and y position relative to the label's anchor. + * + * @param {number} dx translation for x coordinate + * @param {number} dy translation for y coordinate + */ + ControllableLabel.prototype.translate = function (dx, dy) { + var chart = this.annotation.chart, + // Annotation.options + labelOptions = this.annotation.userOptions, + // Chart.options.annotations + annotationIndex = chart.annotations.indexOf(this.annotation), + chartAnnotations = chart.options.annotations, + chartOptions = chartAnnotations[annotationIndex], + temp; + if (chart.inverted) { + temp = dx; + dx = dy; + dy = temp; + } + // Local options: + this.options.x += dx; + this.options.y += dy; + // Options stored in chart: + chartOptions[this.collection][this.index].x = this.options.x; + chartOptions[this.collection][this.index].y = this.options.y; + labelOptions[this.collection][this.index].x = this.options.x; + labelOptions[this.collection][this.index].y = this.options.y; + }; + ControllableLabel.prototype.render = function (parent) { + var options = this.options, + attrs = this.attrsFromOptions(options), + style = options.style; + this.graphic = this.annotation.chart.renderer + .label('', 0, -9999, // #10055 + options.shape, null, null, options.useHTML, null, 'annotation-label') + .attr(attrs) + .add(parent); + if (!this.annotation.chart.styledMode) { + if (style.color === 'contrast') { + style.color = this.annotation.chart.renderer.getContrast(ControllableLabel.shapesWithoutBackground.indexOf(options.shape) > -1 ? '#FFFFFF' : options.backgroundColor); + } + this.graphic + .css(options.style) + .shadow(options.shadow); + } + if (options.className) { + this.graphic.addClass(options.className); + } + this.graphic.labelrank = options.labelrank; + ControllableMixin.render.call(this); + }; + ControllableLabel.prototype.redraw = function (animation) { + var options = this.options, + text = this.text || options.format || options.text, + label = this.graphic, + point = this.points[0], + anchor, + attrs; + label.attr({ + text: text ? + format(text, point.getLabelConfig(), this.annotation.chart) : + options.formatter.call(point, this) + }); + anchor = this.anchor(point); + attrs = this.position(anchor); + if (attrs) { + label.alignAttr = attrs; + attrs.anchorX = anchor.absolutePosition.x; + attrs.anchorY = anchor.absolutePosition.y; + label[animation ? 'animate' : 'attr'](attrs); + } + else { + label.attr({ + x: 0, + y: -9999 // #10055 + }); + } + label.placed = !!attrs; + ControllableMixin.redraw.call(this, animation); + }; + /** + * All basic shapes don't support alignTo() method except label. + * For a controllable label, we need to subtract translation from + * options. + */ + ControllableLabel.prototype.anchor = function (_point) { + var anchor = ControllableMixin.anchor.apply(this, + arguments), + x = this.options.x || 0, + y = this.options.y || 0; + anchor.absolutePosition.x -= x; + anchor.absolutePosition.y -= y; + anchor.relativePosition.x -= x; + anchor.relativePosition.y -= y; + return anchor; + }; + /** + * Returns the label position relative to its anchor. + * + * @param {Highcharts.AnnotationAnchorObject} anchor + * + * @return {Highcharts.PositionObject|null} + */ + ControllableLabel.prototype.position = function (anchor) { + var item = this.graphic, + chart = this.annotation.chart, + point = this.points[0], + itemOptions = this.options, + anchorAbsolutePosition = anchor.absolutePosition, + anchorRelativePosition = anchor.relativePosition, + itemPosition, + alignTo, + itemPosRelativeX, + itemPosRelativeY, + showItem = point.series.visible && + MockPoint.prototype.isInsidePlot.call(point); + if (showItem) { + if (itemOptions.distance) { + itemPosition = Tooltip.prototype.getPosition.call({ + chart: chart, + distance: pick(itemOptions.distance, 16) + }, item.width, item.height, { + plotX: anchorRelativePosition.x, + plotY: anchorRelativePosition.y, + negative: point.negative, + ttBelow: point.ttBelow, + h: (anchorRelativePosition.height || anchorRelativePosition.width) + }); + } + else if (itemOptions.positioner) { + itemPosition = itemOptions.positioner.call(this); + } + else { + alignTo = { + x: anchorAbsolutePosition.x, + y: anchorAbsolutePosition.y, + width: 0, + height: 0 + }; + itemPosition = ControllableLabel.alignedPosition(extend(itemOptions, { + width: item.width, + height: item.height + }), alignTo); + if (this.options.overflow === 'justify') { + itemPosition = ControllableLabel.alignedPosition(ControllableLabel.justifiedOptions(chart, item, itemOptions, itemPosition), alignTo); + } + } + if (itemOptions.crop) { + itemPosRelativeX = itemPosition.x - chart.plotLeft; + itemPosRelativeY = itemPosition.y - chart.plotTop; + showItem = + chart.isInsidePlot(itemPosRelativeX, itemPosRelativeY) && + chart.isInsidePlot(itemPosRelativeX + item.width, itemPosRelativeY + item.height); + } + } + return showItem ? itemPosition : null; + }; + /* * + * + * Static Properties + * + * */ + /** + * A map object which allows to map options attributes to element attributes + * + * @type {Highcharts.Dictionary} + */ + ControllableLabel.attrsMap = { + backgroundColor: 'fill', + borderColor: 'stroke', + borderWidth: 'stroke-width', + zIndex: 'zIndex', + borderRadius: 'r', + padding: 'padding' + }; + /** + * Shapes which do not have background - the object is used for proper + * setting of the contrast color. + * + * @type {Array} + */ + ControllableLabel.shapesWithoutBackground = ['connector']; + return ControllableLabel; + }()); + /* ********************************************************************** */ + /** + * General symbol definition for labels with connector + * @private + */ + SVGRenderer.prototype.symbols.connector = function (x, y, w, h, options) { + var anchorX = options && options.anchorX, + anchorY = options && options.anchorY, + path, + yOffset, + lateral = w / 2; + if (isNumber(anchorX) && isNumber(anchorY)) { + path = [['M', anchorX, anchorY]]; + // Prefer 45 deg connectors + yOffset = y - anchorY; + if (yOffset < 0) { + yOffset = -h - yOffset; + } + if (yOffset < w) { + lateral = anchorX < x + (w / 2) ? yOffset : w - yOffset; + } + // Anchor below label + if (anchorY > y + h) { + path.push(['L', x + lateral, y + h]); + // Anchor above label + } + else if (anchorY < y) { + path.push(['L', x + lateral, y]); + // Anchor left of label + } + else if (anchorX < x) { + path.push(['L', x, y + h / 2]); + // Anchor right of label + } + else if (anchorX > x + w) { + path.push(['L', x + w, y + h / 2]); + } + } + return path || []; + }; + + return ControllableLabel; + }); + _registerModule(_modules, 'Extensions/Annotations/Controllables/ControllableImage.js', [_modules['Extensions/Annotations/Controllables/ControllableLabel.js'], _modules['Extensions/Annotations/Mixins/ControllableMixin.js']], function (ControllableLabel, ControllableMixin) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * A controllable image class. + * + * @requires modules/annotations + * + * @private + * @class + * @name Highcharts.AnnotationControllableImage + * + * @param {Highcharts.Annotation} annotation + * An annotation instance. + * + * @param {Highcharts.AnnotationsShapeOptions} options + * A controllable's options. + * + * @param {number} index + * Index of the image. + */ + var ControllableImage = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function ControllableImage(annotation, options, index) { + /* * + * + * Properties + * + * */ + this.addControlPoints = ControllableMixin.addControlPoints; + this.anchor = ControllableMixin.anchor; + this.attr = ControllableMixin.attr; + this.attrsFromOptions = ControllableMixin.attrsFromOptions; + this.destroy = ControllableMixin.destroy; + this.getPointsOptions = ControllableMixin.getPointsOptions; + this.init = ControllableMixin.init; + this.linkPoints = ControllableMixin.linkPoints; + this.point = ControllableMixin.point; + this.rotate = ControllableMixin.rotate; + this.scale = ControllableMixin.scale; + this.setControlPointsVisibility = ControllableMixin.setControlPointsVisibility; + this.shouldBeDrawn = ControllableMixin.shouldBeDrawn; + this.transform = ControllableMixin.transform; + this.transformPoint = ControllableMixin.transformPoint; + this.translatePoint = ControllableMixin.translatePoint; + this.translateShape = ControllableMixin.translateShape; + this.update = ControllableMixin.update; + /** + * @type 'image' + */ + this.type = 'image'; + this.translate = ControllableMixin.translateShape; + this.init(annotation, options, index); + this.collection = 'shapes'; + } + ControllableImage.prototype.render = function (parent) { + var attrs = this.attrsFromOptions(this.options), + options = this.options; + this.graphic = this.annotation.chart.renderer + .image(options.src, 0, -9e9, options.width, options.height) + .attr(attrs) + .add(parent); + this.graphic.width = options.width; + this.graphic.height = options.height; + ControllableMixin.render.call(this); + }; + ControllableImage.prototype.redraw = function (animation) { + var anchor = this.anchor(this.points[0]), + position = ControllableLabel.prototype.position.call(this, + anchor); + if (position) { + this.graphic[animation ? 'animate' : 'attr']({ + x: position.x, + y: position.y + }); + } + else { + this.graphic.attr({ + x: 0, + y: -9e9 + }); + } + this.graphic.placed = Boolean(position); + ControllableMixin.redraw.call(this, animation); + }; + /* * + * + * Static Properties + * + * */ + /** + * A map object which allows to map options attributes to element attributes + * + * @name Highcharts.AnnotationControllableImage.attrsMap + * @type {Highcharts.Dictionary} + */ + ControllableImage.attrsMap = { + width: 'width', + height: 'height', + zIndex: 'zIndex' + }; + return ControllableImage; + }()); + + return ControllableImage; + }); + _registerModule(_modules, 'Extensions/Annotations/Annotations.js', [_modules['Core/Chart/Chart.js'], _modules['Extensions/Annotations/Mixins/ControllableMixin.js'], _modules['Extensions/Annotations/Controllables/ControllableRect.js'], _modules['Extensions/Annotations/Controllables/ControllableCircle.js'], _modules['Extensions/Annotations/Controllables/ControllablePath.js'], _modules['Extensions/Annotations/Controllables/ControllableImage.js'], _modules['Extensions/Annotations/Controllables/ControllableLabel.js'], _modules['Extensions/Annotations/ControlPoint.js'], _modules['Extensions/Annotations/Mixins/EventEmitterMixin.js'], _modules['Core/Globals.js'], _modules['Extensions/Annotations/MockPoint.js'], _modules['Core/Pointer.js'], _modules['Core/Utilities.js']], function (Chart, ControllableMixin, ControllableRect, ControllableCircle, ControllablePath, ControllableImage, ControllableLabel, ControlPoint, EventEmitterMixin, H, MockPoint, Pointer, U) { + /* * + * + * (c) 2009-2017 Highsoft, Black Label + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var chartProto = Chart.prototype; + var addEvent = U.addEvent, + defined = U.defined, + destroyObjectProperties = U.destroyObjectProperties, + erase = U.erase, + extend = U.extend, + find = U.find, + fireEvent = U.fireEvent, + getDeferredAnimation = U.getDeferredAnimation, + merge = U.merge, + pick = U.pick, + splat = U.splat, + wrap = U.wrap; + /* ********************************************************************* + * + * ANNOTATION + * + ******************************************************************** */ + /** + * Possible directions for draggable annotations. An empty string (`''`) + * makes the annotation undraggable. + * + * @typedef {''|'x'|'xy'|'y'} Highcharts.AnnotationDraggableValue + */ + /** + * @private + * @typedef { + * Highcharts.AnnotationControllableCircle| + * Highcharts.AnnotationControllableImage| + * Highcharts.AnnotationControllablePath| + * Highcharts.AnnotationControllableRect + * } + * Highcharts.AnnotationShapeType + * @requires modules/annotations + */ + /** + * @private + * @typedef { + * Highcharts.AnnotationControllableLabel + * } + * Highcharts.AnnotationLabelType + * @requires modules/annotations + */ + /** + * A point-like object, a mock point or a point used in series. + * @private + * @typedef {Highcharts.AnnotationMockPoint|Highcharts.Point} Highcharts.AnnotationPointType + * @requires modules/annotations + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * An annotation class which serves as a container for items like labels or + * shapes. Created items are positioned on the chart either by linking them to + * existing points or created mock points + * + * @class + * @name Highcharts.Annotation + * + * @param {Highcharts.Chart} chart a chart instance + * @param {Highcharts.AnnotationsOptions} userOptions the options object + */ + var Annotation = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Annotation(chart, userOptions) { + /* * + * + * Properties + * + * */ + this.annotation = void 0; + this.coll = 'annotations'; + this.collection = void 0; + this.animationConfig = void 0; + this.graphic = void 0; + this.group = void 0; + this.labelCollector = void 0; + this.labelsGroup = void 0; + this.shapesGroup = void 0; + var labelsAndShapes; + /** + * The chart that the annotation belongs to. + * + * @type {Highcharts.Chart} + */ + this.chart = chart; + /** + * The array of points which defines the annotation. + * + * @type {Array} + */ + this.points = []; + /** + * The array of control points. + * + * @private + * @name Highcharts.Annotation#controlPoints + * @type {Array} + */ + this.controlPoints = []; + this.coll = 'annotations'; + /** + * The array of labels which belong to the annotation. + * + * @private + * @name Highcharts.Annotation#labels + * @type {Array} + */ + this.labels = []; + /** + * The array of shapes which belong to the annotation. + * + * @private + * @name Highcharts.Annotation#shapes + * @type {Array} + */ + this.shapes = []; + /** + * The options for the annotations. + * + * @name Highcharts.Annotation#options + * @type {Highcharts.AnnotationsOptions} + */ + this.options = merge(this.defaultOptions, userOptions); + /** + * The user options for the annotations. + * + * @name Highcharts.Annotation#userOptions + * @type {Highcharts.AnnotationsOptions} + */ + this.userOptions = userOptions; + // Handle labels and shapes - those are arrays + // Merging does not work with arrays (stores reference) + labelsAndShapes = this.getLabelsAndShapesOptions(this.options, userOptions); + this.options.labels = labelsAndShapes.labels; + this.options.shapes = labelsAndShapes.shapes; + /** + * The callback that reports to the overlapping-labels module which + * labels it should account for. + * @private + * @name Highcharts.Annotation#labelCollector + * @type {Function} + */ + /** + * The group svg element. + * + * @name Highcharts.Annotation#group + * @type {Highcharts.SVGElement} + */ + /** + * The group svg element of the annotation's shapes. + * + * @name Highcharts.Annotation#shapesGroup + * @type {Highcharts.SVGElement} + */ + /** + * The group svg element of the annotation's labels. + * + * @name Highcharts.Annotation#labelsGroup + * @type {Highcharts.SVGElement} + */ + this.init(chart, this.options); + } + /** + * Initialize the annotation. + * @private + */ + Annotation.prototype.init = function () { + var chart = this.chart, + animOptions = this.options.animation; + this.linkPoints(); + this.addControlPoints(); + this.addShapes(); + this.addLabels(); + this.setLabelCollector(); + this.animationConfig = getDeferredAnimation(chart, animOptions); + }; + Annotation.prototype.getLabelsAndShapesOptions = function (baseOptions, newOptions) { + var mergedOptions = {}; + ['labels', 'shapes'].forEach(function (name) { + if (baseOptions[name]) { + mergedOptions[name] = splat(newOptions[name]).map(function (basicOptions, i) { + return merge(baseOptions[name][i], basicOptions); + }); + } + }); + return mergedOptions; + }; + Annotation.prototype.addShapes = function () { + (this.options.shapes || []).forEach(function (shapeOptions, i) { + var shape = this.initShape(shapeOptions, + i); + merge(true, this.options.shapes[i], shape.options); + }, this); + }; + Annotation.prototype.addLabels = function () { + (this.options.labels || []).forEach(function (labelsOptions, i) { + var labels = this.initLabel(labelsOptions, + i); + merge(true, this.options.labels[i], labels.options); + }, this); + }; + Annotation.prototype.addClipPaths = function () { + this.setClipAxes(); + if (this.clipXAxis && this.clipYAxis) { + this.clipRect = this.chart.renderer.clipRect(this.getClipBox()); + } + }; + Annotation.prototype.setClipAxes = function () { + var xAxes = this.chart.xAxis, + yAxes = this.chart.yAxis, + linkedAxes = (this.options.labels || []) + .concat(this.options.shapes || []) + .reduce(function (axes, + labelOrShape) { + return [ + xAxes[labelOrShape && + labelOrShape.point && + labelOrShape.point.xAxis] || axes[0], + yAxes[labelOrShape && + labelOrShape.point && + labelOrShape.point.yAxis] || axes[1] + ]; + }, []); + this.clipXAxis = linkedAxes[0]; + this.clipYAxis = linkedAxes[1]; + }; + Annotation.prototype.getClipBox = function () { + if (this.clipXAxis && this.clipYAxis) { + return { + x: this.clipXAxis.left, + y: this.clipYAxis.top, + width: this.clipXAxis.width, + height: this.clipYAxis.height + }; + } + }; + Annotation.prototype.setLabelCollector = function () { + var annotation = this; + annotation.labelCollector = function () { + return annotation.labels.reduce(function (labels, label) { + if (!label.options.allowOverlap) { + labels.push(label.graphic); + } + return labels; + }, []); + }; + annotation.chart.labelCollectors.push(annotation.labelCollector); + }; + /** + * Set an annotation options. + * @private + * @param {Highcharts.AnnotationsOptions} - user options for an annotation + */ + Annotation.prototype.setOptions = function (userOptions) { + this.options = merge(this.defaultOptions, userOptions); + }; + Annotation.prototype.redraw = function (animation) { + this.linkPoints(); + if (!this.graphic) { + this.render(); + } + if (this.clipRect) { + this.clipRect.animate(this.getClipBox()); + } + this.redrawItems(this.shapes, animation); + this.redrawItems(this.labels, animation); + ControllableMixin.redraw.call(this, animation); + }; + /** + * @private + * @param {Array} items + * @param {boolean} [animation] + */ + Annotation.prototype.redrawItems = function (items, animation) { + var i = items.length; + // needs a backward loop + // labels/shapes array might be modified + // due to destruction of the item + while (i--) { + this.redrawItem(items[i], animation); + } + }; + /** + * @private + * @param {Array} items + */ + Annotation.prototype.renderItems = function (items) { + var i = items.length; + while (i--) { + this.renderItem(items[i]); + } + }; + Annotation.prototype.render = function () { + var renderer = this.chart.renderer; + this.graphic = renderer + .g('annotation') + .attr({ + opacity: 0, + zIndex: this.options.zIndex, + visibility: this.options.visible ? + 'visible' : + 'hidden' + }) + .add(); + this.shapesGroup = renderer + .g('annotation-shapes') + .add(this.graphic) + .clip(this.chart.plotBoxClip); + this.labelsGroup = renderer + .g('annotation-labels') + .attr({ + // hideOverlappingLabels requires translation + translateX: 0, + translateY: 0 + }) + .add(this.graphic); + this.addClipPaths(); + if (this.clipRect) { + this.graphic.clip(this.clipRect); + } + // Render shapes and labels before adding events (#13070). + this.renderItems(this.shapes); + this.renderItems(this.labels); + this.addEvents(); + ControllableMixin.render.call(this); + }; + /** + * Set the annotation's visibility. + * @private + * @param {boolean} [visible] + * Whether to show or hide an annotation. If the param is omitted, the + * annotation's visibility is toggled. + */ + Annotation.prototype.setVisibility = function (visible) { + var options = this.options, + visibility = pick(visible, !options.visible); + this.graphic.attr('visibility', visibility ? 'visible' : 'hidden'); + if (!visibility) { + this.setControlPointsVisibility(false); + } + options.visible = visibility; + }; + Annotation.prototype.setControlPointsVisibility = function (visible) { + var setItemControlPointsVisibility = function (item) { + item.setControlPointsVisibility(visible); + }; + ControllableMixin.setControlPointsVisibility.call(this, visible); + this.shapes.forEach(setItemControlPointsVisibility); + this.labels.forEach(setItemControlPointsVisibility); + }; + /** + * Destroy the annotation. This function does not touch the chart + * that the annotation belongs to (all annotations are kept in + * the chart.annotations array) - it is recommended to use + * {@link Highcharts.Chart#removeAnnotation} instead. + * @private + */ + Annotation.prototype.destroy = function () { + var chart = this.chart, + destroyItem = function (item) { + item.destroy(); + }; + this.labels.forEach(destroyItem); + this.shapes.forEach(destroyItem); + this.clipXAxis = null; + this.clipYAxis = null; + erase(chart.labelCollectors, this.labelCollector); + EventEmitterMixin.destroy.call(this); + ControllableMixin.destroy.call(this); + destroyObjectProperties(this, chart); + }; + /** + * See {@link Highcharts.Chart#removeAnnotation}. + * @private + */ + Annotation.prototype.remove = function () { + // Let chart.update() remove annoations on demand + return this.chart.removeAnnotation(this); + }; + /** + * Updates an annotation. + * + * @function Highcharts.Annotation#update + * + * @param {Partial} userOptions + * New user options for the annotation. + * + * @return {void} + */ + Annotation.prototype.update = function (userOptions, redraw) { + var chart = this.chart, + labelsAndShapes = this.getLabelsAndShapesOptions(this.userOptions, + userOptions), + userOptionsIndex = chart.annotations.indexOf(this), + options = merge(true, + this.userOptions, + userOptions); + options.labels = labelsAndShapes.labels; + options.shapes = labelsAndShapes.shapes; + this.destroy(); + this.constructor(chart, options); + // Update options in chart options, used in exporting (#9767): + chart.options.annotations[userOptionsIndex] = options; + this.isUpdating = true; + if (pick(redraw, true)) { + chart.redraw(); + } + fireEvent(this, 'afterUpdate'); + this.isUpdating = false; + }; + /* ************************************************************* + * ITEM SECTION + * Contains methods for handling a single item in an annotation + **************************************************************** */ + /** + * Initialisation of a single shape + * @private + * @param {Object} shapeOptions - a confg object for a single shape + */ + Annotation.prototype.initShape = function (shapeOptions, index) { + var options = merge(this.options.shapeOptions, { + controlPointOptions: this.options.controlPointOptions + }, + shapeOptions), + shape = new Annotation.shapesMap[options.type](this, + options, + index); + shape.itemType = 'shape'; + this.shapes.push(shape); + return shape; + }; + /** + * Initialisation of a single label + * @private + */ + Annotation.prototype.initLabel = function (labelOptions, index) { + var options = merge(this.options.labelOptions, { + controlPointOptions: this.options.controlPointOptions + }, + labelOptions), + label = new ControllableLabel(this, + options, + index); + label.itemType = 'label'; + this.labels.push(label); + return label; + }; + /** + * Redraw a single item. + * @private + * @param {Annotation.Label|Annotation.Shape} item + * @param {boolean} [animation] + */ + Annotation.prototype.redrawItem = function (item, animation) { + item.linkPoints(); + if (!item.shouldBeDrawn()) { + this.destroyItem(item); + } + else { + if (!item.graphic) { + this.renderItem(item); + } + item.redraw(pick(animation, true) && item.graphic.placed); + if (item.points.length) { + this.adjustVisibility(item); + } + } + }; + /** + * Hide or show annotaiton attached to points. + * @private + * @param {Annotation.Label|Annotation.Shape} item + */ + Annotation.prototype.adjustVisibility = function (item) { + var hasVisiblePoints = false, + label = item.graphic; + item.points.forEach(function (point) { + if (point.series.visible !== false && + point.visible !== false) { + hasVisiblePoints = true; + } + }); + if (!hasVisiblePoints) { + label.hide(); + } + else if (label.visibility === 'hidden') { + label.show(); + } + }; + /** + * Destroy a single item. + * @private + * @param {Annotation.Label|Annotation.Shape} item + */ + Annotation.prototype.destroyItem = function (item) { + // erase from shapes or labels array + erase(this[item.itemType + 's'], item); + item.destroy(); + }; + /** + * @private + */ + Annotation.prototype.renderItem = function (item) { + item.render(item.itemType === 'label' ? + this.labelsGroup : + this.shapesGroup); + }; + /** + * @private + */ + Annotation.ControlPoint = ControlPoint; + /** + * @private + */ + Annotation.MockPoint = MockPoint; + /** + * An object uses for mapping between a shape type and a constructor. + * To add a new shape type extend this object with type name as a key + * and a constructor as its value. + */ + Annotation.shapesMap = { + 'rect': ControllableRect, + 'circle': ControllableCircle, + 'path': ControllablePath, + 'image': ControllableImage + }; + /** + * @private + */ + Annotation.types = {}; + return Annotation; + }()); + merge(true, Annotation.prototype, ControllableMixin, EventEmitterMixin, + // restore original Annotation implementation after mixin overwrite + merge(Annotation.prototype, + /** @lends Highcharts.Annotation# */ + { + /** + * List of events for `annotation.options.events` that should not be + * added to `annotation.graphic` but to the `annotation`. + * + * @private + * @type {Array} + */ + nonDOMEvents: ['add', 'afterUpdate', 'drag', 'remove'], + /** + * A basic type of an annotation. It allows to add custom labels + * or shapes. The items can be tied to points, axis coordinates + * or chart pixel coordinates. + * + * @sample highcharts/annotations/basic/ + * Basic annotations + * @sample highcharts/demo/annotations/ + * Advanced annotations + * @sample highcharts/css/annotations + * Styled mode + * @sample highcharts/annotations-advanced/controllable + * Controllable items + * @sample {highstock} stock/annotations/fibonacci-retracements + * Custom annotation, Fibonacci retracement + * + * @type {Array<*>} + * @since 6.0.0 + * @requires modules/annotations + * @optionparent annotations + * + * @private + */ + defaultOptions: { + /** + * Sets an ID for an annotation. Can be user later when + * removing an annotation in [Chart#removeAnnotation(id)]( + * /class-reference/Highcharts.Chart#removeAnnotation) method. + * + * @type {number|string} + * @apioption annotations.id + */ + /** + * Whether the annotation is visible. + * + * @sample highcharts/annotations/visible/ + * Set annotation visibility + */ + visible: true, + /** + * Enable or disable the initial animation when a series is + * displayed for the `annotation`. The animation can also be set + * as a configuration object. Please note that this option only + * applies to the initial animation. + * For other animations, see [chart.animation](#chart.animation) + * and the animation parameter under the API methods. + * The following properties are supported: + * + * - `defer`: The animation delay time in milliseconds. + * + * @sample {highcharts} highcharts/annotations/defer/ + * Animation defer settings + * @type {boolean|Partial} + * @since 8.2.0 + * @apioption annotations.animation + */ + animation: {}, + /** + * The animation delay time in milliseconds. + * Set to `0` renders annotation immediately. + * As `undefined` inherits defer time from the [series.animation.defer](#plotOptions.series.animation.defer). + * + * @type {number} + * @since 8.2.0 + * @apioption annotations.animation.defer + */ + /** + * Allow an annotation to be draggable by a user. Possible + * values are `'x'`, `'xy'`, `'y'` and `''` (disabled). + * + * @sample highcharts/annotations/draggable/ + * Annotations draggable: 'xy' + * + * @type {Highcharts.AnnotationDraggableValue} + */ + draggable: 'xy', + /** + * Options for annotation's labels. Each label inherits options + * from the labelOptions object. An option from the labelOptions + * can be overwritten by config for a specific label. + * + * @requires modules/annotations + */ + labelOptions: { + /** + * The alignment of the annotation's label. If right, + * the right side of the label should be touching the point. + * + * @sample highcharts/annotations/label-position/ + * Set labels position + * + * @type {Highcharts.AlignValue} + */ + align: 'center', + /** + * Whether to allow the annotation's labels to overlap. + * To make the labels less sensitive for overlapping, + * the can be set to 0. + * + * @sample highcharts/annotations/tooltip-like/ + * Hide overlapping labels + */ + allowOverlap: false, + /** + * The background color or gradient for the annotation's + * label. + * + * @sample highcharts/annotations/label-presentation/ + * Set labels graphic options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + backgroundColor: 'rgba(0, 0, 0, 0.75)', + /** + * The border color for the annotation's label. + * + * @sample highcharts/annotations/label-presentation/ + * Set labels graphic options + * + * @type {Highcharts.ColorString} + */ + borderColor: 'black', + /** + * The border radius in pixels for the annotaiton's label. + * + * @sample highcharts/annotations/label-presentation/ + * Set labels graphic options + */ + borderRadius: 3, + /** + * The border width in pixels for the annotation's label + * + * @sample highcharts/annotations/label-presentation/ + * Set labels graphic options + */ + borderWidth: 1, + /** + * A class name for styling by CSS. + * + * @sample highcharts/css/annotations + * Styled mode annotations + * + * @since 6.0.5 + */ + className: '', + /** + * Whether to hide the annotation's label + * that is outside the plot area. + * + * @sample highcharts/annotations/label-crop-overflow/ + * Crop or justify labels + */ + crop: false, + /** + * The label's pixel distance from the point. + * + * @sample highcharts/annotations/label-position/ + * Set labels position + * + * @type {number} + * @apioption annotations.labelOptions.distance + */ + /** + * A + * [format](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * string for the data label. + * + * @see [plotOptions.series.dataLabels.format](plotOptions.series.dataLabels.format.html) + * + * @sample highcharts/annotations/label-text/ + * Set labels text + * + * @type {string} + * @apioption annotations.labelOptions.format + */ + /** + * Alias for the format option. + * + * @see [format](annotations.labelOptions.format.html) + * + * @sample highcharts/annotations/label-text/ + * Set labels text + * + * @type {string} + * @apioption annotations.labelOptions.text + */ + /** + * Callback JavaScript function to format the annotation's + * label. Note that if a `format` or `text` are defined, + * the format or text take precedence and the formatter is + * ignored. `This` refers to a point object. + * + * @sample highcharts/annotations/label-text/ + * Set labels text + * + * @type {Highcharts.FormatterCallbackFunction} + * @default function () { return defined(this.y) ? this.y : 'Annotation label'; } + */ + formatter: function () { + return defined(this.y) ? this.y : 'Annotation label'; + }, + /** + * Whether the annotation is visible in the exported data + * table. + * + * @sample highcharts/annotations/include-in-data-export/ + * Do not include in the data export + * + * @since 8.2.0 + * @requires modules/export-data + */ + includeInDataExport: true, + /** + * How to handle the annotation's label that flow outside + * the plot area. The justify option aligns the label inside + * the plot area. + * + * @sample highcharts/annotations/label-crop-overflow/ + * Crop or justify labels + * + * @validvalue ["allow", "justify"] + */ + overflow: 'justify', + /** + * When either the borderWidth or the backgroundColor is + * set, this is the padding within the box. + * + * @sample highcharts/annotations/label-presentation/ + * Set labels graphic options + */ + padding: 5, + /** + * The shadow of the box. The shadow can be an object + * configuration containing `color`, `offsetX`, `offsetY`, + * `opacity` and `width`. + * + * @sample highcharts/annotations/label-presentation/ + * Set labels graphic options + * + * @type {boolean|Highcharts.ShadowOptionsObject} + */ + shadow: false, + /** + * The name of a symbol to use for the border around the + * label. Symbols are predefined functions on the Renderer + * object. + * + * @sample highcharts/annotations/shapes/ + * Available shapes for labels + */ + shape: 'callout', + /** + * Styles for the annotation's label. + * + * @see [plotOptions.series.dataLabels.style](plotOptions.series.dataLabels.style.html) + * + * @sample highcharts/annotations/label-presentation/ + * Set labels graphic options + * + * @type {Highcharts.CSSObject} + */ + style: { + /** @ignore */ + fontSize: '11px', + /** @ignore */ + fontWeight: 'normal', + /** @ignore */ + color: 'contrast' + }, + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the annotation's label. + */ + useHTML: false, + /** + * The vertical alignment of the annotation's label. + * + * @sample highcharts/annotations/label-position/ + * Set labels position + * + * @type {Highcharts.VerticalAlignValue} + */ + verticalAlign: 'bottom', + /** + * The x position offset of the label relative to the point. + * Note that if a `distance` is defined, the distance takes + * precedence over `x` and `y` options. + * + * @sample highcharts/annotations/label-position/ + * Set labels position + */ + x: 0, + /** + * The y position offset of the label relative to the point. + * Note that if a `distance` is defined, the distance takes + * precedence over `x` and `y` options. + * + * @sample highcharts/annotations/label-position/ + * Set labels position + */ + y: -16 + }, + /** + * An array of labels for the annotation. For options that apply + * to multiple labels, they can be added to the + * [labelOptions](annotations.labelOptions.html). + * + * @type {Array<*>} + * @extends annotations.labelOptions + * @apioption annotations.labels + */ + /** + * This option defines the point to which the label will be + * connected. It can be either the point which exists in the + * series - it is referenced by the point's id - or a new point + * with defined x, y properties and optionally axes. + * + * @sample highcharts/annotations/mock-point/ + * Attach annotation to a mock point + * + * @declare Highcharts.AnnotationMockPointOptionsObject + * @type {string|*} + * @requires modules/annotations + * @apioption annotations.labels.point + */ + /** + * The x position of the point. Units can be either in axis + * or chart pixel coordinates. + * + * @type {number} + * @apioption annotations.labels.point.x + */ + /** + * The y position of the point. Units can be either in axis + * or chart pixel coordinates. + * + * @type {number} + * @apioption annotations.labels.point.y + */ + /** + * This number defines which xAxis the point is connected to. + * It refers to either the axis id or the index of the axis in + * the xAxis array. If the option is not configured or the axis + * is not found the point's x coordinate refers to the chart + * pixels. + * + * @type {number|string|null} + * @apioption annotations.labels.point.xAxis + */ + /** + * This number defines which yAxis the point is connected to. + * It refers to either the axis id or the index of the axis in + * the yAxis array. If the option is not configured or the axis + * is not found the point's y coordinate refers to the chart + * pixels. + * + * @type {number|string|null} + * @apioption annotations.labels.point.yAxis + */ + /** + * An array of shapes for the annotation. For options that apply + * to multiple shapes, then can be added to the + * [shapeOptions](annotations.shapeOptions.html). + * + * @type {Array<*>} + * @extends annotations.shapeOptions + * @apioption annotations.shapes + */ + /** + * This option defines the point to which the shape will be + * connected. It can be either the point which exists in the + * series - it is referenced by the point's id - or a new point + * with defined x, y properties and optionally axes. + * + * @declare Highcharts.AnnotationMockPointOptionsObject + * @type {string|Highcharts.AnnotationMockPointOptionsObject} + * @extends annotations.labels.point + * @apioption annotations.shapes.point + */ + /** + * An array of points for the shape. This option is available + * for shapes which can use multiple points such as path. A + * point can be either a point object or a point's id. + * + * @see [annotations.shapes.point](annotations.shapes.point.html) + * + * @declare Highcharts.AnnotationMockPointOptionsObject + * @type {Array} + * @extends annotations.labels.point + * @apioption annotations.shapes.points + */ + /** + * The URL for an image to use as the annotation shape. Note, + * type has to be set to `'image'`. + * + * @see [annotations.shapes.type](annotations.shapes.type) + * @sample highcharts/annotations/shape-src/ + * Define a marker image url for annotations + * + * @type {string} + * @apioption annotations.shapes.src + */ + /** + * Id of the marker which will be drawn at the final vertex of + * the path. Custom markers can be defined in defs property. + * + * @see [defs.markers](defs.markers.html) + * + * @sample highcharts/annotations/custom-markers/ + * Define a custom marker for annotations + * + * @type {string} + * @apioption annotations.shapes.markerEnd + */ + /** + * Id of the marker which will be drawn at the first vertex of + * the path. Custom markers can be defined in defs property. + * + * @see [defs.markers](defs.markers.html) + * + * @sample {highcharts} highcharts/annotations/custom-markers/ + * Define a custom marker for annotations + * + * @type {string} + * @apioption annotations.shapes.markerStart + */ + /** + * Options for annotation's shapes. Each shape inherits options + * from the shapeOptions object. An option from the shapeOptions + * can be overwritten by config for a specific shape. + * + * @requires modules/annotations + */ + shapeOptions: { + /** + * The width of the shape. + * + * @sample highcharts/annotations/shape/ + * Basic shape annotation + * + * @type {number} + * @apioption annotations.shapeOptions.width + **/ + /** + * The height of the shape. + * + * @sample highcharts/annotations/shape/ + * Basic shape annotation + * + * @type {number} + * @apioption annotations.shapeOptions.height + */ + /** + * The type of the shape, e.g. circle or rectangle. + * + * @sample highcharts/annotations/shape/ + * Basic shape annotation + * + * @type {string} + * @default 'rect' + * @apioption annotations.shapeOptions.type + */ + /** + * The URL for an image to use as the annotation shape. + * Note, type has to be set to `'image'`. + * + * @see [annotations.shapeOptions.type](annotations.shapeOptions.type) + * @sample highcharts/annotations/shape-src/ + * Define a marker image url for annotations + * + * @type {string} + * @apioption annotations.shapeOptions.src + */ + /** + * Name of the dash style to use for the shape's stroke. + * + * @sample {highcharts} highcharts/plotoptions/series-dashstyle-all/ + * Possible values demonstrated + * + * @type {Highcharts.DashStyleValue} + * @apioption annotations.shapeOptions.dashStyle + */ + /** + * The color of the shape's stroke. + * + * @sample highcharts/annotations/shape/ + * Basic shape annotation + * + * @type {Highcharts.ColorString} + */ + stroke: 'rgba(0, 0, 0, 0.75)', + /** + * The pixel stroke width of the shape. + * + * @sample highcharts/annotations/shape/ + * Basic shape annotation + */ + strokeWidth: 1, + /** + * The color of the shape's fill. + * + * @sample highcharts/annotations/shape/ + * Basic shape annotation + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + fill: 'rgba(0, 0, 0, 0.75)', + /** + * The radius of the shape. + * + * @sample highcharts/annotations/shape/ + * Basic shape annotation + */ + r: 0, + /** + * Defines additional snapping area around an annotation + * making this annotation to focus. Defined in pixels. + */ + snap: 2 + }, + /** + * Options for annotation's control points. Each control point + * inherits options from controlPointOptions object. + * Options from the controlPointOptions can be overwritten + * by options in a specific control point. + * + * @declare Highcharts.AnnotationControlPointOptionsObject + * @requires modules/annotations + * @apioption annotations.controlPointOptions + */ + controlPointOptions: { + /** + * @type {Highcharts.AnnotationControlPointPositionerFunction} + * @apioption annotations.controlPointOptions.positioner + */ + symbol: 'circle', + width: 10, + height: 10, + style: { + stroke: 'black', + 'stroke-width': 2, + fill: 'white' + }, + visible: false, + events: {} + }, + /** + * Event callback when annotation is added to the chart. + * + * @type {Highcharts.EventCallbackFunction} + * @since 7.1.0 + * @apioption annotations.events.add + */ + /** + * Event callback when annotation is updated (e.g. drag and + * droppped or resized by control points). + * + * @type {Highcharts.EventCallbackFunction} + * @since 7.1.0 + * @apioption annotations.events.afterUpdate + */ + /** + * Event callback when annotation is removed from the chart. + * + * @type {Highcharts.EventCallbackFunction} + * @since 7.1.0 + * @apioption annotations.events.remove + */ + /** + * Events available in annotations. + * + * @requires modules/annotations + */ + events: {}, + /** + * The Z index of the annotation. + */ + zIndex: 6 + } + })); + H.extendAnnotation = function (Constructor, BaseConstructor, prototype, defaultOptions) { + BaseConstructor = BaseConstructor || Annotation; + merge(true, Constructor.prototype, BaseConstructor.prototype, prototype); + Constructor.prototype.defaultOptions = merge(Constructor.prototype.defaultOptions, defaultOptions || {}); + }; + /* ********************************************************************* + * + * EXTENDING CHART PROTOTYPE + * + ******************************************************************** */ + extend(chartProto, /** @lends Highcharts.Chart# */ { + initAnnotation: function (userOptions) { + var Constructor = Annotation.types[userOptions.type] || Annotation, + annotation = new Constructor(this, + userOptions); + this.annotations.push(annotation); + return annotation; + }, + /** + * Add an annotation to the chart after render time. + * + * @param {Highcharts.AnnotationsOptions} options + * The annotation options for the new, detailed annotation. + * @param {boolean} [redraw] + * + * @return {Highcharts.Annotation} - The newly generated annotation. + */ + addAnnotation: function (userOptions, redraw) { + var annotation = this.initAnnotation(userOptions); + this.options.annotations.push(annotation.options); + if (pick(redraw, true)) { + annotation.redraw(); + annotation.graphic.attr({ + opacity: 1 + }); + } + return annotation; + }, + /** + * Remove an annotation from the chart. + * + * @param {number|string|Highcharts.Annotation} idOrAnnotation + * The annotation's id or direct annotation object. + */ + removeAnnotation: function (idOrAnnotation) { + var annotations = this.annotations, + annotation = idOrAnnotation.coll === 'annotations' ? + idOrAnnotation : + find(annotations, + function (annotation) { + return annotation.options.id === idOrAnnotation; + }); + if (annotation) { + fireEvent(annotation, 'remove'); + erase(this.options.annotations, annotation.options); + erase(annotations, annotation); + annotation.destroy(); + } + }, + drawAnnotations: function () { + this.plotBoxClip.attr(this.plotBox); + this.annotations.forEach(function (annotation) { + annotation.redraw(); + annotation.graphic.animate({ + opacity: 1 + }, annotation.animationConfig); + }); + } + }); + // Let chart.update() update annotations + chartProto.collectionsWithUpdate.push('annotations'); + // Let chart.update() create annoations on demand + chartProto.collectionsWithInit.annotations = [chartProto.addAnnotation]; + chartProto.callbacks.push(function (chart) { + chart.annotations = []; + if (!chart.options.annotations) { + chart.options.annotations = []; + } + chart.plotBoxClip = this.renderer.clipRect(this.plotBox); + chart.controlPointsGroup = chart.renderer + .g('control-points') + .attr({ zIndex: 99 }) + .clip(chart.plotBoxClip) + .add(); + chart.options.annotations.forEach(function (annotationOptions, i) { + var annotation = chart.initAnnotation(annotationOptions); + chart.options.annotations[i] = annotation.options; + }); + chart.drawAnnotations(); + addEvent(chart, 'redraw', chart.drawAnnotations); + addEvent(chart, 'destroy', function () { + chart.plotBoxClip.destroy(); + chart.controlPointsGroup.destroy(); + }); + addEvent(chart, 'exportData', function (event) { + var _a, + _b, + _c, + _d, + _e, + _f, + _g, + _h; + var annotations = chart.annotations, + csvColumnHeaderFormatter = ((this.options.exporting && + this.options.exporting.csv) || + {}).columnHeaderFormatter, + // If second row doesn't have xValues + // then it is a title row thus multiple level header is in use. + multiLevelHeaders = !event.dataRows[1].xValues, + annotationHeader = (_b = (_a = chart.options.lang) === null || _a === void 0 ? void 0 : _a.exportData) === null || _b === void 0 ? void 0 : _b.annotationHeader, + columnHeaderFormatter = function (index) { + var s; + if (csvColumnHeaderFormatter) { + s = csvColumnHeaderFormatter(index); + if (s !== false) { + return s; + } + } + s = annotationHeader + ' ' + index; + if (multiLevelHeaders) { + return { + columnTitle: s, + topLevelColumnTitle: s + }; + } + return s; + }, startRowLength = event.dataRows[0].length, annotationSeparator = (_e = (_d = (_c = chart.options.exporting) === null || _c === void 0 ? void 0 : _c.csv) === null || _d === void 0 ? void 0 : _d.annotations) === null || _e === void 0 ? void 0 : _e.itemDelimiter, joinAnnotations = (_h = (_g = (_f = chart.options.exporting) === null || _f === void 0 ? void 0 : _f.csv) === null || _g === void 0 ? void 0 : _g.annotations) === null || _h === void 0 ? void 0 : _h.join; + annotations.forEach(function (annotation) { + if (annotation.options.labelOptions.includeInDataExport) { + annotation.labels.forEach(function (label) { + if (label.options.text) { + var annotationText_1 = label.options.text; + label.points.forEach(function (points) { + var annotationX = points.x, + xAxisIndex = points.series.xAxis ? + points.series.xAxis.options.index : + -1; + var wasAdded = false; + // Annotation not connected to any xAxis - + // add new row. + if (xAxisIndex === -1) { + var n = event.dataRows[0].length, + newRow = new Array(n); + for (var i = 0; i < n; ++i) { + newRow[i] = ''; + } + newRow.push(annotationText_1); + newRow.xValues = []; + newRow.xValues[xAxisIndex] = annotationX; + event.dataRows.push(newRow); + wasAdded = true; + } + // Annotation placed on a exported data point + // - add new column + if (!wasAdded) { + event.dataRows.forEach(function (row, rowIndex) { + if (!wasAdded && + row.xValues && + xAxisIndex !== void 0 && + annotationX === row.xValues[xAxisIndex]) { + if (joinAnnotations && + row.length > startRowLength) { + row[row.length - 1] += + annotationSeparator + annotationText_1; + } + else { + row.push(annotationText_1); + } + wasAdded = true; + } + }); + } + // Annotation not placed on any exported data point, + // but connected to the xAxis - add new row + if (!wasAdded) { + var n = event.dataRows[0].length, + newRow = new Array(n); + for (var i = 0; i < n; ++i) { + newRow[i] = ''; + } + newRow[0] = annotationX; + newRow.push(annotationText_1); + newRow.xValues = []; + if (xAxisIndex !== void 0) { + newRow.xValues[xAxisIndex] = annotationX; + } + event.dataRows.push(newRow); + } + }); + } + }); + } + }); + var maxRowLen = 0; + event.dataRows.forEach(function (row) { + maxRowLen = Math.max(maxRowLen, row.length); + }); + var newRows = maxRowLen - event.dataRows[0].length; + for (var i = 0; i < newRows; i++) { + var header = columnHeaderFormatter(i + 1); + if (multiLevelHeaders) { + event.dataRows[0].push(header.topLevelColumnTitle); + event.dataRows[1].push(header.columnTitle); + } + else { + event.dataRows[0].push(header); + } + } + }); + }); + wrap(Pointer.prototype, 'onContainerMouseDown', function (proceed) { + if (!this.chart.hasDraggedAnnotation) { + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + } + }); + H.Annotation = Annotation; + + return Annotation; + }); + _registerModule(_modules, 'Mixins/Navigation.js', [], function () { + /** + * + * (c) 2010-2018 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var chartNavigation = { + /** + * Initializes `chart.navigation` object which delegates `update()` methods + * to all other common classes (used in exporting and navigationBindings). + * + * @private + * @param {Highcharts.Chart} chart + * The chart instance. + * @return {void} + */ + initUpdate: function (chart) { + if (!chart.navigation) { + chart.navigation = { + updates: [], + update: function (options, + redraw) { + this.updates.forEach(function (updateConfig) { + updateConfig.update.call(updateConfig.context, + options, + redraw); + }); + } + }; + } + }, + /** + * Registers an `update()` method in the `chart.navigation` object. + * + * @private + * @param {Highcharts.ChartNavigationUpdateFunction} update + * The `update()` method that will be called in `chart.update()`. + * @param {Highcharts.Chart} chart + * The chart instance. `update()` will use that as a context + * (`this`). + * @return {void} + */ + addUpdate: function (update, chart) { + if (!chart.navigation) { + this.initUpdate(chart); + } + chart.navigation.updates.push({ + update: update, + context: chart + }); + } + }; + + return chartNavigation; + }); + _registerModule(_modules, 'Extensions/Annotations/NavigationBindings.js', [_modules['Extensions/Annotations/Annotations.js'], _modules['Mixins/Navigation.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (Annotation, chartNavigationMixin, H, U) { + /* * + * + * (c) 2009-2017 Highsoft, Black Label + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + attr = U.attr, + extend = U.extend, + format = U.format, + fireEvent = U.fireEvent, + isArray = U.isArray, + isFunction = U.isFunction, + isNumber = U.isNumber, + isObject = U.isObject, + merge = U.merge, + objectEach = U.objectEach, + pick = U.pick, + setOptions = U.setOptions; + /** + * A config object for navigation bindings in annotations. + * + * @interface Highcharts.NavigationBindingsOptionsObject + */ /** + * ClassName of the element for a binding. + * @name Highcharts.NavigationBindingsOptionsObject#className + * @type {string|undefined} + */ /** + * Last event to be fired after last step event. + * @name Highcharts.NavigationBindingsOptionsObject#end + * @type {Function|undefined} + */ /** + * Initial event, fired on a button click. + * @name Highcharts.NavigationBindingsOptionsObject#init + * @type {Function|undefined} + */ /** + * Event fired on first click on a chart. + * @name Highcharts.NavigationBindingsOptionsObject#start + * @type {Function|undefined} + */ /** + * Last event to be fired after last step event. Array of step events to be + * called sequentially after each user click. + * @name Highcharts.NavigationBindingsOptionsObject#steps + * @type {Array|undefined} + */ + var doc = H.doc, + win = H.win, + PREFIX = 'highcharts-'; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * IE 9-11 polyfill for Element.closest(): + * @private + */ + function closestPolyfill(el, s) { + var ElementProto = win.Element.prototype, + elementMatches = ElementProto.matches || + ElementProto.msMatchesSelector || + ElementProto.webkitMatchesSelector, + ret = null; + if (ElementProto.closest) { + ret = ElementProto.closest.call(el, s); + } + else { + do { + if (elementMatches.call(el, s)) { + return el; + } + el = el.parentElement || el.parentNode; + } while (el !== null && el.nodeType === 1); + } + return ret; + } + /** + * @private + * @interface bindingsUtils + */ + var bindingsUtils = { + /** + * Update size of background (rect) in some annotations: Measure, + Simple + * Rect. + * + * @private + * @function Highcharts.NavigationBindingsUtilsObject.updateRectSize + * + * @param {Highcharts.PointerEventObject} event + * Normalized browser event + * + * @param {Highcharts.Annotation} annotation + * Annotation to be updated + */ + updateRectSize: function (event, + annotation) { + var chart = annotation.chart, + options = annotation.options.typeOptions, + coords = chart.pointer.getCoordinates(event), + width = coords.xAxis[0].value - options.point.x, + height = options.point.y - coords.yAxis[0].value; + annotation.update({ + typeOptions: { + background: { + width: chart.inverted ? height : width, + height: chart.inverted ? width : height + } + } + }); + }, + /** + * Get field type according to value + * + * @private + * @function Highcharts.NavigationBindingsUtilsObject.getFieldType + * + * @param {'boolean'|'number'|'string'} value + * Atomic type (one of: string, number, boolean) + * + * @return {'checkbox'|'number'|'text'} + * Field type (one of: text, number, checkbox) + */ + getFieldType: function (value) { + return { + 'string': 'text', + 'number': 'number', + 'boolean': 'checkbox' + }[typeof value]; + } + }; + /** + * @private + */ + var NavigationBindings = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function NavigationBindings(chart, options) { + this.boundClassNames = void 0; + this.selectedButton = void 0; + this.chart = chart; + this.options = options; + this.eventsToUnbind = []; + this.container = doc.getElementsByClassName(this.options.bindingsClassName || ''); + } + // Private properties added by bindings: + // Active (selected) annotation that is editted through popup/forms + // activeAnnotation: Annotation + // Holder for current step, used on mouse move to update bound object + // mouseMoveEvent: function () {} + // Next event in `step` array to be called on chart's click + // nextEvent: function () {} + // Index in the `step` array of the current event + // stepIndex: 0 + // Flag to determine if current binding has steps + // steps: true|false + // Bindings holder for all events + // selectedButton: {} + // Holder for user options, returned from `start` event, and passed on to + // `step`'s' and `end`. + // currentUserDetails: {} + /* * + * + * Functions + * + * */ + /** + * Initi all events conencted to NavigationBindings. + * + * @private + * @function Highcharts.NavigationBindings#initEvents + */ + NavigationBindings.prototype.initEvents = function () { + var navigation = this, + chart = navigation.chart, + bindingsContainer = navigation.container, + options = navigation.options; + // Shorthand object for getting events for buttons: + navigation.boundClassNames = {}; + objectEach((options.bindings || {}), function (value) { + navigation.boundClassNames[value.className] = value; + }); + // Handle multiple containers with the same class names: + [].forEach.call(bindingsContainer, function (subContainer) { + navigation.eventsToUnbind.push(addEvent(subContainer, 'click', function (event) { + var bindings = navigation.getButtonEvents(subContainer, + event); + if (bindings) { + navigation.bindingsButtonClick(bindings.button, bindings.events, event); + } + })); + }); + objectEach(options.events || {}, function (callback, eventName) { + if (isFunction(callback)) { + navigation.eventsToUnbind.push(addEvent(navigation, eventName, callback)); + } + }); + navigation.eventsToUnbind.push(addEvent(chart.container, 'click', function (e) { + if (!chart.cancelClick && + chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop)) { + navigation.bindingsChartClick(this, e); + } + })); + navigation.eventsToUnbind.push(addEvent(chart.container, H.isTouchDevice ? 'touchmove' : 'mousemove', function (e) { + navigation.bindingsContainerMouseMove(this, e); + })); + }; + /** + * Common chart.update() delegation, shared between bindings and exporting. + * + * @private + * @function Highcharts.NavigationBindings#initUpdate + */ + NavigationBindings.prototype.initUpdate = function () { + var navigation = this; + chartNavigationMixin.addUpdate(function (options) { + navigation.update(options); + }, this.chart); + }; + /** + * Hook for click on a button, method selcts/unselects buttons, + * then calls `bindings.init` callback. + * + * @private + * @function Highcharts.NavigationBindings#bindingsButtonClick + * + * @param {Highcharts.HTMLDOMElement} [button] + * Clicked button + * + * @param {object} events + * Events passed down from bindings (`init`, `start`, `step`, `end`) + * + * @param {Highcharts.PointerEventObject} clickEvent + * Browser's click event + */ + NavigationBindings.prototype.bindingsButtonClick = function (button, events, clickEvent) { + var navigation = this, + chart = navigation.chart; + if (navigation.selectedButtonElement) { + fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement }); + if (navigation.nextEvent) { + // Remove in-progress annotations adders: + if (navigation.currentUserDetails && + navigation.currentUserDetails.coll === 'annotations') { + chart.removeAnnotation(navigation.currentUserDetails); + } + navigation.mouseMoveEvent = navigation.nextEvent = false; + } + } + navigation.selectedButton = events; + navigation.selectedButtonElement = button; + fireEvent(navigation, 'selectButton', { button: button }); + // Call "init" event, for example to open modal window + if (events.init) { + events.init.call(navigation, button, clickEvent); + } + if (events.start || events.steps) { + chart.renderer.boxWrapper.addClass(PREFIX + 'draw-mode'); + } + }; + /** + * Hook for click on a chart, first click on a chart calls `start` event, + * then on all subsequent clicks iterate over `steps` array. + * When finished, calls `end` event. + * + * @private + * @function Highcharts.NavigationBindings#bindingsChartClick + * + * @param {Highcharts.Chart} chart + * Chart that click was performed on. + * + * @param {Highcharts.PointerEventObject} clickEvent + * Browser's click event. + */ + NavigationBindings.prototype.bindingsChartClick = function (chart, clickEvent) { + var navigation = this, + chart = navigation.chart, + selectedButton = navigation.selectedButton, + svgContainer = chart.renderer.boxWrapper; + // Click outside popups, should close them and deselect the annotation + if (navigation.activeAnnotation && + !clickEvent.activeAnnotation && + // Element could be removed in the child action, e.g. button + clickEvent.target.parentNode && + // TO DO: Polyfill for IE11? + !closestPolyfill(clickEvent.target, '.' + PREFIX + 'popup')) { + fireEvent(navigation, 'closePopup'); + navigation.deselectAnnotation(); + } + if (!selectedButton || !selectedButton.start) { + return; + } + if (!navigation.nextEvent) { + // Call init method: + navigation.currentUserDetails = selectedButton.start.call(navigation, clickEvent); + // If steps exists (e.g. Annotations), bind them: + if (selectedButton.steps) { + navigation.stepIndex = 0; + navigation.steps = true; + navigation.mouseMoveEvent = navigation.nextEvent = + selectedButton.steps[navigation.stepIndex]; + } + else { + fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement }); + svgContainer.removeClass(PREFIX + 'draw-mode'); + navigation.steps = false; + navigation.selectedButton = null; + // First click is also the last one: + if (selectedButton.end) { + selectedButton.end.call(navigation, clickEvent, navigation.currentUserDetails); + } + } + } + else { + navigation.nextEvent(clickEvent, navigation.currentUserDetails); + if (navigation.steps) { + navigation.stepIndex++; + if (selectedButton.steps[navigation.stepIndex]) { + // If we have more steps, bind them one by one: + navigation.mouseMoveEvent = navigation.nextEvent = + selectedButton.steps[navigation.stepIndex]; + } + else { + fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement }); + svgContainer.removeClass(PREFIX + 'draw-mode'); + // That was the last step, call end(): + if (selectedButton.end) { + selectedButton.end.call(navigation, clickEvent, navigation.currentUserDetails); + } + navigation.nextEvent = false; + navigation.mouseMoveEvent = false; + navigation.selectedButton = null; + } + } + } + }; + /** + * Hook for mouse move on a chart's container. It calls current step. + * + * @private + * @function Highcharts.NavigationBindings#bindingsContainerMouseMove + * + * @param {Highcharts.HTMLDOMElement} container + * Chart's container. + * + * @param {global.Event} moveEvent + * Browser's move event. + */ + NavigationBindings.prototype.bindingsContainerMouseMove = function (_container, moveEvent) { + if (this.mouseMoveEvent) { + this.mouseMoveEvent(moveEvent, this.currentUserDetails); + } + }; + /** + * Translate fields (e.g. `params.period` or `marker.styles.color`) to + * Highcharts options object (e.g. `{ params: { period } }`). + * + * @private + * @function Highcharts.NavigationBindings#fieldsToOptions + * + * @param {Highcharts.Dictionary} fields + * Fields from popup form. + * + * @param {T} config + * Default config to be modified. + * + * @return {T} + * Modified config + */ + NavigationBindings.prototype.fieldsToOptions = function (fields, config) { + objectEach(fields, function (value, field) { + var parsedValue = parseFloat(value), + path = field.split('.'), + parent = config, + pathLength = path.length - 1; + // If it's a number (not "format" options), parse it: + if (isNumber(parsedValue) && + !value.match(/px/g) && + !field.match(/format/g)) { + value = parsedValue; + } + // Remove empty strings or values like 0 + if (value !== '' && value !== 'undefined') { + path.forEach(function (name, index) { + var nextName = pick(path[index + 1], ''); + if (pathLength === index) { + // Last index, put value: + parent[name] = value; + } + else if (!parent[name]) { + // Create middle property: + parent[name] = nextName.match(/\d/g) ? [] : {}; + parent = parent[name]; + } + else { + // Jump into next property + parent = parent[name]; + } + }); + } + }); + return config; + }; + /** + * Shorthand method to deselect an annotation. + * + * @function Highcharts.NavigationBindings#deselectAnnotation + */ + NavigationBindings.prototype.deselectAnnotation = function () { + if (this.activeAnnotation) { + this.activeAnnotation.setControlPointsVisibility(false); + this.activeAnnotation = false; + } + }; + /** + * Generates API config for popup in the same format as options for + * Annotation object. + * + * @function Highcharts.NavigationBindings#annotationToFields + * + * @param {Highcharts.Annotation} annotation + * Annotations object + * + * @return {Highcharts.Dictionary} + * Annotation options to be displayed in popup box + */ + NavigationBindings.prototype.annotationToFields = function (annotation) { + var options = annotation.options, + editables = NavigationBindings.annotationsEditable, + nestedEditables = editables.nestedOptions, + getFieldType = this.utils.getFieldType, + type = pick(options.type, + options.shapes && options.shapes[0] && + options.shapes[0].type, + options.labels && options.labels[0] && + options.labels[0].itemType, 'label'), + nonEditables = NavigationBindings.annotationsNonEditable[options.langKey] || [], + visualOptions = { + langKey: options.langKey, + type: type + }; + /** + * Nested options traversing. Method goes down to the options and copies + * allowed options (with values) to new object, which is last parameter: + * "parent". + * + * @private + * + * @param {*} option + * Atomic type or object/array + * + * @param {string} key + * Option name, for example "visible" or "x", "y" + * + * @param {object} parentEditables + * Editables from NavigationBindings.annotationsEditable + * + * @param {object} parent + * Where new options will be assigned + */ + function traverse(option, key, parentEditables, parent) { + var nextParent; + if (parentEditables && + option && + nonEditables.indexOf(key) === -1 && + ((parentEditables.indexOf && + parentEditables.indexOf(key)) >= 0 || + parentEditables[key] || // nested array + parentEditables === true // simple array + )) { + // Roots: + if (isArray(option)) { + parent[key] = []; + option.forEach(function (arrayOption, i) { + if (!isObject(arrayOption)) { + // Simple arrays, e.g. [String, Number, Boolean] + traverse(arrayOption, 0, nestedEditables[key], parent[key]); + } + else { + // Advanced arrays, e.g. [Object, Object] + parent[key][i] = {}; + objectEach(arrayOption, function (nestedOption, nestedKey) { + traverse(nestedOption, nestedKey, nestedEditables[key], parent[key][i]); + }); + } + }); + } + else if (isObject(option)) { + nextParent = {}; + if (isArray(parent)) { + parent.push(nextParent); + nextParent[key] = {}; + nextParent = nextParent[key]; + } + else { + parent[key] = nextParent; + } + objectEach(option, function (nestedOption, nestedKey) { + traverse(nestedOption, nestedKey, key === 0 ? parentEditables : nestedEditables[key], nextParent); + }); + } + else { + // Leaf: + if (key === 'format') { + parent[key] = [ + format(option, annotation.labels[0].points[0]).toString(), + 'text' + ]; + } + else if (isArray(parent)) { + parent.push([option, getFieldType(option)]); + } + else { + parent[key] = [option, getFieldType(option)]; + } + } + } + } + objectEach(options, function (option, key) { + if (key === 'typeOptions') { + visualOptions[key] = {}; + objectEach(options[key], function (typeOption, typeKey) { + traverse(typeOption, typeKey, nestedEditables, visualOptions[key], true); + }); + } + else { + traverse(option, key, editables[type], visualOptions); + } + }); + return visualOptions; + }; + /** + * Get all class names for all parents in the element. Iterates until finds + * main container. + * + * @function Highcharts.NavigationBindings#getClickedClassNames + * + * @param {Highcharts.HTMLDOMElement} + * Container that event is bound to. + * + * @param {global.Event} event + * Browser's event. + * + * @return {Array>} + * Array of class names with corresponding elements + */ + NavigationBindings.prototype.getClickedClassNames = function (container, event) { + var element = event.target, + classNames = [], + elemClassName; + while (element) { + elemClassName = attr(element, 'class'); + if (elemClassName) { + classNames = classNames.concat(elemClassName + .split(' ') + .map(function (name) { + return [ + name, + element + ]; + })); + } + element = element.parentNode; + if (element === container) { + return classNames; + } + } + return classNames; + }; + /** + * Get events bound to a button. It's a custom event delegation to find all + * events connected to the element. + * + * @private + * @function Highcharts.NavigationBindings#getButtonEvents + * + * @param {Highcharts.HTMLDOMElement} container + * Container that event is bound to. + * + * @param {global.Event} event + * Browser's event. + * + * @return {object} + * Object with events (init, start, steps, and end) + */ + NavigationBindings.prototype.getButtonEvents = function (container, event) { + var navigation = this, + classNames = this.getClickedClassNames(container, + event), + bindings; + classNames.forEach(function (className) { + if (navigation.boundClassNames[className[0]] && !bindings) { + bindings = { + events: navigation.boundClassNames[className[0]], + button: className[1] + }; + } + }); + return bindings; + }; + /** + * Bindings are just events, so the whole update process is simply + * removing old events and adding new ones. + * + * @private + * @function Highcharts.NavigationBindings#update + */ + NavigationBindings.prototype.update = function (options) { + this.options = merge(true, this.options, options); + this.removeEvents(); + this.initEvents(); + }; + /** + * Remove all events created in the navigation. + * + * @private + * @function Highcharts.NavigationBindings#removeEvents + */ + NavigationBindings.prototype.removeEvents = function () { + this.eventsToUnbind.forEach(function (unbinder) { + unbinder(); + }); + }; + NavigationBindings.prototype.destroy = function () { + this.removeEvents(); + }; + /* * + * + * Static Properties + * + * */ + // Define which options from annotations should show up in edit box: + NavigationBindings.annotationsEditable = { + // `typeOptions` are always available + // Nested and shared options: + nestedOptions: { + labelOptions: ['style', 'format', 'backgroundColor'], + labels: ['style'], + label: ['style'], + style: ['fontSize', 'color'], + background: ['fill', 'strokeWidth', 'stroke'], + innerBackground: ['fill', 'strokeWidth', 'stroke'], + outerBackground: ['fill', 'strokeWidth', 'stroke'], + shapeOptions: ['fill', 'strokeWidth', 'stroke'], + shapes: ['fill', 'strokeWidth', 'stroke'], + line: ['strokeWidth', 'stroke'], + backgroundColors: [true], + connector: ['fill', 'strokeWidth', 'stroke'], + crosshairX: ['strokeWidth', 'stroke'], + crosshairY: ['strokeWidth', 'stroke'] + }, + // Simple shapes: + circle: ['shapes'], + verticalLine: [], + label: ['labelOptions'], + // Measure + measure: ['background', 'crosshairY', 'crosshairX'], + // Others: + fibonacci: [], + tunnel: ['background', 'line', 'height'], + pitchfork: ['innerBackground', 'outerBackground'], + rect: ['shapes'], + // Crooked lines, elliots, arrows etc: + crookedLine: [], + basicAnnotation: ['shapes', 'labelOptions'] + }; + // Define non editable fields per annotation, for example Rectangle inherits + // options from Measure, but crosshairs are not available + NavigationBindings.annotationsNonEditable = { + rectangle: ['crosshairX', 'crosshairY', 'label'] + }; + return NavigationBindings; + }()); + /** + * General utils for bindings + * + * @private + * @name Highcharts.NavigationBindings.utils + * @type {bindingsUtils} + */ + NavigationBindings.prototype.utils = bindingsUtils; + H.Chart.prototype.initNavigationBindings = function () { + var chart = this, + options = chart.options; + if (options && options.navigation && options.navigation.bindings) { + chart.navigationBindings = new NavigationBindings(chart, options.navigation); + chart.navigationBindings.initEvents(); + chart.navigationBindings.initUpdate(); + } + }; + addEvent(H.Chart, 'load', function () { + this.initNavigationBindings(); + }); + addEvent(H.Chart, 'destroy', function () { + if (this.navigationBindings) { + this.navigationBindings.destroy(); + } + }); + addEvent(NavigationBindings, 'deselectButton', function () { + this.selectedButtonElement = null; + }); + addEvent(Annotation, 'remove', function () { + if (this.chart.navigationBindings) { + this.chart.navigationBindings.deselectAnnotation(); + } + }); + /** + * Show edit-annotation form: + * @private + */ + function selectableAnnotation(annotationType) { + var originalClick = annotationType.prototype.defaultOptions.events && + annotationType.prototype.defaultOptions.events.click; + /** + * @private + */ + function selectAndshowPopup(event) { + var annotation = this, + navigation = annotation.chart.navigationBindings, + prevAnnotation = navigation.activeAnnotation; + if (originalClick) { + originalClick.call(annotation, event); + } + if (prevAnnotation !== annotation) { + // Select current: + navigation.deselectAnnotation(); + navigation.activeAnnotation = annotation; + annotation.setControlPointsVisibility(true); + fireEvent(navigation, 'showPopup', { + annotation: annotation, + formType: 'annotation-toolbar', + options: navigation.annotationToFields(annotation), + onSubmit: function (data) { + var config = {}, + typeOptions; + if (data.actionType === 'remove') { + navigation.activeAnnotation = false; + navigation.chart.removeAnnotation(annotation); + } + else { + navigation.fieldsToOptions(data.fields, config); + navigation.deselectAnnotation(); + typeOptions = config.typeOptions; + if (annotation.options.type === 'measure') { + // Manually disable crooshars according to + // stroke width of the shape: + typeOptions.crosshairY.enabled = + typeOptions.crosshairY.strokeWidth !== 0; + typeOptions.crosshairX.enabled = + typeOptions.crosshairX.strokeWidth !== 0; + } + annotation.update(config); + } + } + }); + } + else { + // Deselect current: + navigation.deselectAnnotation(); + fireEvent(navigation, 'closePopup'); + } + // Let bubble event to chart.click: + event.activeAnnotation = true; + } + merge(true, annotationType.prototype.defaultOptions.events, { + click: selectAndshowPopup + }); + } + if (H.Annotation) { + // Basic shapes: + selectableAnnotation(Annotation); + // Advanced annotations: + objectEach(Annotation.types, function (annotationType) { + selectableAnnotation(annotationType); + }); + } + setOptions({ + /** + * @optionparent lang + * + * @private + */ + lang: { + /** + * Configure the Popup strings in the chart. Requires the + * `annotations.js` or `annotations-advanced.src.js` module to be + * loaded. + * + * @since 7.0.0 + * @product highcharts highstock + */ + navigation: { + /** + * Translations for all field names used in popup. + * + * @product highcharts highstock + */ + popup: { + simpleShapes: 'Simple shapes', + lines: 'Lines', + circle: 'Circle', + rectangle: 'Rectangle', + label: 'Label', + shapeOptions: 'Shape options', + typeOptions: 'Details', + fill: 'Fill', + format: 'Text', + strokeWidth: 'Line width', + stroke: 'Line color', + title: 'Title', + name: 'Name', + labelOptions: 'Label options', + labels: 'Labels', + backgroundColor: 'Background color', + backgroundColors: 'Background colors', + borderColor: 'Border color', + borderRadius: 'Border radius', + borderWidth: 'Border width', + style: 'Style', + padding: 'Padding', + fontSize: 'Font size', + color: 'Color', + height: 'Height', + shapes: 'Shape options' + } + } + }, + /** + * @optionparent navigation + * @product highcharts highstock + * + * @private + */ + navigation: { + /** + * A CSS class name where all bindings will be attached to. Multiple + * charts on the same page should have separate class names to prevent + * duplicating events. + * + * Default value of versions < 7.0.4 `highcharts-bindings-wrapper` + * + * @since 7.0.0 + * @type {string} + */ + bindingsClassName: 'highcharts-bindings-container', + /** + * Bindings definitions for custom HTML buttons. Each binding implements + * simple event-driven interface: + * + * - `className`: classname used to bind event to + * + * - `init`: initial event, fired on button click + * + * - `start`: fired on first click on a chart + * + * - `steps`: array of sequential events fired one after another on each + * of users clicks + * + * - `end`: last event to be called after last step event + * + * @type {Highcharts.Dictionary|*} + * @sample stock/stocktools/stocktools-thresholds + * Custom bindings in Highstock + * @since 7.0.0 + * @product highcharts highstock + */ + bindings: { + /** + * A circle annotation bindings. Includes `start` and one event in + * `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @default {"className": "highcharts-circle-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + circleAnnotation: { + /** @ignore-option */ + className: 'highcharts-circle-annotation', + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), + navigation = this.chart.options.navigation; + return this.chart.addAnnotation(merge({ + langKey: 'circle', + type: 'basicAnnotation', + shapes: [{ + type: 'circle', + point: { + xAxis: 0, + yAxis: 0, + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, + r: 5 + }] + }, navigation + .annotationsOptions, navigation + .bindings + .circleAnnotation + .annotationsOptions)); + }, + /** @ignore-option */ + steps: [ + function (e, annotation) { + var point = annotation.options.shapes[0].point, + x = this.chart.xAxis[0].toPixels(point.x), + y = this.chart.yAxis[0].toPixels(point.y), + inverted = this.chart.inverted, + distance = Math.max(Math.sqrt(Math.pow(inverted ? y - e.chartX : x - e.chartX, 2) + + Math.pow(inverted ? x - e.chartY : y - e.chartY, 2)), 5); + annotation.update({ + shapes: [{ + r: distance + }] + }); + } + ] + }, + /** + * A rectangle annotation bindings. Includes `start` and one event + * in `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @default {"className": "highcharts-rectangle-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + rectangleAnnotation: { + /** @ignore-option */ + className: 'highcharts-rectangle-annotation', + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), + navigation = this.chart.options.navigation, + x = coords.xAxis[0].value, + y = coords.yAxis[0].value; + return this.chart.addAnnotation(merge({ + langKey: 'rectangle', + type: 'basicAnnotation', + shapes: [{ + type: 'path', + points: [{ + xAxis: 0, + yAxis: 0, + x: x, + y: y + }, { + xAxis: 0, + yAxis: 0, + x: x, + y: y + }, { + xAxis: 0, + yAxis: 0, + x: x, + y: y + }, { + xAxis: 0, + yAxis: 0, + x: x, + y: y + }] + }] + }, navigation + .annotationsOptions, navigation + .bindings + .rectangleAnnotation + .annotationsOptions)); + }, + /** @ignore-option */ + steps: [ + function (e, annotation) { + var points = annotation.options.shapes[0].points, + coords = this.chart.pointer.getCoordinates(e), + x = coords.xAxis[0].value, + y = coords.yAxis[0].value; + // Top right point + points[1].x = x; + // Bottom right point (cursor position) + points[2].x = x; + points[2].y = y; + // Bottom left + points[3].y = y; + annotation.update({ + shapes: [{ + points: points + }] + }); + } + ] + }, + /** + * A label annotation bindings. Includes `start` event only. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @default {"className": "highcharts-label-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + labelAnnotation: { + /** @ignore-option */ + className: 'highcharts-label-annotation', + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), + navigation = this.chart.options.navigation; + return this.chart.addAnnotation(merge({ + langKey: 'label', + type: 'basicAnnotation', + labelOptions: { + format: '{y:.2f}' + }, + labels: [{ + point: { + xAxis: 0, + yAxis: 0, + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, + overflow: 'none', + crop: true + }] + }, navigation + .annotationsOptions, navigation + .bindings + .labelAnnotation + .annotationsOptions)); + } + } + }, + /** + * Path where Highcharts will look for icons. Change this to use icons + * from a different server. + * + * @type {string} + * @default https://code.highcharts.com/8.2.0/gfx/stock-icons/ + * @since 7.1.3 + * @apioption navigation.iconsURL + */ + /** + * A `showPopup` event. Fired when selecting for example an annotation. + * + * @type {Function} + * @apioption navigation.events.showPopup + */ + /** + * A `closePopup` event. Fired when Popup should be hidden, for example + * when clicking on an annotation again. + * + * @type {Function} + * @apioption navigation.events.closePopup + */ + /** + * Event fired on a button click. + * + * @type {Function} + * @sample highcharts/annotations/gui/ + * Change icon in a dropddown on event + * @sample highcharts/annotations/gui-buttons/ + * Change button class on event + * @apioption navigation.events.selectButton + */ + /** + * Event fired when button state should change, for example after + * adding an annotation. + * + * @type {Function} + * @sample highcharts/annotations/gui/ + * Change icon in a dropddown on event + * @sample highcharts/annotations/gui-buttons/ + * Change button class on event + * @apioption navigation.events.deselectButton + */ + /** + * Events to communicate between Stock Tools and custom GUI. + * + * @since 7.0.0 + * @product highcharts highstock + * @optionparent navigation.events + */ + events: {}, + /** + * Additional options to be merged into all annotations. + * + * @sample stock/stocktools/navigation-annotation-options + * Set red color of all line annotations + * + * @type {Highcharts.AnnotationsOptions} + * @extends annotations + * @exclude crookedLine, elliottWave, fibonacci, infinityLine, + * measure, pitchfork, tunnel, verticalLine, basicAnnotation + * @apioption navigation.annotationsOptions + */ + annotationsOptions: { + animation: { + defer: 0 + } + } + } + }); + + return NavigationBindings; + }); + _registerModule(_modules, 'Extensions/Annotations/Popup.js', [_modules['Core/Globals.js'], _modules['Extensions/Annotations/NavigationBindings.js'], _modules['Core/Pointer.js'], _modules['Core/Utilities.js']], function (H, NavigationBindings, Pointer, U) { + /* * + * + * Popup generator for Stock tools + * + * (c) 2009-2017 Sebastian Bochan + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + createElement = U.createElement, + defined = U.defined, + getOptions = U.getOptions, + isArray = U.isArray, + isObject = U.isObject, + isString = U.isString, + objectEach = U.objectEach, + pick = U.pick, + wrap = U.wrap; + var indexFilter = /\d/g, PREFIX = 'highcharts-', DIV = 'div', INPUT = 'input', LABEL = 'label', BUTTON = 'button', SELECT = 'select', OPTION = 'option', SPAN = 'span', UL = 'ul', LI = 'li', H3 = 'h3'; + /* eslint-disable no-invalid-this, valid-jsdoc */ + // onContainerMouseDown blocks internal popup events, due to e.preventDefault. + // Related issue #4606 + wrap(Pointer.prototype, 'onContainerMouseDown', function (proceed, e) { + var popupClass = e.target && e.target.className; + // elements is not in popup + if (!(isString(popupClass) && + popupClass.indexOf(PREFIX + 'popup-field') >= 0)) { + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + } + }); + H.Popup = function (parentDiv, iconsURL) { + this.init(parentDiv, iconsURL); + }; + H.Popup.prototype = { + /** + * Initialize the popup. Create base div and add close button. + * @private + * @param {Highcharts.HTMLDOMElement} parentDiv + * Container where popup should be placed + * @param {string} iconsURL + * Icon URL + */ + init: function (parentDiv, iconsURL) { + // create popup div + this.container = createElement(DIV, { + className: PREFIX + 'popup' + }, null, parentDiv); + this.lang = this.getLangpack(); + this.iconsURL = iconsURL; + // add close button + this.addCloseBtn(); + }, + /** + * Create HTML element and attach click event (close popup). + * @private + */ + addCloseBtn: function () { + var _self = this, + closeBtn; + // create close popup btn + closeBtn = createElement(DIV, { + className: PREFIX + 'popup-close' + }, null, this.container); + closeBtn.style['background-image'] = 'url(' + + this.iconsURL + 'close.svg)'; + ['click', 'touchstart'].forEach(function (eventName) { + addEvent(closeBtn, eventName, function () { + _self.closePopup(); + }); + }); + }, + /** + * Create two columns (divs) in HTML. + * @private + * @param {Highcharts.HTMLDOMElement} container + * Container of columns + * @return {Highcharts.Dictionary} + * Reference to two HTML columns (lhsCol, rhsCol) + */ + addColsContainer: function (container) { + var rhsCol, + lhsCol; + // left column + lhsCol = createElement(DIV, { + className: PREFIX + 'popup-lhs-col' + }, null, container); + // right column + rhsCol = createElement(DIV, { + className: PREFIX + 'popup-rhs-col' + }, null, container); + // wrapper content + createElement(DIV, { + className: PREFIX + 'popup-rhs-col-wrapper' + }, null, rhsCol); + return { + lhsCol: lhsCol, + rhsCol: rhsCol + }; + }, + /** + * Create input with label. + * @private + * @param {string} option + * Chain of fields i.e params.styles.fontSize + * @param {string} type + * Indicator type + * @param {Highhcharts.HTMLDOMElement} + * Container where elements should be added + * @param {string} value + * Default value of input i.e period value is 14, extracted from + * defaultOptions (ADD mode) or series options (EDIT mode) + */ + addInput: function (option, type, parentDiv, value) { + var optionParamList = option.split('.'), optionName = optionParamList[optionParamList.length - 1], lang = this.lang, inputName = PREFIX + type + '-' + optionName; + if (!inputName.match(indexFilter)) { + // add label + createElement(LABEL, { + innerHTML: lang[optionName] || optionName, + htmlFor: inputName + }, null, parentDiv); + } + // add input + createElement(INPUT, { + name: inputName, + value: value[0], + type: value[1], + className: PREFIX + 'popup-field' + }, null, parentDiv).setAttribute(PREFIX + 'data-name', option); + }, + /** + * Create button. + * @private + * @param {Highcharts.HTMLDOMElement} parentDiv + * Container where elements should be added + * @param {string} label + * Text placed as button label + * @param {string} type + * add | edit | remove + * @param {Function} callback + * On click callback + * @param {Highcharts.HTMLDOMElement} fieldsDiv + * Container where inputs are generated + * @return {Highcharts.HTMLDOMElement} + * HTML button + */ + addButton: function (parentDiv, label, type, callback, fieldsDiv) { + var _self = this, + closePopup = this.closePopup, + getFields = this.getFields, + button; + button = createElement(BUTTON, { + innerHTML: label + }, null, parentDiv); + ['click', 'touchstart'].forEach(function (eventName) { + addEvent(button, eventName, function () { + closePopup.call(_self); + return callback(getFields(fieldsDiv, type)); + }); + }); + return button; + }, + /** + * Get values from all inputs and create JSON. + * @private + * @param {Highcharts.HTMLDOMElement} - container where inputs are created + * @param {string} - add | edit | remove + * @return {Highcharts.PopupFieldsObject} - fields + */ + getFields: function (parentDiv, type) { + var inputList = parentDiv.querySelectorAll('input'), optionSeries = '#' + PREFIX + 'select-series > option:checked', optionVolume = '#' + PREFIX + 'select-volume > option:checked', linkedTo = parentDiv.querySelectorAll(optionSeries)[0], volumeTo = parentDiv.querySelectorAll(optionVolume)[0], seriesId, param, fieldsOutput; + fieldsOutput = { + actionType: type, + linkedTo: linkedTo && linkedTo.getAttribute('value'), + fields: {} + }; + [].forEach.call(inputList, function (input) { + param = input.getAttribute(PREFIX + 'data-name'); + seriesId = input.getAttribute(PREFIX + 'data-series-id'); + // params + if (seriesId) { + fieldsOutput.seriesId = input.value; + } + else if (param) { + fieldsOutput.fields[param] = input.value; + } + else { + // type like sma / ema + fieldsOutput.type = input.value; + } + }); + if (volumeTo) { + fieldsOutput.fields['params.volumeSeriesID'] = volumeTo.getAttribute('value'); + } + return fieldsOutput; + }, + /** + * Reset content of the current popup and show. + * @private + */ + showPopup: function () { + var popupDiv = this.container, + toolbarClass = PREFIX + 'annotation-toolbar', + popupCloseBtn = popupDiv + .querySelectorAll('.' + PREFIX + 'popup-close')[0]; + // reset content + popupDiv.innerHTML = ''; + // reset toolbar styles if exists + if (popupDiv.className.indexOf(toolbarClass) >= 0) { + popupDiv.classList.remove(toolbarClass); + // reset toolbar inline styles + popupDiv.removeAttribute('style'); + } + // add close button + popupDiv.appendChild(popupCloseBtn); + popupDiv.style.display = 'block'; + }, + /** + * Hide popup. + * @private + */ + closePopup: function () { + this.popup.container.style.display = 'none'; + }, + /** + * Create content and show popup. + * @private + * @param {string} - type of popup i.e indicators + * @param {Highcharts.Chart} - chart + * @param {Highcharts.AnnotationsOptions} - options + * @param {Function} - on click callback + */ + showForm: function (type, chart, options, callback) { + this.popup = chart.navigationBindings.popup; + // show blank popup + this.showPopup(); + // indicator form + if (type === 'indicators') { + this.indicators.addForm.call(this, chart, options, callback); + } + // annotation small toolbar + if (type === 'annotation-toolbar') { + this.annotations.addToolbar.call(this, chart, options, callback); + } + // annotation edit form + if (type === 'annotation-edit') { + this.annotations.addForm.call(this, chart, options, callback); + } + // flags form - add / edit + if (type === 'flag') { + this.annotations.addForm.call(this, chart, options, callback, true); + } + }, + /** + * Return lang definitions for popup. + * @private + * @return {Highcharts.Dictionary} - elements translations. + */ + getLangpack: function () { + return getOptions().lang.navigation.popup; + }, + annotations: { + /** + * Create annotation simple form. It contains two buttons + * (edit / remove) and text label. + * @private + * @param {Highcharts.Chart} - chart + * @param {Highcharts.AnnotationsOptions} - options + * @param {Function} - on click callback + */ + addToolbar: function (chart, options, callback) { + var _self = this, + lang = this.lang, + popupDiv = this.popup.container, + showForm = this.showForm, + toolbarClass = PREFIX + 'annotation-toolbar', + button; + // set small size + if (popupDiv.className.indexOf(toolbarClass) === -1) { + popupDiv.className += ' ' + toolbarClass; + } + // set position + popupDiv.style.top = chart.plotTop + 10 + 'px'; + // create label + createElement(SPAN, { + innerHTML: pick( + // Advanced annotations: + lang[options.langKey] || options.langKey, + // Basic shapes: + options.shapes && options.shapes[0].type) + }, null, popupDiv); + // add buttons + button = this.addButton(popupDiv, lang.removeButton || 'remove', 'remove', callback, popupDiv); + button.className += ' ' + PREFIX + 'annotation-remove-button'; + button.style['background-image'] = 'url(' + + this.iconsURL + 'destroy.svg)'; + button = this.addButton(popupDiv, lang.editButton || 'edit', 'edit', function () { + showForm.call(_self, 'annotation-edit', chart, options, callback); + }, popupDiv); + button.className += ' ' + PREFIX + 'annotation-edit-button'; + button.style['background-image'] = 'url(' + + this.iconsURL + 'edit.svg)'; + }, + /** + * Create annotation simple form. + * It contains fields with param names. + * @private + * @param {Highcharts.Chart} chart + * Chart + * @param {Object} options + * Options + * @param {Function} callback + * On click callback + * @param {boolean} [isInit] + * If it is a form declared for init annotation + */ + addForm: function (chart, options, callback, isInit) { + var popupDiv = this.popup.container, + lang = this.lang, + bottomRow, + lhsCol; + // create title of annotations + lhsCol = createElement('h2', { + innerHTML: lang[options.langKey] || options.langKey, + className: PREFIX + 'popup-main-title' + }, null, popupDiv); + // left column + lhsCol = createElement(DIV, { + className: PREFIX + 'popup-lhs-col ' + PREFIX + 'popup-lhs-full' + }, null, popupDiv); + bottomRow = createElement(DIV, { + className: PREFIX + 'popup-bottom-row' + }, null, popupDiv); + this.annotations.addFormFields.call(this, lhsCol, chart, '', options, [], true); + this.addButton(bottomRow, isInit ? + (lang.addButton || 'add') : + (lang.saveButton || 'save'), isInit ? 'add' : 'save', callback, popupDiv); + }, + /** + * Create annotation's form fields. + * @private + * @param {Highcharts.HTMLDOMElement} parentDiv + * Div where inputs are placed + * @param {Highcharts.Chart} chart + * Chart + * @param {string} parentNode + * Name of parent to create chain of names + * @param {Highcharts.AnnotationsOptions} options + * Options + * @param {Array} storage + * Array where all items are stored + * @param {boolean} [isRoot] + * Recursive flag for root + */ + addFormFields: function (parentDiv, chart, parentNode, options, storage, isRoot) { + var _self = this, + addFormFields = this.annotations.addFormFields, + addInput = this.addInput, + lang = this.lang, + parentFullName, + titleName; + objectEach(options, function (value, option) { + // create name like params.styles.fontSize + parentFullName = parentNode !== '' ? + parentNode + '.' + option : option; + if (isObject(value)) { + if ( + // value is object of options + !isArray(value) || + // array of objects with params. i.e labels in Fibonacci + (isArray(value) && isObject(value[0]))) { + titleName = lang[option] || option; + if (!titleName.match(indexFilter)) { + storage.push([ + true, + titleName, + parentDiv + ]); + } + addFormFields.call(_self, parentDiv, chart, parentFullName, value, storage, false); + } + else { + storage.push([ + _self, + parentFullName, + 'annotation', + parentDiv, + value + ]); + } + } + }); + if (isRoot) { + storage = storage.sort(function (a) { + return a[1].match(/format/g) ? -1 : 1; + }); + storage.forEach(function (genInput) { + if (genInput[0] === true) { + createElement(SPAN, { + className: PREFIX + 'annotation-title', + innerHTML: genInput[1] + }, null, genInput[2]); + } + else { + addInput.apply(genInput[0], genInput.splice(1)); + } + }); + } + } + }, + indicators: { + /** + * Create indicator's form. It contains two tabs (ADD and EDIT) with + * content. + * @private + */ + addForm: function (chart, _options, callback) { + var tabsContainers, + indicators = this.indicators, + lang = this.lang, + buttonParentDiv; + // add tabs + this.tabs.init.call(this, chart); + // get all tabs content divs + tabsContainers = this.popup.container + .querySelectorAll('.' + PREFIX + 'tab-item-content'); + // ADD tab + this.addColsContainer(tabsContainers[0]); + indicators.addIndicatorList.call(this, chart, tabsContainers[0], 'add'); + buttonParentDiv = tabsContainers[0] + .querySelectorAll('.' + PREFIX + 'popup-rhs-col')[0]; + this.addButton(buttonParentDiv, lang.addButton || 'add', 'add', callback, buttonParentDiv); + // EDIT tab + this.addColsContainer(tabsContainers[1]); + indicators.addIndicatorList.call(this, chart, tabsContainers[1], 'edit'); + buttonParentDiv = tabsContainers[1] + .querySelectorAll('.' + PREFIX + 'popup-rhs-col')[0]; + this.addButton(buttonParentDiv, lang.saveButton || 'save', 'edit', callback, buttonParentDiv); + this.addButton(buttonParentDiv, lang.removeButton || 'remove', 'remove', callback, buttonParentDiv); + }, + /** + * Create HTML list of all indicators (ADD mode) or added indicators + * (EDIT mode). + * @private + */ + addIndicatorList: function (chart, parentDiv, listType) { + var _self = this, lhsCol = parentDiv.querySelectorAll('.' + PREFIX + 'popup-lhs-col')[0], rhsCol = parentDiv.querySelectorAll('.' + PREFIX + 'popup-rhs-col')[0], isEdit = listType === 'edit', series = (isEdit ? + chart.series : // EDIT mode + chart.options.plotOptions // ADD mode + ), addFormFields = this.indicators.addFormFields, rhsColWrapper, indicatorList, item; + // create wrapper for list + indicatorList = createElement(UL, { + className: PREFIX + 'indicator-list' + }, null, lhsCol); + rhsColWrapper = rhsCol + .querySelectorAll('.' + PREFIX + 'popup-rhs-col-wrapper')[0]; + objectEach(series, function (serie, value) { + var seriesOptions = serie.options; + if (serie.params || + seriesOptions && seriesOptions.params) { + var indicatorNameType = _self.indicators.getNameType(serie, + value), + indicatorType = indicatorNameType.type; + item = createElement(LI, { + className: PREFIX + 'indicator-list', + innerHTML: indicatorNameType.name + }, null, indicatorList); + ['click', 'touchstart'].forEach(function (eventName) { + addEvent(item, eventName, function () { + addFormFields.call(_self, chart, isEdit ? serie : series[indicatorType], indicatorNameType.type, rhsColWrapper); + // add hidden input with series.id + if (isEdit && serie.options) { + createElement(INPUT, { + type: 'hidden', + name: PREFIX + 'id-' + indicatorType, + value: serie.options.id + }, null, rhsColWrapper) + .setAttribute(PREFIX + 'data-series-id', serie.options.id); + } + }); + }); + } + }); + // select first item from the list + if (indicatorList.childNodes.length > 0) { + indicatorList.childNodes[0].click(); + } + }, + /** + * Extract full name and type of requested indicator. + * @private + * @param {Highcharts.Series} series + * Series which name is needed. (EDIT mode - defaultOptions.series, ADD + * mode - indicator series). + * @param {string} - indicator type like: sma, ema, etc. + * @return {Object} - series name and type like: sma, ema, etc. + */ + getNameType: function (series, type) { + var options = series.options, + seriesTypes = H.seriesTypes, + // add mode + seriesName = seriesTypes[type] && + seriesTypes[type].prototype.nameBase || type.toUpperCase(), + seriesType = type; + // edit + if (options && options.type) { + seriesType = series.options.type; + seriesName = series.name; + } + return { + name: seriesName, + type: seriesType + }; + }, + /** + * List all series with unique ID. Its mandatory for indicators to set + * correct linking. + * @private + * @param {string} type + * Indicator type like: sma, ema, etc. + * @param {string} optionName + * Type of select i.e series or volume. + * @param {Highcharts.Chart} chart + * Chart + * @param {Highcharts.HTMLDOMElement} parentDiv + * Element where created HTML list is added + * @param {string} selectedOption + * optional param for default value in dropdown + */ + listAllSeries: function (type, optionName, chart, parentDiv, selectedOption) { + var selectName = PREFIX + optionName + '-type-' + type, + lang = this.lang, + selectBox, + seriesOptions; + createElement(LABEL, { + innerHTML: lang[optionName] || optionName, + htmlFor: selectName + }, null, parentDiv); + // select type + selectBox = createElement(SELECT, { + name: selectName, + className: PREFIX + 'popup-field' + }, null, parentDiv); + selectBox.setAttribute('id', PREFIX + 'select-' + optionName); + // list all series which have id - mandatory for creating indicator + chart.series.forEach(function (serie) { + seriesOptions = serie.options; + if (!seriesOptions.params && + seriesOptions.id && + seriesOptions.id !== PREFIX + 'navigator-series') { + createElement(OPTION, { + innerHTML: seriesOptions.name || seriesOptions.id, + value: seriesOptions.id + }, null, selectBox); + } + }); + if (defined(selectedOption)) { + selectBox.value = selectedOption; + } + }, + /** + * Create typical inputs for chosen indicator. Fields are extracted from + * defaultOptions (ADD mode) or current indicator (ADD mode). Two extra + * fields are added: + * - hidden input - contains indicator type (required for callback) + * - select - list of series which can be linked with indicator + * @private + * @param {Highcharts.Chart} chart + * Chart + * @param {Highcharts.Series} series + * Indicator + * @param {string} seriesType + * Indicator type like: sma, ema, etc. + * @param {Highcharts.HTMLDOMElement} rhsColWrapper + * Element where created HTML list is added + */ + addFormFields: function (chart, series, seriesType, rhsColWrapper) { + var fields = series.params || series.options.params, + getNameType = this.indicators.getNameType; + // reset current content + rhsColWrapper.innerHTML = ''; + // create title (indicator name in the right column) + createElement(H3, { + className: PREFIX + 'indicator-title', + innerHTML: getNameType(series, seriesType).name + }, null, rhsColWrapper); + // input type + createElement(INPUT, { + type: 'hidden', + name: PREFIX + 'type-' + seriesType, + value: seriesType + }, null, rhsColWrapper); + // list all series with id + this.indicators.listAllSeries.call(this, seriesType, 'series', chart, rhsColWrapper, series.linkedParent && fields.volumeSeriesID); + if (fields.volumeSeriesID) { + this.indicators.listAllSeries.call(this, seriesType, 'volume', chart, rhsColWrapper, series.linkedParent && series.linkedParent.options.id); + } + // add param fields + this.indicators.addParamInputs.call(this, chart, 'params', fields, seriesType, rhsColWrapper); + }, + /** + * Recurent function which lists all fields, from params object and + * create them as inputs. Each input has unique `data-name` attribute, + * which keeps chain of fields i.e params.styles.fontSize. + * @private + * @param {Highcharts.Chart} chart + * Chart + * @param {string} parentNode + * Name of parent to create chain of names + * @param {Highcharts.PopupFieldsDictionary} fields + * Params which are based for input create + * @param {string} type + * Indicator type like: sma, ema, etc. + * @param {Highcharts.HTMLDOMElement} parentDiv + * Element where created HTML list is added + */ + addParamInputs: function (chart, parentNode, fields, type, parentDiv) { + var _self = this, + addParamInputs = this.indicators.addParamInputs, + addInput = this.addInput, + parentFullName; + objectEach(fields, function (value, fieldName) { + // create name like params.styles.fontSize + parentFullName = parentNode + '.' + fieldName; + if (isObject(value)) { + addParamInputs.call(_self, chart, parentFullName, value, type, parentDiv); + } + else if ( + // skip volume field which is created by addFormFields + parentFullName !== 'params.volumeSeriesID') { + addInput.call(_self, parentFullName, type, parentDiv, [value, 'text'] // all inputs are text type + ); + } + }); + }, + /** + * Get amount of indicators added to chart. + * @private + * @return {number} - Amount of indicators + */ + getAmount: function () { + var series = this.series, + counter = 0; + series.forEach(function (serie) { + var seriesOptions = serie.options; + if (serie.params || + seriesOptions && seriesOptions.params) { + counter++; + } + }); + return counter; + } + }, + tabs: { + /** + * Init tabs. Create tab menu items, tabs containers + * @private + * @param {Highcharts.Chart} chart + * Reference to current chart + */ + init: function (chart) { + var tabs = this.tabs, + indicatorsCount = this.indicators.getAmount.call(chart), + firstTab; // run by default + // create menu items + firstTab = tabs.addMenuItem.call(this, 'add'); + tabs.addMenuItem.call(this, 'edit', indicatorsCount); + // create tabs containers + tabs.addContentItem.call(this, 'add'); + tabs.addContentItem.call(this, 'edit'); + tabs.switchTabs.call(this, indicatorsCount); + // activate first tab + tabs.selectTab.call(this, firstTab, 0); + }, + /** + * Create tab menu item + * @private + * @param {string} tabName + * `add` or `edit` + * @param {number} [disableTab] + * Disable tab when 0 + * @return {Highcharts.HTMLDOMElement} + * Created HTML tab-menu element + */ + addMenuItem: function (tabName, disableTab) { + var popupDiv = this.popup.container, + className = PREFIX + 'tab-item', + lang = this.lang, + menuItem; + if (disableTab === 0) { + className += ' ' + PREFIX + 'tab-disabled'; + } + // tab 1 + menuItem = createElement(SPAN, { + innerHTML: lang[tabName + 'Button'] || tabName, + className: className + }, null, popupDiv); + menuItem.setAttribute(PREFIX + 'data-tab-type', tabName); + return menuItem; + }, + /** + * Create tab content + * @private + * @return {HTMLDOMElement} - created HTML tab-content element + */ + addContentItem: function () { + var popupDiv = this.popup.container; + return createElement(DIV, { + className: PREFIX + 'tab-item-content' + }, null, popupDiv); + }, + /** + * Add click event to each tab + * @private + * @param {number} disableTab + * Disable tab when 0 + */ + switchTabs: function (disableTab) { + var _self = this, + popupDiv = this.popup.container, + tabs = popupDiv.querySelectorAll('.' + PREFIX + 'tab-item'), + dataParam; + tabs.forEach(function (tab, i) { + dataParam = tab.getAttribute(PREFIX + 'data-tab-type'); + if (dataParam === 'edit' && disableTab === 0) { + return; + } + ['click', 'touchstart'].forEach(function (eventName) { + addEvent(tab, eventName, function () { + // reset class on other elements + _self.tabs.deselectAll.call(_self); + _self.tabs.selectTab.call(_self, this, i); + }); + }); + }); + }, + /** + * Set tab as visible + * @private + * @param {globals.Element} - current tab + * @param {number} - Index of tab in menu + */ + selectTab: function (tab, index) { + var allTabs = this.popup.container + .querySelectorAll('.' + PREFIX + 'tab-item-content'); + tab.className += ' ' + PREFIX + 'tab-item-active'; + allTabs[index].className += ' ' + PREFIX + 'tab-item-show'; + }, + /** + * Set all tabs as invisible. + * @private + */ + deselectAll: function () { + var popupDiv = this.popup.container, + tabs = popupDiv + .querySelectorAll('.' + PREFIX + 'tab-item'), + tabsContent = popupDiv + .querySelectorAll('.' + PREFIX + 'tab-item-content'), + i; + for (i = 0; i < tabs.length; i++) { + tabs[i].classList.remove(PREFIX + 'tab-item-active'); + tabsContent[i].classList.remove(PREFIX + 'tab-item-show'); + } + } + } + }; + addEvent(NavigationBindings, 'showPopup', function (config) { + if (!this.popup) { + // Add popup to main container + this.popup = new H.Popup(this.chart.container, (this.chart.options.navigation.iconsURL || + (this.chart.options.stockTools && + this.chart.options.stockTools.gui.iconsURL) || + 'https://code.highcharts.com/8.2.0/gfx/stock-icons/')); + } + this.popup.showForm(config.formType, this.chart, config.options, config.onSubmit); + }); + addEvent(NavigationBindings, 'closePopup', function () { + if (this.popup) { + this.popup.closePopup(); + } + }); + + }); + _registerModule(_modules, 'masters/modules/annotations.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/arrow-symbols.js b/highcharts/modules/arrow-symbols.js new file mode 100644 index 0000000..17fa23a --- /dev/null +++ b/highcharts/modules/arrow-symbols.js @@ -0,0 +1,13 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Arrow Symbols + + (c) 2017-2019 Lars A. V. Cabrera + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/arrow-symbols",["highcharts"],function(f){a(f);a.Highcharts=f;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function f(a,e,b,c){a.hasOwnProperty(e)||(a[e]=c.apply(null,b))}a=a?a._modules:{};f(a,"Extensions/ArrowSymbols.js",[a["Core/Renderer/SVG/SVGRenderer.js"]],function(a){a.prototype.symbols.arrow=function(a,b,c, +d){return[["M",a,b+d/2],["L",a+c,b],["L",a,b+d/2],["L",a+c,b+d]]};a.prototype.symbols["arrow-half"]=function(e,b,c,d){return a.prototype.symbols.arrow(e,b,c/2,d)};a.prototype.symbols["triangle-left"]=function(a,b,c,d){return[["M",a+c,b],["L",a,b+d/2],["L",a+c,b+d],["Z"]]};a.prototype.symbols["arrow-filled"]=a.prototype.symbols["triangle-left"];a.prototype.symbols["triangle-left-half"]=function(e,b,c,d){return a.prototype.symbols["triangle-left"](e,b,c/2,d)};a.prototype.symbols["arrow-filled-half"]= +a.prototype.symbols["triangle-left-half"]});f(a,"masters/modules/arrow-symbols.src.js",[],function(){})}); +//# sourceMappingURL=arrow-symbols.js.map \ No newline at end of file diff --git a/highcharts/modules/arrow-symbols.js.map b/highcharts/modules/arrow-symbols.js.map new file mode 100644 index 0000000..01b7bbe --- /dev/null +++ b/highcharts/modules/arrow-symbols.js.map @@ -0,0 +1 @@ +{"version":3,"file":"arrow-symbols.js.map","lineCount":12,"mappings":"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","sources":["arrow-symbols.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","SVGRenderer","prototype","symbols","arrow","SVGRenderer.prototype.symbols.arrow","x","y","w","h"]} \ No newline at end of file diff --git a/highcharts/modules/arrow-symbols.src.js b/highcharts/modules/arrow-symbols.src.js new file mode 100644 index 0000000..611b012 --- /dev/null +++ b/highcharts/modules/arrow-symbols.src.js @@ -0,0 +1,228 @@ +/** + * @license Highcharts JS v8.2.0 (2020-08-20) + * + * Arrow Symbols + * + * (c) 2017-2019 Lars A. V. Cabrera + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/arrow-symbols', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'Extensions/ArrowSymbols.js', [_modules['Core/Renderer/SVG/SVGRenderer.js']], function (SVGRenderer) { + /* * + * + * (c) 2017 Highsoft AS + * Authors: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Creates an arrow symbol. Like a triangle, except not filled. + * ``` + * o + * o + * o + * o + * o + * o + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + SVGRenderer.prototype.symbols.arrow = function (x, y, w, h) { + return [ + ['M', x, y + h / 2], + ['L', x + w, y], + ['L', x, y + h / 2], + ['L', x + w, y + h] + ]; + }; + /** + * Creates a half-width arrow symbol. Like a triangle, except not filled. + * ``` + * o + * o + * o + * o + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + SVGRenderer.prototype.symbols['arrow-half'] = function (x, y, w, h) { + return SVGRenderer.prototype.symbols.arrow(x, y, w / 2, h); + }; + /** + * Creates a left-oriented triangle. + * ``` + * o + * ooooooo + * ooooooooooooo + * ooooooo + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the triangle + * + * @param {number} y + * y position of the triangle + * + * @param {number} w + * width of the triangle + * + * @param {number} h + * height of the triangle + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + SVGRenderer.prototype.symbols['triangle-left'] = function (x, y, w, h) { + return [ + ['M', x + w, y], + ['L', x, y + h / 2], + ['L', x + w, y + h], + ['Z'] + ]; + }; + /** + * Alias function for triangle-left. + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + SVGRenderer.prototype.symbols['arrow-filled'] = SVGRenderer.prototype.symbols['triangle-left']; + /** + * Creates a half-width, left-oriented triangle. + * ``` + * o + * oooo + * ooooooo + * oooo + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the triangle + * + * @param {number} y + * y position of the triangle + * + * @param {number} w + * width of the triangle + * + * @param {number} h + * height of the triangle + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + SVGRenderer.prototype.symbols['triangle-left-half'] = function (x, y, w, h) { + return SVGRenderer.prototype.symbols['triangle-left'](x, y, w / 2, h); + }; + /** + * Alias function for triangle-left-half. + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + SVGRenderer.prototype.symbols['arrow-filled-half'] = SVGRenderer.prototype.symbols['triangle-left-half']; + + }); + _registerModule(_modules, 'masters/modules/arrow-symbols.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/boost-canvas.js b/highcharts/modules/boost-canvas.js new file mode 100644 index 0000000..e6c07fe --- /dev/null +++ b/highcharts/modules/boost-canvas.js @@ -0,0 +1,25 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Boost module + + (c) 2010-2019 Highsoft AS + Author: Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(f){"object"===typeof module&&module.exports?(f["default"]=f,module.exports=f):"function"===typeof define&&define.amd?define("highcharts/modules/boost-canvas",["highcharts"],function(q){f(q);f.Highcharts=q;return f}):f("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(f){function q(f,r,q,m){f.hasOwnProperty(r)||(f[r]=m.apply(null,q))}f=f?f._modules:{};q(f,"Extensions/BoostCanvas.js",[f["Core/Chart/Chart.js"],f["Core/Globals.js"],f["Core/Color.js"],f["Core/Utilities.js"]],function(f, +r,q,m){var ba=q.parse,z=m.addEvent,x=m.extend,ca=m.fireEvent,da=m.isNumber,ea=m.merge,fa=m.pick,w=m.wrap,A=r.win.document,ha=function(){},B=r.Series,n=r.seriesTypes,L;r.initCanvasBoost=function(){r.seriesTypes.heatmap&&w(r.seriesTypes.heatmap.prototype,"drawPoints",function(){var a=this.chart,b=this.getContext(),e=this.chart.inverted,f=this.xAxis,c=this.yAxis;b?(this.points.forEach(function(d){var g=d.plotY;"undefined"===typeof g||isNaN(g)||null===d.y||(g=d.shapeArgs,d=a.styledMode?d.series.colorAttribs(d): +d.series.pointAttribs(d),b.fillStyle=d.fill,e?b.fillRect(c.len-g.y+f.left,f.len-g.x+c.top,-g.height,-g.width):b.fillRect(g.x+f.left,g.y+c.top,g.width,g.height))}),this.canvasToSVG()):this.chart.showLoading("Your browser doesn't support HTML5 canvas,
    please use a modern browser")});x(B.prototype,{getContext:function(){var a=this.chart,b=a.chartWidth,e=a.chartHeight,d=a.seriesGroup||this.group,c=this,f=function(a,c,e,b,f,d,g){a.call(this,e,c,b,f,d,g)};a.isChartSeriesBoosting()&&(c=a,d=a.seriesGroup); +var g=c.ctx;c.canvas||(c.canvas=A.createElement("canvas"),c.renderTarget=a.renderer.image("",0,0,b,e).addClass("highcharts-boost-canvas").add(d),c.ctx=g=c.canvas.getContext("2d"),a.inverted&&["moveTo","lineTo","rect","arc"].forEach(function(a){w(g,a,f)}),c.boostCopy=function(){c.renderTarget.attr({href:c.canvas.toDataURL("image/png")})},c.boostClear=function(){g.clearRect(0,0,c.canvas.width,c.canvas.height);c===this&&c.renderTarget.attr({href:""})},c.boostClipRect=a.renderer.clipRect(),c.renderTarget.clip(c.boostClipRect)); +c.canvas.width!==b&&(c.canvas.width=b);c.canvas.height!==e&&(c.canvas.height=e);c.renderTarget.attr({x:0,y:0,width:b,height:e,style:"pointer-events: none",href:""});c.boostClipRect.attr(a.getBoostClipRect(c));return g},canvasToSVG:function(){this.chart.isChartSeriesBoosting()?this.boostClear&&this.boostClear():(this.boostCopy||this.chart.boostCopy)&&(this.boostCopy||this.chart.boostCopy)()},cvsLineTo:function(a,b,e){a.lineTo(b,e)},renderCanvas:function(){var a=this,b=a.options,e=a.chart,f=this.xAxis, +c=this.yAxis,n=(e.options.boost||{}).timeRendering||!1,g=0,w=a.processedXData,A=a.processedYData,M=b.data,k=f.getExtremes(),C=k.min,D=k.max;k=c.getExtremes();var B=k.min,ia=k.max,N={},E,ja=!!a.sampling,F=b.marker&&b.marker.radius,O=this.cvsDrawPoint,G=b.lineWidth?this.cvsLineTo:void 0,P=F&&1>=F?this.cvsMarkerSquare:this.cvsMarkerCircle,ka=this.cvsStrokeBatch||1E3,la=!1!==b.enableMouseTracking,Q;k=b.threshold;var u=c.getThreshold(k),R=da(k),S=u,ma=this.fill,T=a.pointArrayMap&&"low,high"===a.pointArrayMap.join(","), +U=!!b.stacking,V=a.cropStart||0;k=e.options.loading;var na=a.requireSorting,W,oa=b.connectNulls,X=!w,H,I,v,y,J,t=U?a.data:w||M,pa=a.fillOpacity?(new q(a.color)).setOpacity(fa(b.fillOpacity,.75)).get():a.color,Y=function(){ma?(l.fillStyle=pa,l.fill()):(l.strokeStyle=a.color,l.lineWidth=b.lineWidth,l.stroke())},Z=function(c,b,f,d){0===g&&(l.beginPath(),G&&(l.lineJoin="round"));e.scroller&&"highcharts-navigator-series"===a.options.className?(b+=e.scroller.top,f&&(f+=e.scroller.top)):b+=e.plotTop;c+= +e.plotLeft;W?l.moveTo(c,b):O?O(l,c,b,f,Q):G?G(l,c,b):P&&P.call(a,l,c,b,F,d);g+=1;g===ka&&(Y(),g=0);Q={clientX:c,plotY:b,yBottom:f}},qa="x"===b.findNearestPointBy,aa=this.xData||this.options.xData||this.processedXData||!1,K=function(a,b,d){J=qa?a:a+","+b;la&&!N[J]&&(N[J]=!0,e.inverted&&(a=f.len-a,b=c.len-b),ra.push({x:aa?aa[V+d]:!1,clientX:a,plotX:a,plotY:b,i:V+d}))};this.renderTarget&&this.renderTarget.attr({href:""});(this.points||this.graph)&&this.destroyGraphics();a.plotGroup("group","series", +a.visible?"visible":"hidden",b.zIndex,e.seriesGroup);a.markerGroup=a.group;z(a,"destroy",function(){a.markerGroup=null});var ra=this.points=[];var l=this.getContext();a.buildKDTree=ha;this.boostClear&&this.boostClear();this.visible&&(99999=C&&k<=D&&(g=!0);l&&l>=C&&l<=D&&(n=!0);if(T){X&&(h=b.slice(1,3));var m=h[0];h=h[1]}else U&&(p=b.x,h=b.stackY,m=h-b.y);b=null===h;na||(r=h>=B&&h<=ia);if(!b&&(p>=C&&p<=D&&r||g||n))if(p=Math.round(f.toPixels(p,!0)),ja){if("undefined"===typeof v||p===E){T||(m=h);if("undefined"=== +typeof y||h>I)I=h,y=d;if("undefined"===typeof v||m' + + 'please use a modern browser'); + // Uncomment this to provide low-level (slow) support in oldIE. + // It will cause script errors on charts with more than a few + // thousand points. + // arguments[0].call(this); + } + }); + } + extend(Series.prototype, { + /** + * Create a hidden canvas to draw the graph on. The contents is later + * copied over to an SVG image element. + * + * @private + * @function Highcharts.Series#getContext + */ + getContext: function () { + var chart = this.chart, + width = chart.chartWidth, + height = chart.chartHeight, + targetGroup = chart.seriesGroup || this.group, + target = this, + ctx, + swapXY = function (proceed, + x, + y, + a, + b, + c, + d) { + proceed.call(this, + y, + x, + a, + b, + c, + d); + }; + if (chart.isChartSeriesBoosting()) { + target = chart; + targetGroup = chart.seriesGroup; + } + ctx = target.ctx; + if (!target.canvas) { + target.canvas = doc.createElement('canvas'); + target.renderTarget = chart.renderer + .image('', 0, 0, width, height) + .addClass('highcharts-boost-canvas') + .add(targetGroup); + target.ctx = ctx = target.canvas.getContext('2d'); + if (chart.inverted) { + ['moveTo', 'lineTo', 'rect', 'arc'].forEach(function (fn) { + wrap(ctx, fn, swapXY); + }); + } + target.boostCopy = function () { + target.renderTarget.attr({ + href: target.canvas.toDataURL('image/png') + }); + }; + target.boostClear = function () { + ctx.clearRect(0, 0, target.canvas.width, target.canvas.height); + if (target === this) { + target.renderTarget.attr({ href: '' }); + } + }; + target.boostClipRect = chart.renderer.clipRect(); + target.renderTarget.clip(target.boostClipRect); + } + else if (!(target instanceof H.Chart)) { + // ctx.clearRect(0, 0, width, height); + } + if (target.canvas.width !== width) { + target.canvas.width = width; + } + if (target.canvas.height !== height) { + target.canvas.height = height; + } + target.renderTarget.attr({ + x: 0, + y: 0, + width: width, + height: height, + style: 'pointer-events: none', + href: '' + }); + target.boostClipRect.attr(chart.getBoostClipRect(target)); + return ctx; + }, + /** + * Draw the canvas image inside an SVG image + * + * @private + * @function Highcharts.Series#canvasToSVG + */ + canvasToSVG: function () { + if (!this.chart.isChartSeriesBoosting()) { + if (this.boostCopy || this.chart.boostCopy) { + (this.boostCopy || this.chart.boostCopy)(); + } + } + else { + if (this.boostClear) { + this.boostClear(); + } + } + }, + cvsLineTo: function (ctx, clientX, plotY) { + ctx.lineTo(clientX, plotY); + }, + renderCanvas: function () { + var series = this, options = series.options, chart = series.chart, xAxis = this.xAxis, yAxis = this.yAxis, activeBoostSettings = chart.options.boost || {}, boostSettings = { + timeRendering: activeBoostSettings.timeRendering || false, + timeSeriesProcessing: activeBoostSettings.timeSeriesProcessing || false, + timeSetup: activeBoostSettings.timeSetup || false + }, ctx, c = 0, xData = series.processedXData, yData = series.processedYData, rawData = options.data, xExtremes = xAxis.getExtremes(), xMin = xExtremes.min, xMax = xExtremes.max, yExtremes = yAxis.getExtremes(), yMin = yExtremes.min, yMax = yExtremes.max, pointTaken = {}, lastClientX, sampling = !!series.sampling, points, r = options.marker && options.marker.radius, cvsDrawPoint = this.cvsDrawPoint, cvsLineTo = options.lineWidth ? this.cvsLineTo : void 0, cvsMarker = (r && r <= 1 ? + this.cvsMarkerSquare : + this.cvsMarkerCircle), strokeBatch = this.cvsStrokeBatch || 1000, enableMouseTracking = options.enableMouseTracking !== false, lastPoint, threshold = options.threshold, yBottom = yAxis.getThreshold(threshold), hasThreshold = isNumber(threshold), translatedThreshold = yBottom, doFill = this.fill, isRange = (series.pointArrayMap && + series.pointArrayMap.join(',') === 'low,high'), isStacked = !!options.stacking, cropStart = series.cropStart || 0, loadingOptions = chart.options.loading, requireSorting = series.requireSorting, wasNull, connectNulls = options.connectNulls, useRaw = !xData, minVal, maxVal, minI, maxI, index, sdata = (isStacked ? + series.data : + (xData || rawData)), fillColor = (series.fillOpacity ? + new Color(series.color).setOpacity(pick(options.fillOpacity, 0.75)).get() : + series.color), + // + stroke = function () { + if (doFill) { + ctx.fillStyle = fillColor; + ctx.fill(); + } + else { + ctx.strokeStyle = series.color; + ctx.lineWidth = options.lineWidth; + ctx.stroke(); + } + }, + // + drawPoint = function (clientX, plotY, yBottom, i) { + if (c === 0) { + ctx.beginPath(); + if (cvsLineTo) { + ctx.lineJoin = 'round'; + } + } + if (chart.scroller && + series.options.className === + 'highcharts-navigator-series') { + plotY += chart.scroller.top; + if (yBottom) { + yBottom += chart.scroller.top; + } + } + else { + plotY += chart.plotTop; + } + clientX += chart.plotLeft; + if (wasNull) { + ctx.moveTo(clientX, plotY); + } + else { + if (cvsDrawPoint) { + cvsDrawPoint(ctx, clientX, plotY, yBottom, lastPoint); + } + else if (cvsLineTo) { + cvsLineTo(ctx, clientX, plotY); + } + else if (cvsMarker) { + cvsMarker.call(series, ctx, clientX, plotY, r, i); + } + } + // We need to stroke the line for every 1000 pixels. It will + // crash the browser memory use if we stroke too + // infrequently. + c = c + 1; + if (c === strokeBatch) { + stroke(); + c = 0; + } + // Area charts need to keep track of the last point + lastPoint = { + clientX: clientX, + plotY: plotY, + yBottom: yBottom + }; + }, + // + compareX = options.findNearestPointBy === 'x', + // + xDataFull = (this.xData || + this.options.xData || + this.processedXData || + false), + // + addKDPoint = function (clientX, plotY, i) { + // Shaves off about 60ms compared to repeated concatenation + index = compareX ? clientX : clientX + ',' + plotY; + // The k-d tree requires series points. + // Reduce the amount of points, since the time to build the + // tree increases exponentially. + if (enableMouseTracking && !pointTaken[index]) { + pointTaken[index] = true; + if (chart.inverted) { + clientX = xAxis.len - clientX; + plotY = yAxis.len - plotY; + } + points.push({ + x: xDataFull ? + xDataFull[cropStart + i] : + false, + clientX: clientX, + plotX: clientX, + plotY: plotY, + i: cropStart + i + }); + } + }; + if (this.renderTarget) { + this.renderTarget.attr({ 'href': '' }); + } + // If we are zooming out from SVG mode, destroy the graphics + if (this.points || this.graph) { + this.destroyGraphics(); + } + // The group + series.plotGroup('group', 'series', series.visible ? 'visible' : 'hidden', options.zIndex, chart.seriesGroup); + series.markerGroup = series.group; + addEvent(series, 'destroy', function () { + // Prevent destroy twice + series.markerGroup = null; + }); + points = this.points = []; + ctx = this.getContext(); + series.buildKDTree = noop; // Do not start building while drawing + if (this.boostClear) { + this.boostClear(); + } + // if (this.canvas) { + // ctx.clearRect( + // 0, + // 0, + // this.canvas.width, + // this.canvas.height + // ); + // } + if (!this.visible) { + return; + } + // Display a loading indicator + if (rawData.length > 99999) { + chart.options.loading = merge(loadingOptions, { + labelStyle: { + backgroundColor: color('#ffffff').setOpacity(0.75).get(), + padding: '1em', + borderRadius: '0.5em' + }, + style: { + backgroundColor: 'none', + opacity: 1 + } + }); + U.clearTimeout(destroyLoadingDiv); + chart.showLoading('Drawing...'); + chart.options.loading = loadingOptions; // reset + } + if (boostSettings.timeRendering) { + console.time('canvas rendering'); // eslint-disable-line no-console + } + // Loop over the points + H.eachAsync(sdata, function (d, i) { + var x, + y, + clientX, + plotY, + isNull, + low, + isNextInside = false, + isPrevInside = false, + nx = false, + px = false, + chartDestroyed = typeof chart.index === 'undefined', + isYInside = true; + if (!chartDestroyed) { + if (useRaw) { + x = d[0]; + y = d[1]; + if (sdata[i + 1]) { + nx = sdata[i + 1][0]; + } + if (sdata[i - 1]) { + px = sdata[i - 1][0]; + } + } + else { + x = d; + y = yData[i]; + if (sdata[i + 1]) { + nx = sdata[i + 1]; + } + if (sdata[i - 1]) { + px = sdata[i - 1]; + } + } + if (nx && nx >= xMin && nx <= xMax) { + isNextInside = true; + } + if (px && px >= xMin && px <= xMax) { + isPrevInside = true; + } + // Resolve low and high for range series + if (isRange) { + if (useRaw) { + y = d.slice(1, 3); + } + low = y[0]; + y = y[1]; + } + else if (isStacked) { + x = d.x; + y = d.stackY; + low = y - d.y; + } + isNull = y === null; + // Optimize for scatter zooming + if (!requireSorting) { + isYInside = y >= yMin && y <= yMax; + } + if (!isNull && + ((x >= xMin && x <= xMax && isYInside) || + (isNextInside || isPrevInside))) { + clientX = Math.round(xAxis.toPixels(x, true)); + if (sampling) { + if (typeof minI === 'undefined' || + clientX === lastClientX) { + if (!isRange) { + low = y; + } + if (typeof maxI === 'undefined' || y > maxVal) { + maxVal = y; + maxI = i; + } + if (typeof minI === 'undefined' || + low < minVal) { + minVal = low; + minI = i; + } + } + // Add points and reset + if (clientX !== lastClientX) { + // maxI also a number: + if (typeof minI !== 'undefined') { + plotY = yAxis.toPixels(maxVal, true); + yBottom = yAxis.toPixels(minVal, true); + drawPoint(clientX, hasThreshold ? + Math.min(plotY, translatedThreshold) : plotY, hasThreshold ? + Math.max(yBottom, translatedThreshold) : yBottom, i); + addKDPoint(clientX, plotY, maxI); + if (yBottom !== plotY) { + addKDPoint(clientX, yBottom, minI); + } + } + minI = maxI = void 0; + lastClientX = clientX; + } + } + else { + plotY = Math.round(yAxis.toPixels(y, true)); + drawPoint(clientX, plotY, yBottom, i); + addKDPoint(clientX, plotY, i); + } + } + wasNull = isNull && !connectNulls; + if (i % CHUNK_SIZE === 0) { + if (series.boostCopy || series.chart.boostCopy) { + (series.boostCopy || series.chart.boostCopy)(); + } + } + } + return !chartDestroyed; + }, function () { + var loadingDiv = chart.loadingDiv, + loadingShown = chart.loadingShown; + stroke(); + // if (series.boostCopy || series.chart.boostCopy) { + // (series.boostCopy || series.chart.boostCopy)(); + // } + series.canvasToSVG(); + if (boostSettings.timeRendering) { + console.timeEnd('canvas rendering'); // eslint-disable-line no-console + } + fireEvent(series, 'renderedCanvas'); + // Do not use chart.hideLoading, as it runs JS animation and + // will be blocked by buildKDTree. CSS animation looks good, but + // then it must be deleted in timeout. If we add the module to + // core, change hideLoading so we can skip this block. + if (loadingShown) { + extend(loadingDiv.style, { + transition: 'opacity 250ms', + opacity: 0 + }); + chart.loadingShown = false; + destroyLoadingDiv = setTimeout(function () { + if (loadingDiv.parentNode) { // In exporting it is falsy + loadingDiv.parentNode.removeChild(loadingDiv); + } + chart.loadingDiv = chart.loadingSpan = null; + }, 250); + } + // Go back to prototype, ready to build + delete series.buildKDTree; + series.buildKDTree(); + // Don't do async on export, the exportChart, getSVGForExport and + // getSVG methods are not chained for it. + }, chart.renderer.forExport ? Number.MAX_VALUE : void 0); + } + }); + seriesTypes.scatter.prototype.cvsMarkerCircle = function (ctx, clientX, plotY, r) { + ctx.moveTo(clientX, plotY); + ctx.arc(clientX, plotY, r, 0, 2 * Math.PI, false); + }; + // Rect is twice as fast as arc, should be used for small markers + seriesTypes.scatter.prototype.cvsMarkerSquare = function (ctx, clientX, plotY, r) { + ctx.rect(clientX - r, plotY - r, r * 2, r * 2); + }; + seriesTypes.scatter.prototype.fill = true; + if (seriesTypes.bubble) { + seriesTypes.bubble.prototype.cvsMarkerCircle = function (ctx, clientX, plotY, r, i) { + ctx.moveTo(clientX, plotY); + ctx.arc(clientX, plotY, this.radii && this.radii[i], 0, 2 * Math.PI, false); + }; + seriesTypes.bubble.prototype.cvsStrokeBatch = 1; + } + extend(seriesTypes.area.prototype, { + cvsDrawPoint: function (ctx, clientX, plotY, yBottom, lastPoint) { + if (lastPoint && clientX !== lastPoint.clientX) { + ctx.moveTo(lastPoint.clientX, lastPoint.yBottom); + ctx.lineTo(lastPoint.clientX, lastPoint.plotY); + ctx.lineTo(clientX, plotY); + ctx.lineTo(clientX, yBottom); + } + }, + fill: true, + fillOpacity: true, + sampling: true + }); + extend(seriesTypes.column.prototype, { + cvsDrawPoint: function (ctx, clientX, plotY, yBottom) { + ctx.rect(clientX - 1, plotY, 1, yBottom - plotY); + }, + fill: true, + sampling: true + }); + Chart.prototype.callbacks.push(function (chart) { + /** + * @private + */ + function canvasToSVG() { + if (chart.boostCopy) { + chart.boostCopy(); + } + } + /** + * @private + */ + function clear() { + if (chart.renderTarget) { + chart.renderTarget.attr({ href: '' }); + } + if (chart.canvas) { + chart.canvas.getContext('2d').clearRect(0, 0, chart.canvas.width, chart.canvas.height); + } + } + addEvent(chart, 'predraw', clear); + addEvent(chart, 'render', canvasToSVG); + }); + }; + + }); + _registerModule(_modules, 'masters/modules/boost-canvas.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/boost.js b/highcharts/modules/boost.js new file mode 100644 index 0000000..217f242 --- /dev/null +++ b/highcharts/modules/boost.js @@ -0,0 +1,136 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Boost module + + (c) 2010-2019 Highsoft AS + Author: Torstein Honsi + + License: www.highcharts.com/license + + This is a Highcharts module that draws long data series on a canvas in order + to increase performance of the initial load time and tooltip responsiveness. + + Compatible with WebGL compatible browsers (not IE < 11). + + If this module is taken in as part of the core + - All the loading logic should be merged with core. Update styles in the + core. + - Most of the method wraps should probably be added directly in parent + methods. + + Notes for boost mode + - Area lines are not drawn + - Lines are not drawn on scatter charts + - Zones and negativeColor don't work + - Dash styles are not rendered on lines. + - Columns are always one pixel wide. Don't set the threshold too low. + - Disable animations + - Marker shapes are not supported: markers will always be circles, except + heatmap series, where markers are always rectangles. + + Optimizing tips for users + - Set extremes (min, max) explicitly on the axes in order for Highcharts to + avoid computing extremes. + - Set enableMouseTracking to false on the series to improve total rendering + time. + - The default threshold is set based on one series. If you have multiple, + dense series, the combined number of points drawn gets higher, and you may + want to set the threshold lower in order to use optimizations. + - If drawing large scatter charts, it's beneficial to set the marker radius + to a value less than 1. This is to add additional spacing to make the chart + more readable. + - If the value increments on both the X and Y axis aren't small, consider + setting useGPUTranslations to true on the boost settings object. If you do + this and the increments are small (e.g. datetime axis with small time + increments) it may cause rendering issues due to floating point rounding + errors, so your millage may vary. + + Settings + There are two ways of setting the boost threshold: + - Per series: boost based on number of points in individual series + - Per chart: boost based on the number of series + + To set the series boost threshold, set seriesBoostThreshold on the chart + object. + To set the series-specific threshold, set boostThreshold on the series + object. + + In addition, the following can be set in the boost object: + { + //Wether or not to use alpha blending + useAlpha: boolean - default: true + //Set to true to perform translations on the GPU. + //Much faster, but may cause rendering issues + //when using values far from 0 due to floating point + //rounding issues + useGPUTranslations: boolean - default: false + //Use pre-allocated buffers, much faster, + //but may cause rendering issues with some data sets + usePreallocated: boolean - default: false + } +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/boost",["highcharts"],function(n){b(n);b.Highcharts=n;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function n(b,l,E,m){b.hasOwnProperty(l)||(b[l]=m.apply(null,E))}b=b?b._modules:{};n(b,"Extensions/Boost/Boostables.js",[],function(){return"area arearange column columnrange bar line scatter heatmap bubble treemap".split(" ")}); +n(b,"Extensions/Boost/BoostableMap.js",[b["Extensions/Boost/Boostables.js"]],function(b){var v={};b.forEach(function(b){v[b]=1});return v});n(b,"Extensions/Boost/WGLShader.js",[b["Core/Utilities.js"]],function(b){var v=b.clamp,E=b.error,m=b.pick;return function(d){function b(){k.length&&E("[highcharts boost] shader error - "+k.join("\n"))}function g(c,a){var e=d.createShader("vertex"===a?d.VERTEX_SHADER:d.FRAGMENT_SHADER);d.shaderSource(e,c);d.compileShader(e);return d.getShaderParameter(e,d.COMPILE_STATUS)? +e:(k.push("when compiling "+a+" shader:\n"+d.getShaderInfoLog(e)),!1)}function z(){function c(c){return d.getUniformLocation(a,c)}var H=g("#version 100\n#define LN10 2.302585092994046\nprecision highp float;\nattribute vec4 aVertexPosition;\nattribute vec4 aColor;\nvarying highp vec2 position;\nvarying highp vec4 vColor;\nuniform mat4 uPMatrix;\nuniform float pSize;\nuniform float translatedThreshold;\nuniform bool hasThreshold;\nuniform bool skipTranslation;\nuniform float xAxisTrans;\nuniform float xAxisMin;\nuniform float xAxisMinPad;\nuniform float xAxisPointRange;\nuniform float xAxisLen;\nuniform bool xAxisPostTranslate;\nuniform float xAxisOrdinalSlope;\nuniform float xAxisOrdinalOffset;\nuniform float xAxisPos;\nuniform bool xAxisCVSCoord;\nuniform bool xAxisIsLog;\nuniform bool xAxisReversed;\nuniform float yAxisTrans;\nuniform float yAxisMin;\nuniform float yAxisMinPad;\nuniform float yAxisPointRange;\nuniform float yAxisLen;\nuniform bool yAxisPostTranslate;\nuniform float yAxisOrdinalSlope;\nuniform float yAxisOrdinalOffset;\nuniform float yAxisPos;\nuniform bool yAxisCVSCoord;\nuniform bool yAxisIsLog;\nuniform bool yAxisReversed;\nuniform bool isBubble;\nuniform bool bubbleSizeByArea;\nuniform float bubbleZMin;\nuniform float bubbleZMax;\nuniform float bubbleZThreshold;\nuniform float bubbleMinSize;\nuniform float bubbleMaxSize;\nuniform bool bubbleSizeAbs;\nuniform bool isInverted;\nfloat bubbleRadius(){\nfloat value = aVertexPosition.w;\nfloat zMax = bubbleZMax;\nfloat zMin = bubbleZMin;\nfloat radius = 0.0;\nfloat pos = 0.0;\nfloat zRange = zMax - zMin;\nif (bubbleSizeAbs){\nvalue = value - bubbleZThreshold;\nzMax = max(zMax - bubbleZThreshold, zMin - bubbleZThreshold);\nzMin = 0.0;\n}\nif (value < zMin){\nradius = bubbleZMin / 2.0 - 1.0;\n} else {\npos = zRange > 0.0 ? (value - zMin) / zRange : 0.5;\nif (bubbleSizeByArea && pos > 0.0){\npos = sqrt(pos);\n}\nradius = ceil(bubbleMinSize + pos * (bubbleMaxSize - bubbleMinSize)) / 2.0;\n}\nreturn radius * 2.0;\n}\nfloat translate(float val,\nfloat pointPlacement,\nfloat localA,\nfloat localMin,\nfloat minPixelPadding,\nfloat pointRange,\nfloat len,\nbool cvsCoord,\nbool isLog,\nbool reversed\n){\nfloat sign = 1.0;\nfloat cvsOffset = 0.0;\nif (cvsCoord) {\nsign *= -1.0;\ncvsOffset = len;\n}\nif (isLog) {\nval = log(val) / LN10;\n}\nif (reversed) {\nsign *= -1.0;\ncvsOffset -= sign * len;\n}\nreturn sign * (val - localMin) * localA + cvsOffset + \n(sign * minPixelPadding);\n}\nfloat xToPixels(float value) {\nif (skipTranslation){\nreturn value;// + xAxisPos;\n}\nreturn translate(value, 0.0, xAxisTrans, xAxisMin, xAxisMinPad, xAxisPointRange, xAxisLen, xAxisCVSCoord, xAxisIsLog, xAxisReversed);// + xAxisPos;\n}\nfloat yToPixels(float value, float checkTreshold) {\nfloat v;\nif (skipTranslation){\nv = value;// + yAxisPos;\n} else {\nv = translate(value, 0.0, yAxisTrans, yAxisMin, yAxisMinPad, yAxisPointRange, yAxisLen, yAxisCVSCoord, yAxisIsLog, yAxisReversed);// + yAxisPos;\nif (v > yAxisLen) {\nv = yAxisLen;\n}\n}\nif (checkTreshold > 0.0 && hasThreshold) {\nv = min(v, translatedThreshold);\n}\nreturn v;\n}\nvoid main(void) {\nif (isBubble){\ngl_PointSize = bubbleRadius();\n} else {\ngl_PointSize = pSize;\n}\nvColor = aColor;\nif (skipTranslation && isInverted) {\ngl_Position = uPMatrix * vec4(aVertexPosition.y + yAxisPos, aVertexPosition.x + xAxisPos, 0.0, 1.0);\n} else if (isInverted) {\ngl_Position = uPMatrix * vec4(yToPixels(aVertexPosition.y, aVertexPosition.z) + yAxisPos, xToPixels(aVertexPosition.x) + xAxisPos, 0.0, 1.0);\n} else {\ngl_Position = uPMatrix * vec4(xToPixels(aVertexPosition.x) + xAxisPos, yToPixels(aVertexPosition.y, aVertexPosition.z) + yAxisPos, 0.0, 1.0);\n}\n}", +"vertex"),e=g("precision highp float;\nuniform vec4 fillColor;\nvarying highp vec2 position;\nvarying highp vec4 vColor;\nuniform sampler2D uSampler;\nuniform bool isCircle;\nuniform bool hasColor;\nvoid main(void) {\nvec4 col = fillColor;\nvec4 tcol;\nif (hasColor) {\ncol = vColor;\n}\nif (isCircle) {\ntcol = texture2D(uSampler, gl_PointCoord.st);\ncol *= tcol;\nif (tcol.r < 0.0) {\ndiscard;\n} else {\ngl_FragColor = col;\n}\n} else {\ngl_FragColor = col;\n}\n}","fragment");if(!H||!e)return a=!1, +b(),!1;a=d.createProgram();d.attachShader(a,H);d.attachShader(a,e);d.linkProgram(a);if(!d.getProgramParameter(a,d.LINK_STATUS))return k.push(d.getProgramInfoLog(a)),b(),a=!1;d.useProgram(a);d.bindAttribLocation(a,0,"aVertexPosition");w=c("uPMatrix");p=c("pSize");f=c("fillColor");B=c("isBubble");O=c("bubbleSizeAbs");h=c("bubbleSizeByArea");I=c("uSampler");l=c("skipTranslation");G=c("isCircle");t=c("isInverted");return!0}function q(c,k){d&&a&&(c=r[c]=r[c]||d.getUniformLocation(a,c),d.uniform1f(c,k))} +var r={},a,w,p,f,B,O,h,l,G,t,k=[],I;return d&&!z()?!1:{psUniform:function(){return p},pUniform:function(){return w},fillColorUniform:function(){return f},setBubbleUniforms:function(c,k,e){var t=c.options,b=Number.MAX_VALUE,p=-Number.MAX_VALUE;d&&a&&"bubble"===c.type&&(b=m(t.zMin,v(k,!1===t.displayNegative?t.zThreshold:-Number.MAX_VALUE,b)),p=m(t.zMax,Math.max(p,e)),d.uniform1i(B,1),d.uniform1i(G,1),d.uniform1i(h,"width"!==c.options.sizeBy),d.uniform1i(O,c.options.sizeByAbsoluteValue),q("bubbleZMin", +b),q("bubbleZMax",p),q("bubbleZThreshold",c.options.zThreshold),q("bubbleMinSize",c.minPxSize),q("bubbleMaxSize",c.maxPxSize))},bind:function(){d&&a&&d.useProgram(a)},program:function(){return a},create:z,setUniform:q,setPMatrix:function(c){d&&a&&d.uniformMatrix4fv(w,!1,c)},setColor:function(c){d&&a&&d.uniform4f(f,c[0]/255,c[1]/255,c[2]/255,c[3])},setPointSize:function(c){d&&a&&d.uniform1f(p,c)},setSkipTranslation:function(c){d&&a&&d.uniform1i(l,!0===c?1:0)},setTexture:function(c){d&&a&&d.uniform1i(I, +c)},setDrawAsCircle:function(c){d&&a&&d.uniform1i(G,c?1:0)},reset:function(){d&&a&&(d.uniform1i(B,0),d.uniform1i(G,0))},setInverted:function(c){d&&a&&d.uniform1i(t,c)},destroy:function(){d&&a&&(d.deleteProgram(a),a=!1)}}}});n(b,"Extensions/Boost/WGLVBuffer.js",[],function(){return function(b,l,E){function m(){d&&(b.deleteBuffer(d),v=d=!1);q=0;g=E||2;r=[]}var d=!1,v=!1,g=E||2,z=!1,q=0,r;return{destroy:m,bind:function(){if(!d)return!1;b.vertexAttribPointer(v,g,b.FLOAT,!1,0,0)},data:r,build:function(a, +w,p){var f;r=a||[];if(!(r&&0!==r.length||z))return m(),!1;g=p||g;d&&b.deleteBuffer(d);z||(f=new Float32Array(r));d=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,d);b.bufferData(b.ARRAY_BUFFER,z||f,b.STATIC_DRAW);v=b.getAttribLocation(l.program(),w);b.enableVertexAttribArray(v);return!0},render:function(a,m,p){var f=z?z.length:r.length;if(!d||!f)return!1;if(!a||a>f||0>a)a=0;if(!m||m>f)m=f;b.drawArrays(b[(p||"points").toUpperCase()],a/g,(m-a)/g);return!0},allocate:function(a){q=-1;z=new Float32Array(4* +a)},push:function(a,b,d,f){z&&(z[++q]=a,z[++q]=b,z[++q]=d,z[++q]=f)}}}});n(b,"Extensions/Boost/WGLRenderer.js",[b["Core/Globals.js"],b["Extensions/Boost/WGLShader.js"],b["Extensions/Boost/WGLVBuffer.js"],b["Core/Color.js"],b["Core/Utilities.js"]],function(b,l,E,m,d){var v=m.parse,g=d.isNumber,z=d.isObject,q=d.merge,r=d.objectEach,a=d.pick,w=b.win.document;return function(d){function p(c){if(c.isSeriesBoosting){var a=!!c.options.stacking;var e=c.xData||c.options.xData||c.processedXData;a=(a?c.data: +e||c.options.data).length;"treemap"===c.type?a*=12:"heatmap"===c.type?a*=6:ma[c.type]&&(a*=2);return a}return 0}function B(){e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT)}function O(c,a){function e(c){c&&(a.colorData.push(c[0]),a.colorData.push(c[1]),a.colorData.push(c[2]),a.colorData.push(c[3]))}function b(c,a,b,k,d){e(d);y.usePreallocated?H.push(c,a,b?1:0,k||1):(N.push(c),N.push(a),N.push(b?1:0),N.push(k||1))}function k(){a.segments.length&&(a.segments[a.segments.length-1].to=N.length)}function d(){a.segments.length&& +a.segments[a.segments.length-1].from===N.length||(k(),a.segments.push({from:N.length}))}function t(c,a,k,d,t){e(t);b(c+k,a);e(t);b(c,a);e(t);b(c,a+d);e(t);b(c,a+d);e(t);b(c+k,a+d);e(t);b(c+k,a)}function p(c,e){y.useGPUTranslations||(a.skipTranslation=!0,c.x=w.toPixels(c.x,!0),c.y=n.toPixels(c.y,!0));e?N=[c.x,c.y,0,2].concat(N):b(c.x,c.y,0,2)}var Z=c.pointArrayMap&&"low,high"===c.pointArrayMap.join(","),P=c.chart,f=c.options,G=!!f.stacking,I=f.data,g=c.xAxis.getExtremes(),h=g.min;g=g.max;var B=c.yAxis.getExtremes(), +q=B.min;B=B.max;var l=c.xData||f.xData||c.processedXData,O=c.yData||f.yData||c.processedYData,r=c.zData||f.zData||c.processedZData,n=c.yAxis,w=c.xAxis,E=c.chart.plotWidth,J=!l||0===l.length,L=f.connectNulls,u=c.points||!1,F=!1,K=!1,Q;l=G?c.data:l||I;var X={x:Number.MAX_VALUE,y:0},M={x:-Number.MAX_VALUE,y:0},T=0,W=!1,D=-1,S=!1,U=!1,ka="undefined"===typeof P.index,fa=!1,ha=!1;var x=!1;var za=ma[c.type],ia=!1,sa=!0,ta=!0,Y=f.zones||!1,V=!1,ua=f.threshold,ja=!1;if(!(f.boostData&&0a.node.levelDynamic)return 1;if(c.node.levelDynamica.zMax&&(a.zMax=C[2]);C[2]a.zMax&&(a.zMax=r[D]),r[D]=h&&U<=g&&(fa=!0);S&&S>=h&&S<=g&&(ha=!0);if(Z){J&&(A=C.slice(1,3));var ba= +A[0];A=A[1]}else G&&(u=C.x,A=C.stackY,ba=A-C.y);null!==q&&"undefined"!==typeof q&&null!==B&&"undefined"!==typeof B&&(sa=A>=q&&A<=B);u>g&&M.xh&&(X.x=u,X.y=A);if(null!==A||!L)if(null!==A&&(sa||fa||ha)){if((U>=h||u>=h)&&(S<=g||u<=g)&&(ia=!0),ia||fa||ha){ja&&u-S>ja&&d();Y&&(x=V.rgba,Y.some(function(c,a){a=Y[a-1];if("undefined"!==typeof c.value&&A<=c.value){if(!a||A>=a.value)x=v(c.color).rgba;return!0}return!1}),x[0]/=255,x[1]/=255,x[2]/=255);if(!y.useGPUTranslations&&(a.skipTranslation= +!0,u=w.toPixels(u,!0),A=n.toPixels(A,!0),u>E&&"points"===a.drawMode))continue;if(za){C=ba;if(!1===ba||"undefined"===typeof ba)C=0>A?A:0;Z||G||(C=Math.max(null===ua?q:ua,q));y.useGPUTranslations||(C=n.toPixels(C,!0));b(u,C,0,0,x)}a.hasMarkers&&ia&&!1!==F&&(c.closestPointRangePx=Math.min(c.closestPointRangePx,Math.abs(u-F)));!y.useGPUTranslations&&!y.usePreallocated&&F&&1>Math.abs(u-F)&&K&&1>Math.abs(A-K)?y.debug.showSkipSummary&&++T:(f.step&&!ta&&b(u,K,0,2,x),b(u,A,0,"bubble"===c.type?va||1:2,x),F= +u,K=A,W=!0,ta=!1)}}else d()}else d()}y.debug.showSkipSummary&&console.log("skipped points:",T);W||!1===L||"line_strip"!==c.drawMode||(X.x-Number.MAX_VALUE&&p(M))}k()}}function h(){F=[];W.data=N=[];L=[];H&&H.destroy()}function J(a){c&&(c.setUniform("xAxisTrans",a.transA),c.setUniform("xAxisMin",a.min),c.setUniform("xAxisMinPad",a.minPixelPadding),c.setUniform("xAxisPointRange",a.pointRange),c.setUniform("xAxisLen",a.len),c.setUniform("xAxisPos",a.pos),c.setUniform("xAxisCVSCoord", +!a.horiz),c.setUniform("xAxisIsLog",!!a.logarithmic),c.setUniform("xAxisReversed",!!a.reversed))}function G(a){c&&(c.setUniform("yAxisTrans",a.transA),c.setUniform("yAxisMin",a.min),c.setUniform("yAxisMinPad",a.minPixelPadding),c.setUniform("yAxisPointRange",a.pointRange),c.setUniform("yAxisLen",a.len),c.setUniform("yAxisPos",a.pos),c.setUniform("yAxisCVSCoord",!a.horiz),c.setUniform("yAxisIsLog",!!a.logarithmic),c.setUniform("yAxisReversed",!!a.reversed))}function t(a,e){c.setUniform("hasThreshold", +a);c.setUniform("translatedThreshold",e)}function k(k){if(k)n=k.chartWidth||800,K=k.chartHeight||400;else return!1;if(!(e&&n&&K&&c))return!1;y.debug.timeRendering&&console.time("gl rendering");e.canvas.width=n;e.canvas.height=K;c.bind();e.viewport(0,0,n,K);c.setPMatrix([2/n,0,0,0,0,-(2/K),0,0,0,0,-2,0,-1,1,-1,1]);12*((f.marker?f.marker.radius:10)||10));p=M[p&&p.symbol||b.series.symbol]||M.circle;if(!(0===b.segments.length||b.segmentslength&&b.segments[0].from===b.segments[0].to)){p.isReady&&(e.bindTexture(e.TEXTURE_2D,p.handle),c.setTexture(p.handle));k.styledMode?p=b.series.markerGroup&&b.series.markerGroup.getStyle("fill"): +(p=b.series.pointAttribs&&b.series.pointAttribs().fill||b.series.color,f.colorByPoint&&(p=b.series.chart.options.colors[d]));b.series.fillOpacity&&f.fillOpacity&&(p=(new m(p)).setOpacity(a(f.fillOpacity,1)).get());p=v(p).rgba;y.useAlpha||(p[3]=1);"lines"===b.drawMode&&y.useAlpha&&1>p[3]&&(p[3]/=10);"add"===f.boostBlending?(e.blendFunc(e.SRC_ALPHA,e.ONE),e.blendEquation(e.FUNC_ADD)):"mult"===f.boostBlending||"multiply"===f.boostBlending?e.blendFunc(e.DST_COLOR,e.ZERO):"darken"===f.boostBlending?(e.blendFunc(e.ONE, +e.ONE),e.blendEquation(e.FUNC_MIN)):e.blendFuncSeparate(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA,e.ONE,e.ONE_MINUS_SRC_ALPHA);c.reset();0=(m.options.boostThreshold||Number.MAX_VALUE)&&++b)}a.boostForceChartBoost=p&&(g===a.series.length&&0=v&&f<=M);if(null!==f&&t>=q&&t<=r&&k)if(a=e.toPixels(t,!0),y){if("undefined"===typeof R||a===O){la||(b=f);if("undefined"===typeof aa||f>da)da=f,aa=c;if("undefined"=== +typeof R||b=(f.options.boostThreshold||Number.MAX_VALUE)}var f=this,c=this.options.data;B(this.chart)&&g[this.type]?(d(c)&&"heatmap"!==this.type&&"treemap"!==this.type&& +!this.options.stacking&&this.hasExtremes&&this.hasExtremes(!0)||(b.apply(this,Array.prototype.slice.call(arguments,1)),c=this.processedXData),(this.isSeriesBoosting=d(c))?(c=this.getFirstValidPoint(this.options.data),w(c)||a(c)||q(12,!1,this.chart),this.enterBoost()):this.exitBoost&&this.exitBoost()):b.apply(this,Array.prototype.slice.call(arguments,1))});v(h,"hide",function(){this.canvas&&this.renderTarget&&(this.ogl&&this.ogl.clear(),this.boostClear())});h.prototype.enterBoost=function(){this.alteredByBoost= +[];["allowDG","directTouch","stickyTracking"].forEach(function(a){this.alteredByBoost.push({prop:a,val:this[a],own:Object.hasOwnProperty.call(this,a)})},this);this.directTouch=this.allowDG=!1;this.finishedAnimating=this.stickyTracking=!0;this.labelBySeries&&(this.labelBySeries=this.labelBySeries.destroy())};h.prototype.exitBoost=function(){(this.alteredByBoost||[]).forEach(function(a){a.own?this[a.prop]=a.val:delete this[a.prop]},this);this.boostClear&&this.boostClear()};h.prototype.hasExtremes=function(a){var b= +this.options,d=this.xAxis&&this.xAxis.options,c=this.yAxis&&this.yAxis.options,f=this.colorAxis&&this.colorAxis.options;return b.data.length>(b.boostThreshold||Number.MAX_VALUE)&&w(c.min)&&w(c.max)&&(!a||w(d.min)&&w(d.max))&&(!f||w(f.min)&&w(f.max))};h.prototype.destroyGraphics=function(){var a=this,b=this.points,d,c;if(b)for(c=0;c 0.0 ? (value - zMin) / zRange : 0.5;', + 'if (bubbleSizeByArea && pos > 0.0){', + 'pos = sqrt(pos);', + '}', + 'radius = ceil(bubbleMinSize + pos * (bubbleMaxSize - bubbleMinSize)) / 2.0;', + '}', + 'return radius * 2.0;', + '}', + 'float translate(float val,', + 'float pointPlacement,', + 'float localA,', + 'float localMin,', + 'float minPixelPadding,', + 'float pointRange,', + 'float len,', + 'bool cvsCoord,', + 'bool isLog,', + 'bool reversed', + '){', + 'float sign = 1.0;', + 'float cvsOffset = 0.0;', + 'if (cvsCoord) {', + 'sign *= -1.0;', + 'cvsOffset = len;', + '}', + 'if (isLog) {', + 'val = log(val) / LN10;', + '}', + 'if (reversed) {', + 'sign *= -1.0;', + 'cvsOffset -= sign * len;', + '}', + 'return sign * (val - localMin) * localA + cvsOffset + ', + '(sign * minPixelPadding);', + '}', + 'float xToPixels(float value) {', + 'if (skipTranslation){', + 'return value;// + xAxisPos;', + '}', + 'return translate(value, 0.0, xAxisTrans, xAxisMin, xAxisMinPad, xAxisPointRange, xAxisLen, xAxisCVSCoord, xAxisIsLog, xAxisReversed);// + xAxisPos;', + '}', + 'float yToPixels(float value, float checkTreshold) {', + 'float v;', + 'if (skipTranslation){', + 'v = value;// + yAxisPos;', + '} else {', + 'v = translate(value, 0.0, yAxisTrans, yAxisMin, yAxisMinPad, yAxisPointRange, yAxisLen, yAxisCVSCoord, yAxisIsLog, yAxisReversed);// + yAxisPos;', + 'if (v > yAxisLen) {', + 'v = yAxisLen;', + '}', + '}', + 'if (checkTreshold > 0.0 && hasThreshold) {', + 'v = min(v, translatedThreshold);', + '}', + 'return v;', + '}', + 'void main(void) {', + 'if (isBubble){', + 'gl_PointSize = bubbleRadius();', + '} else {', + 'gl_PointSize = pSize;', + '}', + // 'gl_PointSize = 10.0;', + 'vColor = aColor;', + 'if (skipTranslation && isInverted) {', + // If we get translated values from JS, just swap them (x, y) + 'gl_Position = uPMatrix * vec4(aVertexPosition.y + yAxisPos, aVertexPosition.x + xAxisPos, 0.0, 1.0);', + '} else if (isInverted) {', + // But when calculating pixel positions directly, + // swap axes and values (x, y) + 'gl_Position = uPMatrix * vec4(yToPixels(aVertexPosition.y, aVertexPosition.z) + yAxisPos, xToPixels(aVertexPosition.x) + xAxisPos, 0.0, 1.0);', + '} else {', + 'gl_Position = uPMatrix * vec4(xToPixels(aVertexPosition.x) + xAxisPos, yToPixels(aVertexPosition.y, aVertexPosition.z) + yAxisPos, 0.0, 1.0);', + '}', + // 'gl_Position = uPMatrix * vec4(aVertexPosition.x, aVertexPosition.y, 0.0, 1.0);', + '}' + /* eslint-enable max-len, @typescript-eslint/indent */ + ].join('\n'), + // Fragment shader source + fragShade = [ + /* eslint-disable max-len, @typescript-eslint/indent */ + 'precision highp float;', + 'uniform vec4 fillColor;', + 'varying highp vec2 position;', + 'varying highp vec4 vColor;', + 'uniform sampler2D uSampler;', + 'uniform bool isCircle;', + 'uniform bool hasColor;', + // 'vec4 toColor(float value, vec2 point) {', + // 'return vec4(0.0, 0.0, 0.0, 0.0);', + // '}', + 'void main(void) {', + 'vec4 col = fillColor;', + 'vec4 tcol;', + 'if (hasColor) {', + 'col = vColor;', + '}', + 'if (isCircle) {', + 'tcol = texture2D(uSampler, gl_PointCoord.st);', + 'col *= tcol;', + 'if (tcol.r < 0.0) {', + 'discard;', + '} else {', + 'gl_FragColor = col;', + '}', + '} else {', + 'gl_FragColor = col;', + '}', + '}' + /* eslint-enable max-len, @typescript-eslint/indent */ + ].join('\n'), uLocations = {}, + // The shader program + shaderProgram, + // Uniform handle to the perspective matrix + pUniform, + // Uniform for point size + psUniform, + // Uniform for fill color + fillColorUniform, + // Uniform for isBubble + isBubbleUniform, + // Uniform for bubble abs sizing + bubbleSizeAbsUniform, bubbleSizeAreaUniform, + // Skip translation uniform + skipTranslationUniform, + // Set to 1 if circle + isCircleUniform, + // Uniform for invertion + isInverted, + // Error stack + errors = [], + // Texture uniform + uSamplerUniform; + /** + * Handle errors accumulated in errors stack + * @private + */ + function handleErrors() { + if (errors.length) { + error('[highcharts boost] shader error - ' + errors.join('\n')); + } + } + /** + * String to shader program + * @private + * @param {string} str - the program source + * @param {string} type - the program type: either `vertex` or `fragment` + * @returns {bool|shader} + */ + function stringToProgram(str, type) { + var t = type === 'vertex' ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER, + shader = gl.createShader(t); + gl.shaderSource(shader, str); + gl.compileShader(shader); + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + errors.push('when compiling ' + + type + + ' shader:\n' + + gl.getShaderInfoLog(shader)); + return false; + } + return shader; + } + /** + * Create the shader. + * Loads the shader program statically defined above + * @private + */ + function createShader() { + var v = stringToProgram(vertShade, 'vertex'), f = stringToProgram(fragShade, 'fragment'); + if (!v || !f) { + shaderProgram = false; + handleErrors(); + return false; + } + /** + * @private + */ + function uloc(n) { + return gl.getUniformLocation(shaderProgram, n); + } + shaderProgram = gl.createProgram(); + gl.attachShader(shaderProgram, v); + gl.attachShader(shaderProgram, f); + gl.linkProgram(shaderProgram); + if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { + errors.push(gl.getProgramInfoLog(shaderProgram)); + handleErrors(); + shaderProgram = false; + return false; + } + gl.useProgram(shaderProgram); + gl.bindAttribLocation(shaderProgram, 0, 'aVertexPosition'); + pUniform = uloc('uPMatrix'); + psUniform = uloc('pSize'); + fillColorUniform = uloc('fillColor'); + isBubbleUniform = uloc('isBubble'); + bubbleSizeAbsUniform = uloc('bubbleSizeAbs'); + bubbleSizeAreaUniform = uloc('bubbleSizeByArea'); + uSamplerUniform = uloc('uSampler'); + skipTranslationUniform = uloc('skipTranslation'); + isCircleUniform = uloc('isCircle'); + isInverted = uloc('isInverted'); + return true; + } + /** + * Destroy the shader + * @private + */ + function destroy() { + if (gl && shaderProgram) { + gl.deleteProgram(shaderProgram); + shaderProgram = false; + } + } + /** + * Bind the shader. + * This makes the shader the active one until another one is bound, + * or until 0 is bound. + * @private + */ + function bind() { + if (gl && shaderProgram) { + gl.useProgram(shaderProgram); + } + } + /** + * Set a uniform value. + * This uses a hash map to cache uniform locations. + * @private + * @param name {string} - the name of the uniform to set + * @param val {float} - the value to set + */ + function setUniform(name, val) { + if (gl && shaderProgram) { + var u = uLocations[name] = (uLocations[name] || + gl.getUniformLocation(shaderProgram, + name)); + gl.uniform1f(u, val); + } + } + /** + * Set the active texture + * @private + * @param texture - the texture + */ + function setTexture(texture) { + if (gl && shaderProgram) { + gl.uniform1i(uSamplerUniform, texture); + } + } + /** + * Set if inversion state + * @private + * @flag is the state + */ + function setInverted(flag) { + if (gl && shaderProgram) { + gl.uniform1i(isInverted, flag); + } + } + /** + * Enable/disable circle drawing + * @private + */ + function setDrawAsCircle(flag) { + if (gl && shaderProgram) { + gl.uniform1i(isCircleUniform, flag ? 1 : 0); + } + } + /** + * Flush + * @private + */ + function reset() { + if (gl && shaderProgram) { + gl.uniform1i(isBubbleUniform, 0); + gl.uniform1i(isCircleUniform, 0); + } + } + /** + * Set bubble uniforms + * @private + * @param series {Highcharts.Series} - the series to use + */ + function setBubbleUniforms(series, zCalcMin, zCalcMax) { + var seriesOptions = series.options, + zMin = Number.MAX_VALUE, + zMax = -Number.MAX_VALUE; + if (gl && shaderProgram && series.type === 'bubble') { + zMin = pick(seriesOptions.zMin, clamp(zCalcMin, seriesOptions.displayNegative === false ? + seriesOptions.zThreshold : -Number.MAX_VALUE, zMin)); + zMax = pick(seriesOptions.zMax, Math.max(zMax, zCalcMax)); + gl.uniform1i(isBubbleUniform, 1); + gl.uniform1i(isCircleUniform, 1); + gl.uniform1i(bubbleSizeAreaUniform, (series.options.sizeBy !== 'width')); + gl.uniform1i(bubbleSizeAbsUniform, series.options + .sizeByAbsoluteValue); + setUniform('bubbleZMin', zMin); + setUniform('bubbleZMax', zMax); + setUniform('bubbleZThreshold', series.options.zThreshold); + setUniform('bubbleMinSize', series.minPxSize); + setUniform('bubbleMaxSize', series.maxPxSize); + } + } + /** + * Set the Color uniform. + * @private + * @param color {Array} - an array with RGBA values + */ + function setColor(color) { + if (gl && shaderProgram) { + gl.uniform4f(fillColorUniform, color[0] / 255.0, color[1] / 255.0, color[2] / 255.0, color[3]); + } + } + /** + * Set skip translation + * @private + */ + function setSkipTranslation(flag) { + if (gl && shaderProgram) { + gl.uniform1i(skipTranslationUniform, flag === true ? 1 : 0); + } + } + /** + * Set the perspective matrix + * @private + * @param m {Matrix4x4} - the matrix + */ + function setPMatrix(m) { + if (gl && shaderProgram) { + gl.uniformMatrix4fv(pUniform, false, m); + } + } + /** + * Set the point size. + * @private + * @param p {float} - point size + */ + function setPointSize(p) { + if (gl && shaderProgram) { + gl.uniform1f(psUniform, p); + } + } + /** + * Get the shader program handle + * @private + * @return {GLInt} - the handle for the program + */ + function getProgram() { + return shaderProgram; + } + if (gl) { + if (!createShader()) { + return false; + } + } + return { + psUniform: function () { + return psUniform; + }, + pUniform: function () { + return pUniform; + }, + fillColorUniform: function () { + return fillColorUniform; + }, + setBubbleUniforms: setBubbleUniforms, + bind: bind, + program: getProgram, + create: createShader, + setUniform: setUniform, + setPMatrix: setPMatrix, + setColor: setColor, + setPointSize: setPointSize, + setSkipTranslation: setSkipTranslation, + setTexture: setTexture, + setDrawAsCircle: setDrawAsCircle, + reset: reset, + setInverted: setInverted, + destroy: destroy + }; + } + + return GLShader; + }); + _registerModule(_modules, 'Extensions/Boost/WGLVBuffer.js', [], function () { + /* * + * + * Copyright (c) 2019-2020 Highsoft AS + * + * Boost module: stripped-down renderer for higher performance + * + * License: highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* eslint-disable valid-jsdoc */ + /** + * Vertex Buffer abstraction. + * A vertex buffer is a set of vertices which are passed to the GPU + * in a single call. + * + * @private + * @function GLVertexBuffer + * + * @param {WebGLContext} gl + * the context in which to create the buffer + * + * @param {GLShader} shader + * the shader to use + * + * @return {*} + */ + function GLVertexBuffer(gl, shader, dataComponents + /* , type */ + ) { + var buffer = false, + vertAttribute = false, + components = dataComponents || 2, + preAllocated = false, + iterator = 0, + // farray = false, + data; + // type = type || 'float'; + /** + * @private + */ + function destroy() { + if (buffer) { + gl.deleteBuffer(buffer); + buffer = false; + vertAttribute = false; + } + iterator = 0; + components = dataComponents || 2; + data = []; + } + /** + * Build the buffer + * @private + * @param dataIn {Array} - a 0 padded array of indices + * @param attrib {String} - the name of the Attribute to bind the buffer to + * @param dataComponents {Integer} - the number of components per. indice + */ + function build(dataIn, attrib, dataComponents) { + var farray; + data = dataIn || []; + if ((!data || data.length === 0) && !preAllocated) { + // console.error('trying to render empty vbuffer'); + destroy(); + return false; + } + components = dataComponents || components; + if (buffer) { + gl.deleteBuffer(buffer); + } + if (!preAllocated) { + farray = new Float32Array(data); + } + buffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, preAllocated || farray, gl.STATIC_DRAW); + // gl.bindAttribLocation(shader.program(), 0, 'aVertexPosition'); + vertAttribute = gl.getAttribLocation(shader.program(), attrib); + gl.enableVertexAttribArray(vertAttribute); + // Trigger cleanup + farray = false; + return true; + } + /** + * Bind the buffer + * @private + */ + function bind() { + if (!buffer) { + return false; + } + // gl.bindAttribLocation(shader.program(), 0, 'aVertexPosition'); + // gl.enableVertexAttribArray(vertAttribute); + // gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.vertexAttribPointer(vertAttribute, components, gl.FLOAT, false, 0, 0); + // gl.enableVertexAttribArray(vertAttribute); + } + /** + * Render the buffer + * @private + * @param from {Integer} - the start indice + * @param to {Integer} - the end indice + * @param drawMode {String} - the draw mode + */ + function render(from, to, drawMode) { + var length = preAllocated ? preAllocated.length : data.length; + if (!buffer) { + return false; + } + if (!length) { + return false; + } + if (!from || from > length || from < 0) { + from = 0; + } + if (!to || to > length) { + to = length; + } + drawMode = drawMode || 'points'; + gl.drawArrays(gl[drawMode.toUpperCase()], from / components, (to - from) / components); + return true; + } + /** + * @private + */ + function push(x, y, a, b) { + if (preAllocated) { // && iterator <= preAllocated.length - 4) { + preAllocated[++iterator] = x; + preAllocated[++iterator] = y; + preAllocated[++iterator] = a; + preAllocated[++iterator] = b; + } + } + /** + * Note about pre-allocated buffers: + * - This is slower for charts with many series + * @private + */ + function allocate(size) { + size *= 4; + iterator = -1; + preAllocated = new Float32Array(size); + } + // ///////////////////////////////////////////////////////////////////////// + return { + destroy: destroy, + bind: bind, + data: data, + build: build, + render: render, + allocate: allocate, + push: push + }; + } + + return GLVertexBuffer; + }); + _registerModule(_modules, 'Extensions/Boost/WGLRenderer.js', [_modules['Core/Globals.js'], _modules['Extensions/Boost/WGLShader.js'], _modules['Extensions/Boost/WGLVBuffer.js'], _modules['Core/Color.js'], _modules['Core/Utilities.js']], function (H, GLShader, GLVertexBuffer, Color, U) { + /* * + * + * Copyright (c) 2019-2020 Highsoft AS + * + * Boost module: stripped-down renderer for higher performance + * + * License: highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var color = Color.parse; + var isNumber = U.isNumber, + isObject = U.isObject, + merge = U.merge, + objectEach = U.objectEach, + pick = U.pick; + var win = H.win, + doc = win.document; + /* eslint-disable valid-jsdoc */ + /** + * Main renderer. Used to render series. + * + * Notes to self: + * - May be able to build a point map by rendering to a separate canvas and + * encoding values in the color data. + * - Need to figure out a way to transform the data quicker + * + * @private + * @function GLRenderer + * + * @param {Function} postRenderCallback + * + * @return {*} + */ + function GLRenderer(postRenderCallback) { + // // Shader + var shader = false, + // Vertex buffers - keyed on shader attribute name + vbuffer = false, + // Opengl context + gl = false, + // Width of our viewport in pixels + width = 0, + // Height of our viewport in pixels + height = 0, + // The data to render - array of coordinates + data = false, + // The marker data + markerData = false, + // Exports + exports = {}, + // Is it inited? + isInited = false, + // The series stack + series = [], + // Texture handles + textureHandles = {}, + // Things to draw as "rectangles" (i.e lines) + asBar = { + 'column': true, + 'columnrange': true, + 'bar': true, + 'area': true, + 'arearange': true + }, + asCircle = { + 'scatter': true, + 'bubble': true + }, + // Render settings + settings = { + pointSize: 1, + lineWidth: 1, + fillColor: '#AA00AA', + useAlpha: true, + usePreallocated: false, + useGPUTranslations: false, + debug: { + timeRendering: false, + timeSeriesProcessing: false, + timeSetup: false, + timeBufferCopy: false, + timeKDTree: false, + showSkipSummary: false + } + }; + // ///////////////////////////////////////////////////////////////////////// + /** + * @private + */ + function setOptions(options) { + merge(true, settings, options); + } + /** + * @private + */ + function seriesPointCount(series) { + var isStacked, + xData, + s; + if (series.isSeriesBoosting) { + isStacked = !!series.options.stacking; + xData = (series.xData || + series.options.xData || + series.processedXData); + s = (isStacked ? series.data : (xData || series.options.data)) + .length; + if (series.type === 'treemap') { + s *= 12; + } + else if (series.type === 'heatmap') { + s *= 6; + } + else if (asBar[series.type]) { + s *= 2; + } + return s; + } + return 0; + } + /** + * Allocate a float buffer to fit all series + * @private + */ + function allocateBuffer(chart) { + var s = 0; + if (!settings.usePreallocated) { + return; + } + chart.series.forEach(function (series) { + if (series.isSeriesBoosting) { + s += seriesPointCount(series); + } + }); + vbuffer.allocate(s); + } + /** + * @private + */ + function allocateBufferForSingleSeries(series) { + var s = 0; + if (!settings.usePreallocated) { + return; + } + if (series.isSeriesBoosting) { + s = seriesPointCount(series); + } + vbuffer.allocate(s); + } + /** + * Returns an orthographic perspective matrix + * @private + * @param {number} width - the width of the viewport in pixels + * @param {number} height - the height of the viewport in pixels + */ + function orthoMatrix(width, height) { + var near = 0, + far = 1; + return [ + 2 / width, 0, 0, 0, + 0, -(2 / height), 0, 0, + 0, 0, -2 / (far - near), 0, + -1, 1, -(far + near) / (far - near), 1 + ]; + } + /** + * Clear the depth and color buffer + * @private + */ + function clear() { + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + } + /** + * Get the WebGL context + * @private + * @returns {WebGLContext} - the context + */ + function getGL() { + return gl; + } + /** + * Push data for a single series + * This calculates additional vertices and transforms the data to be + * aligned correctly in memory + * @private + */ + function pushSeriesData(series, inst) { + var isRange = (series.pointArrayMap && + series.pointArrayMap.join(',') === 'low,high'), chart = series.chart, options = series.options, isStacked = !!options.stacking, rawData = options.data, xExtremes = series.xAxis.getExtremes(), xMin = xExtremes.min, xMax = xExtremes.max, yExtremes = series.yAxis.getExtremes(), yMin = yExtremes.min, yMax = yExtremes.max, xData = series.xData || options.xData || series.processedXData, yData = series.yData || options.yData || series.processedYData, zData = (series.zData || options.zData || + series.processedZData), yAxis = series.yAxis, xAxis = series.xAxis, + // plotHeight = series.chart.plotHeight, + plotWidth = series.chart.plotWidth, useRaw = !xData || xData.length === 0, + // threshold = options.threshold, + // yBottom = chart.yAxis[0].getThreshold(threshold), + // hasThreshold = isNumber(threshold), + // colorByPoint = series.options.colorByPoint, + // This is required for color by point, so make sure this is + // uncommented if enabling that + // colorIndex = 0, + // Required for color axis support + // caxis, + connectNulls = options.connectNulls, + // For some reason eslint/TypeScript don't pick up that this is + // actually used: --- bre1470: it is never read, just set + // maxVal: (number|undefined), // eslint-disable-line no-unused-vars + points = series.points || false, lastX = false, lastY = false, minVal, pcolor, scolor, sdata = isStacked ? series.data : (xData || rawData), closestLeft = { x: Number.MAX_VALUE, y: 0 }, closestRight = { x: -Number.MAX_VALUE, y: 0 }, + // + skipped = 0, hadPoints = false, + // + cullXThreshold = 1, cullYThreshold = 1, + // The following are used in the builder while loop + x, y, d, z, i = -1, px = false, nx = false, low, chartDestroyed = typeof chart.index === 'undefined', nextInside = false, prevInside = false, pcolor = false, drawAsBar = asBar[series.type], isXInside = false, isYInside = true, firstPoint = true, zones = options.zones || false, zoneDefColor = false, threshold = options.threshold, gapSize = false; + if (options.boostData && options.boostData.length > 0) { + return; + } + if (options.gapSize) { + gapSize = options.gapUnit !== 'value' ? + options.gapSize * series.closestPointRange : + options.gapSize; + } + if (zones) { + zones.some(function (zone) { + if (typeof zone.value === 'undefined') { + zoneDefColor = new Color(zone.color); + return true; + } + return false; + }); + if (!zoneDefColor) { + zoneDefColor = ((series.pointAttribs && series.pointAttribs().fill) || + series.color); + zoneDefColor = new Color(zoneDefColor); + } + } + if (chart.inverted) { + // plotHeight = series.chart.plotWidth; + plotWidth = series.chart.plotHeight; + } + series.closestPointRangePx = Number.MAX_VALUE; + /** + * Push color to color buffer - need to do this per vertex. + * @private + */ + function pushColor(color) { + if (color) { + inst.colorData.push(color[0]); + inst.colorData.push(color[1]); + inst.colorData.push(color[2]); + inst.colorData.push(color[3]); + } + } + /** + * Push a vertice to the data buffer. + * @private + */ + function vertice(x, y, checkTreshold, pointSize, color) { + pushColor(color); + if (settings.usePreallocated) { + vbuffer.push(x, y, checkTreshold ? 1 : 0, pointSize || 1); + } + else { + data.push(x); + data.push(y); + data.push(checkTreshold ? 1 : 0); + data.push(pointSize || 1); + } + } + /** + * @private + */ + function closeSegment() { + if (inst.segments.length) { + inst.segments[inst.segments.length - 1].to = data.length; + } + } + /** + * Create a new segment for the current set. + * @private + */ + function beginSegment() { + // Insert a segment on the series. + // A segment is just a start indice. + // When adding a segment, if one exists from before, it should + // set the previous segment's end + if (inst.segments.length && + inst.segments[inst.segments.length - 1].from === data.length) { + return; + } + closeSegment(); + inst.segments.push({ + from: data.length + }); + } + /** + * Push a rectangle to the data buffer. + * @private + */ + function pushRect(x, y, w, h, color) { + pushColor(color); + vertice(x + w, y); + pushColor(color); + vertice(x, y); + pushColor(color); + vertice(x, y + h); + pushColor(color); + vertice(x, y + h); + pushColor(color); + vertice(x + w, y + h); + pushColor(color); + vertice(x + w, y); + } + // Create the first segment + beginSegment(); + // Special case for point shapes + if (points && points.length > 0) { + // If we're doing points, we assume that the points are already + // translated, so we skip the shader translation. + inst.skipTranslation = true; + // Force triangle draw mode + inst.drawMode = 'triangles'; + // We don't have a z component in the shader, so we need to sort. + if (points[0].node && points[0].node.levelDynamic) { + points.sort(function (a, b) { + if (a.node) { + if (a.node.levelDynamic > + b.node.levelDynamic) { + return 1; + } + if (a.node.levelDynamic < + b.node.levelDynamic) { + return -1; + } + } + return 0; + }); + } + points.forEach(function (point) { + var plotY = point.plotY, + shapeArgs, + swidth, + pointAttr; + if (typeof plotY !== 'undefined' && + !isNaN(plotY) && + point.y !== null) { + shapeArgs = point.shapeArgs; + pointAttr = chart.styledMode ? + point.series + .colorAttribs(point) : + pointAttr = point.series.pointAttribs(point); + swidth = pointAttr['stroke-width'] || 0; + // Handle point colors + pcolor = color(pointAttr.fill).rgba; + pcolor[0] /= 255.0; + pcolor[1] /= 255.0; + pcolor[2] /= 255.0; + // So there are two ways of doing this. Either we can + // create a rectangle of two triangles, or we can do a + // point and use point size. Latter is faster, but + // only supports squares. So we're doing triangles. + // We could also use one color per. vertice to get + // better color interpolation. + // If there's stroking, we do an additional rect + if (series.type === 'treemap') { + swidth = swidth || 1; + scolor = color(pointAttr.stroke).rgba; + scolor[0] /= 255.0; + scolor[1] /= 255.0; + scolor[2] /= 255.0; + pushRect(shapeArgs.x, shapeArgs.y, shapeArgs.width, shapeArgs.height, scolor); + swidth /= 2; + } + // } else { + // swidth = 0; + // } + // Fixes issues with inverted heatmaps (see #6981) + // The root cause is that the coordinate system is flipped. + // In other words, instead of [0,0] being top-left, it's + // bottom-right. This causes a vertical and horizontal flip + // in the resulting image, making it rotated 180 degrees. + if (series.type === 'heatmap' && chart.inverted) { + shapeArgs.x = xAxis.len - shapeArgs.x; + shapeArgs.y = yAxis.len - shapeArgs.y; + shapeArgs.width = -shapeArgs.width; + shapeArgs.height = -shapeArgs.height; + } + pushRect(shapeArgs.x + swidth, shapeArgs.y + swidth, shapeArgs.width - (swidth * 2), shapeArgs.height - (swidth * 2), pcolor); + } + }); + closeSegment(); + return; + } + // Extract color axis + // (chart.axes || []).forEach(function (a) { + // if (H.ColorAxis && a instanceof H.ColorAxis) { + // caxis = a; + // } + // }); + while (i < sdata.length - 1) { + d = sdata[++i]; + // px = x = y = z = nx = low = false; + // chartDestroyed = typeof chart.index === 'undefined'; + // nextInside = prevInside = pcolor = isXInside = isYInside = false; + // drawAsBar = asBar[series.type]; + if (chartDestroyed) { + break; + } + // Uncomment this to enable color by point. + // This currently left disabled as the charts look really ugly + // when enabled and there's a lot of points. + // Leaving in for the future (tm). + // if (colorByPoint) { + // colorIndex = ++colorIndex % + // series.chart.options.colors.length; + // pcolor = toRGBAFast(series.chart.options.colors[colorIndex]); + // pcolor[0] /= 255.0; + // pcolor[1] /= 255.0; + // pcolor[2] /= 255.0; + // } + // Handle the point.color option (#5999) + var pointOptions = rawData && rawData[i]; + if (!useRaw && isObject(pointOptions, true)) { + if (pointOptions.color) { + pcolor = color(pointOptions.color).rgba; + pcolor[0] /= 255.0; + pcolor[1] /= 255.0; + pcolor[2] /= 255.0; + } + } + if (useRaw) { + x = d[0]; + y = d[1]; + if (sdata[i + 1]) { + nx = sdata[i + 1][0]; + } + if (sdata[i - 1]) { + px = sdata[i - 1][0]; + } + if (d.length >= 3) { + z = d[2]; + if (d[2] > inst.zMax) { + inst.zMax = d[2]; + } + if (d[2] < inst.zMin) { + inst.zMin = d[2]; + } + } + } + else { + x = d; + y = yData[i]; + if (sdata[i + 1]) { + nx = sdata[i + 1]; + } + if (sdata[i - 1]) { + px = sdata[i - 1]; + } + if (zData && zData.length) { + z = zData[i]; + if (zData[i] > inst.zMax) { + inst.zMax = zData[i]; + } + if (zData[i] < inst.zMin) { + inst.zMin = zData[i]; + } + } + } + if (!connectNulls && (x === null || y === null)) { + beginSegment(); + continue; + } + if (nx && nx >= xMin && nx <= xMax) { + nextInside = true; + } + if (px && px >= xMin && px <= xMax) { + prevInside = true; + } + if (isRange) { + if (useRaw) { + y = d.slice(1, 3); + } + low = y[0]; + y = y[1]; + } + else if (isStacked) { + x = d.x; + y = d.stackY; + low = y - d.y; + } + if (yMin !== null && + typeof yMin !== 'undefined' && + yMax !== null && + typeof yMax !== 'undefined') { + isYInside = y >= yMin && y <= yMax; + } + if (x > xMax && closestRight.x < xMax) { + closestRight.x = x; + closestRight.y = y; + } + if (x < xMin && closestLeft.x > xMin) { + closestLeft.x = x; + closestLeft.y = y; + } + if (y === null && connectNulls) { + continue; + } + // Cull points outside the extremes + if (y === null || (!isYInside && !nextInside && !prevInside)) { + beginSegment(); + continue; + } + // The first point before and first after extremes should be + // rendered (#9962) + if ((nx >= xMin || x >= xMin) && + (px <= xMax || x <= xMax)) { + isXInside = true; + } + if (!isXInside && !nextInside && !prevInside) { + continue; + } + if (gapSize && x - px > gapSize) { + beginSegment(); + } + // Note: Boost requires that zones are sorted! + if (zones) { + pcolor = zoneDefColor.rgba; + zones.some(function (// eslint-disable-line no-loop-func + zone, i) { + var last = zones[i - 1]; + if (typeof zone.value !== 'undefined' && y <= zone.value) { + if (!last || y >= last.value) { + pcolor = color(zone.color).rgba; + } + return true; + } + return false; + }); + pcolor[0] /= 255.0; + pcolor[1] /= 255.0; + pcolor[2] /= 255.0; + } + // Skip translations - temporary floating point fix + if (!settings.useGPUTranslations) { + inst.skipTranslation = true; + x = xAxis.toPixels(x, true); + y = yAxis.toPixels(y, true); + // Make sure we're not drawing outside of the chart area. + // See #6594. Update: this is no longer required as far as I + // can tell. Leaving in for git blame in case there are edge + // cases I've not found. Having this in breaks #10246. + // if (y > plotHeight) { + // y = plotHeight; + // } + if (x > plotWidth) { + // If this is rendered as a point, just skip drawing it + // entirely, as we're not dependandt on lineTo'ing to it. + // See #8197 + if (inst.drawMode === 'points') { + continue; + } + // Having this here will clamp markers and make the angle + // of the last line wrong. See 9166. + // x = plotWidth; + } + } + if (drawAsBar) { + // maxVal = y; + minVal = low; + if (low === false || typeof low === 'undefined') { + if (y < 0) { + minVal = y; + } + else { + minVal = 0; + } + } + if (!isRange && !isStacked) { + minVal = Math.max(threshold === null ? yMin : threshold, // #5268 + yMin); // #8731 + } + if (!settings.useGPUTranslations) { + minVal = yAxis.toPixels(minVal, true); + } + // Need to add an extra point here + vertice(x, minVal, 0, 0, pcolor); + } + // No markers on out of bounds things. + // Out of bound things are shown if and only if the next + // or previous point is inside the rect. + if (inst.hasMarkers && isXInside) { + // x = Highcharts.correctFloat( + // Math.min(Math.max(-1e5, xAxis.translate( + // x, + // 0, + // 0, + // 0, + // 1, + // 0.5, + // false + // )), 1e5) + // ); + if (lastX !== false) { + series.closestPointRangePx = Math.min(series.closestPointRangePx, Math.abs(x - lastX)); + } + } + // If the last _drawn_ point is closer to this point than the + // threshold, skip it. Shaves off 20-100ms in processing. + if (!settings.useGPUTranslations && + !settings.usePreallocated && + (lastX && Math.abs(x - lastX) < cullXThreshold) && + (lastY && Math.abs(y - lastY) < cullYThreshold)) { + if (settings.debug.showSkipSummary) { + ++skipped; + } + continue; + } + // Do step line if enabled. + // Draws an additional point at the old Y at the new X. + // See #6976. + if (options.step && !firstPoint) { + vertice(x, lastY, 0, 2, pcolor); + } + vertice(x, y, 0, series.type === 'bubble' ? (z || 1) : 2, pcolor); + // Uncomment this to support color axis. + // if (caxis) { + // pcolor = color(caxis.toColor(y)).rgba; + // inst.colorData.push(color[0] / 255.0); + // inst.colorData.push(color[1] / 255.0); + // inst.colorData.push(color[2] / 255.0); + // inst.colorData.push(color[3]); + // } + lastX = x; + lastY = y; + hadPoints = true; + firstPoint = false; + } + if (settings.debug.showSkipSummary) { + console.log('skipped points:', skipped); // eslint-disable-line no-console + } + /** + * @private + */ + function pushSupplementPoint(point, atStart) { + if (!settings.useGPUTranslations) { + inst.skipTranslation = true; + point.x = xAxis.toPixels(point.x, true); + point.y = yAxis.toPixels(point.y, true); + } + // We should only do this for lines, and we should ignore markers + // since there's no point here that would have a marker. + if (atStart) { + data = [point.x, point.y, 0, 2].concat(data); + return; + } + vertice(point.x, point.y, 0, 2); + } + if (!hadPoints && + connectNulls !== false && + series.drawMode === 'line_strip') { + if (closestLeft.x < Number.MAX_VALUE) { + // We actually need to push this *before* the complete buffer. + pushSupplementPoint(closestLeft, true); + } + if (closestRight.x > -Number.MAX_VALUE) { + pushSupplementPoint(closestRight); + } + } + closeSegment(); + } + /** + * Push a series to the renderer + * If we render the series immediatly, we don't have to loop later + * @private + * @param s {Highchart.Series} - the series to push + */ + function pushSeries(s) { + if (series.length > 0) { + // series[series.length - 1].to = data.length; + if (series[series.length - 1].hasMarkers) { + series[series.length - 1].markerTo = markerData.length; + } + } + if (settings.debug.timeSeriesProcessing) { + console.time('building ' + s.type + ' series'); // eslint-disable-line no-console + } + series.push({ + segments: [], + // from: data.length, + markerFrom: markerData.length, + // Push RGBA values to this array to use per. point coloring. + // It should be 0-padded, so each component should be pushed in + // succession. + colorData: [], + series: s, + zMin: Number.MAX_VALUE, + zMax: -Number.MAX_VALUE, + hasMarkers: s.options.marker ? + s.options.marker.enabled !== false : + false, + showMarkers: true, + drawMode: { + 'area': 'lines', + 'arearange': 'lines', + 'areaspline': 'line_strip', + 'column': 'lines', + 'columnrange': 'lines', + 'bar': 'lines', + 'line': 'line_strip', + 'scatter': 'points', + 'heatmap': 'triangles', + 'treemap': 'triangles', + 'bubble': 'points' + }[s.type] || 'line_strip' + }); + // Add the series data to our buffer(s) + pushSeriesData(s, series[series.length - 1]); + if (settings.debug.timeSeriesProcessing) { + console.timeEnd('building ' + s.type + ' series'); // eslint-disable-line no-console + } + } + /** + * Flush the renderer. + * This removes pushed series and vertices. + * Should be called after clearing and before rendering + * @private + */ + function flush() { + series = []; + exports.data = data = []; + markerData = []; + if (vbuffer) { + vbuffer.destroy(); + } + } + /** + * Pass x-axis to shader + * @private + * @param axis {Highcharts.Axis} - the x-axis + */ + function setXAxis(axis) { + if (!shader) { + return; + } + shader.setUniform('xAxisTrans', axis.transA); + shader.setUniform('xAxisMin', axis.min); + shader.setUniform('xAxisMinPad', axis.minPixelPadding); + shader.setUniform('xAxisPointRange', axis.pointRange); + shader.setUniform('xAxisLen', axis.len); + shader.setUniform('xAxisPos', axis.pos); + shader.setUniform('xAxisCVSCoord', (!axis.horiz)); + shader.setUniform('xAxisIsLog', (!!axis.logarithmic)); + shader.setUniform('xAxisReversed', (!!axis.reversed)); + } + /** + * Pass y-axis to shader + * @private + * @param axis {Highcharts.Axis} - the y-axis + */ + function setYAxis(axis) { + if (!shader) { + return; + } + shader.setUniform('yAxisTrans', axis.transA); + shader.setUniform('yAxisMin', axis.min); + shader.setUniform('yAxisMinPad', axis.minPixelPadding); + shader.setUniform('yAxisPointRange', axis.pointRange); + shader.setUniform('yAxisLen', axis.len); + shader.setUniform('yAxisPos', axis.pos); + shader.setUniform('yAxisCVSCoord', (!axis.horiz)); + shader.setUniform('yAxisIsLog', (!!axis.logarithmic)); + shader.setUniform('yAxisReversed', (!!axis.reversed)); + } + /** + * Set the translation threshold + * @private + * @param has {boolean} - has threshold flag + * @param translation {Float} - the threshold + */ + function setThreshold(has, translation) { + shader.setUniform('hasThreshold', has); + shader.setUniform('translatedThreshold', translation); + } + /** + * Render the data + * This renders all pushed series. + * @private + */ + function render(chart) { + if (chart) { + if (!chart.chartHeight || !chart.chartWidth) { + // chart.setChartSize(); + } + width = chart.chartWidth || 800; + height = chart.chartHeight || 400; + } + else { + return false; + } + if (!gl || !width || !height || !shader) { + return false; + } + if (settings.debug.timeRendering) { + console.time('gl rendering'); // eslint-disable-line no-console + } + gl.canvas.width = width; + gl.canvas.height = height; + shader.bind(); + gl.viewport(0, 0, width, height); + shader.setPMatrix(orthoMatrix(width, height)); + if (settings.lineWidth > 1 && !H.isMS) { + gl.lineWidth(settings.lineWidth); + } + vbuffer.build(exports.data, 'aVertexPosition', 4); + vbuffer.bind(); + shader.setInverted(chart.inverted); + // Render the series + series.forEach(function (s, si) { + var options = s.series.options, + shapeOptions = options.marker, + sindex, + lineWidth = (typeof options.lineWidth !== 'undefined' ? + options.lineWidth : + 1), + threshold = options.threshold, + hasThreshold = isNumber(threshold), + yBottom = s.series.yAxis.getThreshold(threshold), + translatedThreshold = yBottom, + cbuffer, + showMarkers = pick(options.marker ? options.marker.enabled : null, + s.series.xAxis.isRadial ? true : null, + s.series.closestPointRangePx > + 2 * ((options.marker ? + options.marker.radius : + 10) || 10)), + fillColor, + shapeTexture = textureHandles[(shapeOptions && shapeOptions.symbol) || + s.series.symbol] || textureHandles.circle, + scolor = []; + if (s.segments.length === 0 || + (s.segmentslength && + s.segments[0].from === s.segments[0].to)) { + return; + } + if (shapeTexture.isReady) { + gl.bindTexture(gl.TEXTURE_2D, shapeTexture.handle); + shader.setTexture(shapeTexture.handle); + } + if (chart.styledMode) { + fillColor = (s.series.markerGroup && + s.series.markerGroup.getStyle('fill')); + } + else { + fillColor = + (s.series.pointAttribs && s.series.pointAttribs().fill) || + s.series.color; + if (options.colorByPoint) { + fillColor = s.series.chart.options.colors[si]; + } + } + if (s.series.fillOpacity && options.fillOpacity) { + fillColor = new Color(fillColor).setOpacity(pick(options.fillOpacity, 1.0)).get(); + } + scolor = color(fillColor).rgba; + if (!settings.useAlpha) { + scolor[3] = 1.0; + } + // This is very much temporary + if (s.drawMode === 'lines' && + settings.useAlpha && + scolor[3] < 1) { + scolor[3] /= 10; + } + // Blending + if (options.boostBlending === 'add') { + gl.blendFunc(gl.SRC_ALPHA, gl.ONE); + gl.blendEquation(gl.FUNC_ADD); + } + else if (options.boostBlending === 'mult' || + options.boostBlending === 'multiply') { + gl.blendFunc(gl.DST_COLOR, gl.ZERO); + } + else if (options.boostBlending === 'darken') { + gl.blendFunc(gl.ONE, gl.ONE); + gl.blendEquation(gl.FUNC_MIN); + } + else { + // gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + // gl.blendEquation(gl.FUNC_ADD); + gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + } + shader.reset(); + // If there are entries in the colorData buffer, build and bind it. + if (s.colorData.length > 0) { + shader.setUniform('hasColor', 1.0); + cbuffer = GLVertexBuffer(gl, shader); // eslint-disable-line new-cap + cbuffer.build(s.colorData, 'aColor', 4); + cbuffer.bind(); + } + // Set series specific uniforms + shader.setColor(scolor); + setXAxis(s.series.xAxis); + setYAxis(s.series.yAxis); + setThreshold(hasThreshold, translatedThreshold); + if (s.drawMode === 'points') { + if (options.marker && isNumber(options.marker.radius)) { + shader.setPointSize(options.marker.radius * 2.0); + } + else { + shader.setPointSize(1); + } + } + // If set to true, the toPixels translations in the shader + // is skipped, i.e it's assumed that the value is a pixel coord. + shader.setSkipTranslation(s.skipTranslation); + if (s.series.type === 'bubble') { + shader.setBubbleUniforms(s.series, s.zMin, s.zMax); + } + shader.setDrawAsCircle(asCircle[s.series.type] || false); + // Do the actual rendering + // If the line width is < 0, skip rendering of the lines. See #7833. + if (lineWidth > 0 || s.drawMode !== 'line_strip') { + for (sindex = 0; sindex < s.segments.length; sindex++) { + // if (s.segments[sindex].from < s.segments[sindex].to) { + vbuffer.render(s.segments[sindex].from, s.segments[sindex].to, s.drawMode); + // } + } + } + if (s.hasMarkers && showMarkers) { + if (options.marker && isNumber(options.marker.radius)) { + shader.setPointSize(options.marker.radius * 2.0); + } + else { + shader.setPointSize(10); + } + shader.setDrawAsCircle(true); + for (sindex = 0; sindex < s.segments.length; sindex++) { + // if (s.segments[sindex].from < s.segments[sindex].to) { + vbuffer.render(s.segments[sindex].from, s.segments[sindex].to, 'POINTS'); + // } + } + } + }); + if (settings.debug.timeRendering) { + console.timeEnd('gl rendering'); // eslint-disable-line no-console + } + if (postRenderCallback) { + postRenderCallback(); + } + flush(); + } + /** + * Render the data when ready + * @private + */ + function renderWhenReady(chart) { + clear(); + if (chart.renderer.forExport) { + return render(chart); + } + if (isInited) { + render(chart); + } + else { + setTimeout(function () { + renderWhenReady(chart); + }, 1); + } + } + /** + * Set the viewport size in pixels + * Creates an orthographic perspective matrix and applies it. + * @private + * @param w {Integer} - the width of the viewport + * @param h {Integer} - the height of the viewport + */ + function setSize(w, h) { + // Skip if there's no change, or if we have no valid shader + if ((width === w && height === h) || !shader) { + return; + } + width = w; + height = h; + shader.bind(); + shader.setPMatrix(orthoMatrix(width, height)); + } + /** + * Init OpenGL + * @private + * @param canvas {HTMLCanvas} - the canvas to render to + */ + function init(canvas, noFlush) { + var i = 0, + contexts = [ + 'webgl', + 'experimental-webgl', + 'moz-webgl', + 'webkit-3d' + ]; + isInited = false; + if (!canvas) { + return false; + } + if (settings.debug.timeSetup) { + console.time('gl setup'); // eslint-disable-line no-console + } + for (; i < contexts.length; i++) { + gl = canvas.getContext(contexts[i], { + // premultipliedAlpha: false + }); + if (gl) { + break; + } + } + if (gl) { + if (!noFlush) { + flush(); + } + } + else { + return false; + } + gl.enable(gl.BLEND); + // gl.blendFunc(gl.SRC_ALPHA, gl.ONE); + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + gl.disable(gl.DEPTH_TEST); + // gl.depthMask(gl.FALSE); + gl.depthFunc(gl.LESS); + shader = GLShader(gl); // eslint-disable-line new-cap + if (!shader) { + // We need to abort, there's no shader context + return false; + } + vbuffer = GLVertexBuffer(gl, shader); // eslint-disable-line new-cap + /** + * @private + */ + function createTexture(name, fn) { + var props = { + isReady: false, + texture: doc.createElement('canvas'), + handle: gl.createTexture() + }, + ctx = props.texture.getContext('2d'); + textureHandles[name] = props; + props.texture.width = 512; + props.texture.height = 512; + ctx.mozImageSmoothingEnabled = false; + ctx.webkitImageSmoothingEnabled = false; + ctx.msImageSmoothingEnabled = false; + ctx.imageSmoothingEnabled = false; + ctx.strokeStyle = 'rgba(255, 255, 255, 0)'; + ctx.fillStyle = '#FFF'; + fn(ctx); + try { + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, props.handle); + // gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, props.texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + // gl.generateMipmap(gl.TEXTURE_2D); + gl.bindTexture(gl.TEXTURE_2D, null); + props.isReady = true; + } + catch (e) { + // silent error + } + } + // Circle shape + createTexture('circle', function (ctx) { + ctx.beginPath(); + ctx.arc(256, 256, 256, 0, 2 * Math.PI); + ctx.stroke(); + ctx.fill(); + }); + // Square shape + createTexture('square', function (ctx) { + ctx.fillRect(0, 0, 512, 512); + }); + // Diamond shape + createTexture('diamond', function (ctx) { + ctx.beginPath(); + ctx.moveTo(256, 0); + ctx.lineTo(512, 256); + ctx.lineTo(256, 512); + ctx.lineTo(0, 256); + ctx.lineTo(256, 0); + ctx.fill(); + }); + // Triangle shape + createTexture('triangle', function (ctx) { + ctx.beginPath(); + ctx.moveTo(0, 512); + ctx.lineTo(256, 0); + ctx.lineTo(512, 512); + ctx.lineTo(0, 512); + ctx.fill(); + }); + // Triangle shape (rotated) + createTexture('triangle-down', function (ctx) { + ctx.beginPath(); + ctx.moveTo(0, 0); + ctx.lineTo(256, 512); + ctx.lineTo(512, 0); + ctx.lineTo(0, 0); + ctx.fill(); + }); + isInited = true; + if (settings.debug.timeSetup) { + console.timeEnd('gl setup'); // eslint-disable-line no-console + } + return true; + } + /** + * Check if we have a valid OGL context + * @private + * @returns {Boolean} - true if the context is valid + */ + function valid() { + return gl !== false; + } + /** + * Check if the renderer has been initialized + * @private + * @returns {Boolean} - true if it has, false if not + */ + function inited() { + return isInited; + } + /** + * @private + */ + function destroy() { + flush(); + vbuffer.destroy(); + shader.destroy(); + if (gl) { + objectEach(textureHandles, function (texture) { + if (texture.handle) { + gl.deleteTexture(texture.handle); + } + }); + gl.canvas.width = 1; + gl.canvas.height = 1; + } + } + // ///////////////////////////////////////////////////////////////////////// + exports = { + allocateBufferForSingleSeries: allocateBufferForSingleSeries, + pushSeries: pushSeries, + setSize: setSize, + inited: inited, + setThreshold: setThreshold, + init: init, + render: renderWhenReady, + settings: settings, + valid: valid, + clear: clear, + flush: flush, + setXAxis: setXAxis, + setYAxis: setYAxis, + data: data, + gl: getGL, + allocateBuffer: allocateBuffer, + destroy: destroy, + setOptions: setOptions + }; + return exports; + } + + return GLRenderer; + }); + _registerModule(_modules, 'Extensions/Boost/BoostAttach.js', [_modules['Extensions/Boost/WGLRenderer.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (GLRenderer, H, U) { + /* * + * + * Copyright (c) 2019-2020 Highsoft AS + * + * Boost module: stripped-down renderer for higher performance + * + * License: highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var doc = H.doc; + var error = U.error; + var mainCanvas = doc.createElement('canvas'); + /** + * Create a canvas + context and attach it to the target + * + * @private + * @function createAndAttachRenderer + * + * @param {Highcharts.Chart} chart + * the chart + * + * @param {Highcharts.Series} series + * the series + * + * @return {Highcharts.BoostGLRenderer} + * the canvas renderer + */ + function createAndAttachRenderer(chart, series) { + var width = chart.chartWidth, height = chart.chartHeight, target = chart, targetGroup = chart.seriesGroup || series.group, alpha = 1, foSupported = doc.implementation.hasFeature('www.http://w3.org/TR/SVG11/feature#Extensibility', '1.1'); + if (chart.isChartSeriesBoosting()) { + target = chart; + } + else { + target = series; + } + // Support for foreignObject is flimsy as best. + // IE does not support it, and Chrome has a bug which messes up + // the canvas draw order. + // As such, we force the Image fallback for now, but leaving the + // actual Canvas path in-place in case this changes in the future. + foSupported = false; + if (!target.renderTarget) { + target.canvas = mainCanvas; + // Fall back to image tag if foreignObject isn't supported, + // or if we're exporting. + if (chart.renderer.forExport || !foSupported) { + target.renderTarget = chart.renderer.image('', 0, 0, width, height) + .addClass('highcharts-boost-canvas') + .add(targetGroup); + target.boostClear = function () { + target.renderTarget.attr({ href: '' }); + }; + target.boostCopy = function () { + target.boostResizeTarget(); + target.renderTarget.attr({ + href: target.canvas.toDataURL('image/png') + }); + }; + } + else { + target.renderTargetFo = chart.renderer + .createElement('foreignObject') + .add(targetGroup); + target.renderTarget = doc.createElement('canvas'); + target.renderTargetCtx = + target.renderTarget.getContext('2d'); + target.renderTargetFo.element.appendChild(target.renderTarget); + target.boostClear = function () { + target.renderTarget.width = + target.canvas.width; + target.renderTarget.height = + target.canvas.height; + }; + target.boostCopy = function () { + target.renderTarget.width = + target.canvas.width; + target.renderTarget.height = + target.canvas.height; + target.renderTargetCtx + .drawImage(target.canvas, 0, 0); + }; + } + target.boostResizeTarget = function () { + width = chart.chartWidth; + height = chart.chartHeight; + (target.renderTargetFo || target.renderTarget) + .attr({ + x: 0, + y: 0, + width: width, + height: height + }) + .css({ + pointerEvents: 'none', + mixedBlendMode: 'normal', + opacity: alpha + }); + if (target instanceof H.Chart) { + target.markerGroup.translate(chart.plotLeft, chart.plotTop); + } + }; + target.boostClipRect = chart.renderer.clipRect(); + (target.renderTargetFo || target.renderTarget) + .clip(target.boostClipRect); + if (target instanceof H.Chart) { + target.markerGroup = target.renderer.g().add(targetGroup); + target.markerGroup.translate(series.xAxis.pos, series.yAxis.pos); + } + } + target.canvas.width = width; + target.canvas.height = height; + target.boostClipRect.attr(chart.getBoostClipRect(target)); + target.boostResizeTarget(); + target.boostClear(); + if (!target.ogl) { + target.ogl = GLRenderer(function () { + if (target.ogl.settings.debug.timeBufferCopy) { + console.time('buffer copy'); // eslint-disable-line no-console + } + target.boostCopy(); + if (target.ogl.settings.debug.timeBufferCopy) { + console.timeEnd('buffer copy'); // eslint-disable-line no-console + } + }); + if (!target.ogl.init(target.canvas)) { + // The OGL renderer couldn't be inited. + // This likely means a shader error as we wouldn't get to this point + // if there was no WebGL support. + error('[highcharts boost] - unable to init WebGL renderer'); + } + // target.ogl.clear(); + target.ogl.setOptions(chart.options.boost || {}); + if (target instanceof H.Chart) { + target.ogl.allocateBuffer(chart); + } + } + target.ogl.setSize(width, height); + return target.ogl; + } + + return createAndAttachRenderer; + }); + _registerModule(_modules, 'Extensions/Boost/BoostUtils.js', [_modules['Core/Globals.js'], _modules['Extensions/Boost/BoostableMap.js'], _modules['Extensions/Boost/BoostAttach.js'], _modules['Core/Utilities.js']], function (H, boostableMap, createAndAttachRenderer, U) { + /* * + * + * Copyright (c) 2019-2020 Highsoft AS + * + * Boost module: stripped-down renderer for higher performance + * + * License: highcharts.com/license + * + * This files contains generic utility functions used by the boost module. + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var win = H.win, + doc = H.doc; + var pick = U.pick; + // This should be a const. + var CHUNK_SIZE = 3000; + /** + * Tolerant max() function. + * + * @private + * @function patientMax + * + * @param {...Array>} args + * Max arguments + * + * @return {number} + * Max value + */ + function patientMax() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var r = -Number.MAX_VALUE; + args.forEach(function (t) { + if (typeof t !== 'undefined' && + t !== null && + typeof t.length !== 'undefined') { + // r = r < t.length ? t.length : r; + if (t.length > 0) { + r = t.length; + return true; + } + } + }); + return r; + } + /** + * Return true if ths boost.enabled option is true + * + * @private + * @function boostEnabled + * + * @param {Highcharts.Chart} chart + * The chart + * + * @return {boolean} + * True, if boost is enabled. + */ + function boostEnabled(chart) { + return pick((chart && + chart.options && + chart.options.boost && + chart.options.boost.enabled), true); + } + /** + * Returns true if we should force boosting the chart + * @private + * @function shouldForceChartSeriesBoosting + * + * @param {Highcharts.Chart} chart + * The chart to check for forcing on + * + * @return {boolean} + * True, if boosting should be forced. + */ + function shouldForceChartSeriesBoosting(chart) { + // If there are more than five series currently boosting, + // we should boost the whole chart to avoid running out of webgl contexts. + var sboostCount = 0, + canBoostCount = 0, + allowBoostForce = pick(chart.options.boost && chart.options.boost.allowForce, + true), + series; + if (typeof chart.boostForceChartBoost !== 'undefined') { + return chart.boostForceChartBoost; + } + if (chart.series.length > 1) { + for (var i = 0; i < chart.series.length; i++) { + series = chart.series[i]; + // Don't count series with boostThreshold set to 0 + // See #8950 + // Also don't count if the series is hidden. + // See #9046 + if (series.options.boostThreshold === 0 || + series.visible === false) { + continue; + } + // Don't count heatmap series as they are handled differently. + // In the future we should make the heatmap/treemap path compatible + // with forcing. See #9636. + if (series.type === 'heatmap') { + continue; + } + if (boostableMap[series.type]) { + ++canBoostCount; + } + if (patientMax(series.processedXData, series.options.data, + // series.xData, + series.points) >= (series.options.boostThreshold || Number.MAX_VALUE)) { + ++sboostCount; + } + } + } + chart.boostForceChartBoost = allowBoostForce && ((canBoostCount === chart.series.length && + sboostCount > 0) || + sboostCount > 5); + return chart.boostForceChartBoost; + } + /* eslint-disable valid-jsdoc */ + /** + * Performs the actual render if the renderer is + * attached to the series. + * @private + * @param renderer {OGLRenderer} - the renderer + * @param series {Highcharts.Series} - the series + */ + function renderIfNotSeriesBoosting(renderer, series, chart) { + if (renderer && + series.renderTarget && + series.canvas && + !(chart || series.chart).isChartSeriesBoosting()) { + renderer.render(chart || series.chart); + } + } + /** + * @private + */ + function allocateIfNotSeriesBoosting(renderer, series) { + if (renderer && + series.renderTarget && + series.canvas && + !series.chart.isChartSeriesBoosting()) { + renderer.allocateBufferForSingleSeries(series); + } + } + /** + * An "async" foreach loop. Uses a setTimeout to keep the loop from blocking the + * UI thread. + * + * @private + * + * @param arr {Array} - the array to loop through + * @param fn {Function} - the callback to call for each item + * @param finalFunc {Function} - the callback to call when done + * @param chunkSize {Number} - the number of iterations per timeout + * @param i {Number} - the current index + * @param noTimeout {Boolean} - set to true to skip timeouts + */ + function eachAsync(arr, fn, finalFunc, chunkSize, i, noTimeout) { + i = i || 0; + chunkSize = chunkSize || CHUNK_SIZE; + var threshold = i + chunkSize, + proceed = true; + while (proceed && i < threshold && i < arr.length) { + proceed = fn(arr[i], i); + ++i; + } + if (proceed) { + if (i < arr.length) { + if (noTimeout) { + eachAsync(arr, fn, finalFunc, chunkSize, i, noTimeout); + } + else if (win.requestAnimationFrame) { + // If available, do requestAnimationFrame - shaves off a few ms + win.requestAnimationFrame(function () { + eachAsync(arr, fn, finalFunc, chunkSize, i); + }); + } + else { + setTimeout(function () { + eachAsync(arr, fn, finalFunc, chunkSize, i); + }); + } + } + else if (finalFunc) { + finalFunc(); + } + } + } + /** + * Returns true if the current browser supports webgl + * + * @private + * @function hasWebGLSupport + * + * @return {boolean} + */ + function hasWebGLSupport() { + var i = 0, canvas, contexts = ['webgl', 'experimental-webgl', 'moz-webgl', 'webkit-3d'], context = false; + if (typeof win.WebGLRenderingContext !== 'undefined') { + canvas = doc.createElement('canvas'); + for (; i < contexts.length; i++) { + try { + context = canvas.getContext(contexts[i]); + if (typeof context !== 'undefined' && context !== null) { + return true; + } + } + catch (e) { + // silent error + } + } + } + return false; + } + /* eslint-disable no-invalid-this */ + /** + * Used for treemap|heatmap.drawPoints + * + * @private + * @function pointDrawHandler + * + * @param {Function} proceed + * + * @return {*} + */ + function pointDrawHandler(proceed) { + var enabled = true, + renderer; + if (this.chart.options && this.chart.options.boost) { + enabled = typeof this.chart.options.boost.enabled === 'undefined' ? + true : + this.chart.options.boost.enabled; + } + if (!enabled || !this.isSeriesBoosting) { + return proceed.call(this); + } + this.chart.isBoosting = true; + // Make sure we have a valid OGL context + renderer = createAndAttachRenderer(this.chart, this); + if (renderer) { + allocateIfNotSeriesBoosting(renderer, this); + renderer.pushSeries(this); + } + renderIfNotSeriesBoosting(renderer, this); + } + /* eslint-enable no-invalid-this, valid-jsdoc */ + var funs = { + patientMax: patientMax, + boostEnabled: boostEnabled, + shouldForceChartSeriesBoosting: shouldForceChartSeriesBoosting, + renderIfNotSeriesBoosting: renderIfNotSeriesBoosting, + allocateIfNotSeriesBoosting: allocateIfNotSeriesBoosting, + eachAsync: eachAsync, + hasWebGLSupport: hasWebGLSupport, + pointDrawHandler: pointDrawHandler + }; + // This needs to be fixed. + H.hasWebGLSupport = hasWebGLSupport; + + return funs; + }); + _registerModule(_modules, 'Extensions/Boost/BoostInit.js', [_modules['Core/Chart/Chart.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js'], _modules['Extensions/Boost/BoostUtils.js'], _modules['Extensions/Boost/BoostAttach.js']], function (Chart, H, U, butils, createAndAttachRenderer) { + /* * + * + * Copyright (c) 2019-2020 Highsoft AS + * + * Boost module: stripped-down renderer for higher performance + * + * License: highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + extend = U.extend, + fireEvent = U.fireEvent, + wrap = U.wrap; + var Series = H.Series, + seriesTypes = H.seriesTypes, + noop = function () { }, + eachAsync = butils.eachAsync, + pointDrawHandler = butils.pointDrawHandler, + allocateIfNotSeriesBoosting = butils.allocateIfNotSeriesBoosting, + renderIfNotSeriesBoosting = butils.renderIfNotSeriesBoosting, + shouldForceChartSeriesBoosting = butils.shouldForceChartSeriesBoosting, + index; + /* eslint-disable valid-jsdoc */ + /** + * Initialize the boot module. + * + * @private + * @return {void} + */ + function init() { + extend(Series.prototype, { + /** + * @private + * @function Highcharts.Series#renderCanvas + */ + renderCanvas: function () { + var series = this, options = series.options || {}, renderer = false, chart = series.chart, xAxis = this.xAxis, yAxis = this.yAxis, xData = options.xData || series.processedXData, yData = options.yData || series.processedYData, rawData = options.data, xExtremes = xAxis.getExtremes(), xMin = xExtremes.min, xMax = xExtremes.max, yExtremes = yAxis.getExtremes(), yMin = yExtremes.min, yMax = yExtremes.max, pointTaken = {}, lastClientX, sampling = !!series.sampling, points, enableMouseTracking = options.enableMouseTracking !== false, threshold = options.threshold, yBottom = yAxis.getThreshold(threshold), isRange = series.pointArrayMap && + series.pointArrayMap.join(',') === 'low,high', isStacked = !!options.stacking, cropStart = series.cropStart || 0, requireSorting = series.requireSorting, useRaw = !xData, minVal, maxVal, minI, maxI, boostOptions, compareX = options.findNearestPointBy === 'x', xDataFull = (this.xData || + this.options.xData || + this.processedXData || + false), addKDPoint = function (clientX, plotY, i) { + // We need to do ceil on the clientX to make things + // snap to pixel values. The renderer will frequently + // draw stuff on "sub-pixels". + clientX = Math.ceil(clientX); + // Shaves off about 60ms compared to repeated concatenation + index = compareX ? clientX : clientX + ',' + plotY; + // The k-d tree requires series points. + // Reduce the amount of points, since the time to build the + // tree increases exponentially. + if (enableMouseTracking && !pointTaken[index]) { + pointTaken[index] = true; + if (chart.inverted) { + clientX = xAxis.len - clientX; + plotY = yAxis.len - plotY; + } + points.push({ + x: xDataFull ? xDataFull[cropStart + i] : false, + clientX: clientX, + plotX: clientX, + plotY: plotY, + i: cropStart + i + }); + } + }; + // Get or create the renderer + renderer = createAndAttachRenderer(chart, series); + chart.isBoosting = true; + boostOptions = renderer.settings; + if (!this.visible) { + return; + } + // If we are zooming out from SVG mode, destroy the graphics + if (this.points || this.graph) { + this.destroyGraphics(); + } + // If we're rendering per. series we should create the marker groups + // as usual. + if (!chart.isChartSeriesBoosting()) { + // If all series were boosting, but are not anymore + // restore private markerGroup + if (this.markerGroup === chart.markerGroup) { + this.markerGroup = void 0; + } + this.markerGroup = series.plotGroup('markerGroup', 'markers', true, 1, chart.seriesGroup); + } + else { + // If series has a private markeGroup, remove that + // and use common markerGroup + if (this.markerGroup && + this.markerGroup !== chart.markerGroup) { + this.markerGroup.destroy(); + } + // Use a single group for the markers + this.markerGroup = chart.markerGroup; + // When switching from chart boosting mode, destroy redundant + // series boosting targets + if (this.renderTarget) { + this.renderTarget = this.renderTarget.destroy(); + } + } + points = this.points = []; + // Do not start building while drawing + series.buildKDTree = noop; + if (renderer) { + allocateIfNotSeriesBoosting(renderer, this); + renderer.pushSeries(series); + // Perform the actual renderer if we're on series level + renderIfNotSeriesBoosting(renderer, this, chart); + } + /** + * This builds the KD-tree + * @private + */ + function processPoint(d, i) { + var x, + y, + clientX, + plotY, + isNull, + low = false, + chartDestroyed = typeof chart.index === 'undefined', + isYInside = true; + if (!chartDestroyed) { + if (useRaw) { + x = d[0]; + y = d[1]; + } + else { + x = d; + y = yData[i]; + } + // Resolve low and high for range series + if (isRange) { + if (useRaw) { + y = d.slice(1, 3); + } + low = y[0]; + y = y[1]; + } + else if (isStacked) { + x = d.x; + y = d.stackY; + low = y - d.y; + } + isNull = y === null; + // Optimize for scatter zooming + if (!requireSorting) { + isYInside = y >= yMin && y <= yMax; + } + if (!isNull && x >= xMin && x <= xMax && isYInside) { + clientX = xAxis.toPixels(x, true); + if (sampling) { + if (typeof minI === 'undefined' || + clientX === lastClientX) { + if (!isRange) { + low = y; + } + if (typeof maxI === 'undefined' || + y > maxVal) { + maxVal = y; + maxI = i; + } + if (typeof minI === 'undefined' || + low < minVal) { + minVal = low; + minI = i; + } + } + // Add points and reset + if (clientX !== lastClientX) { + // maxI is number too: + if (typeof minI !== 'undefined') { + plotY = + yAxis.toPixels(maxVal, true); + yBottom = + yAxis.toPixels(minVal, true); + addKDPoint(clientX, plotY, maxI); + if (yBottom !== plotY) { + addKDPoint(clientX, yBottom, minI); + } + } + minI = maxI = void 0; + lastClientX = clientX; + } + } + else { + plotY = Math.ceil(yAxis.toPixels(y, true)); + addKDPoint(clientX, plotY, i); + } + } + } + return !chartDestroyed; + } + /** + * @private + */ + function doneProcessing() { + fireEvent(series, 'renderedCanvas'); + // Go back to prototype, ready to build + delete series.buildKDTree; + series.buildKDTree(); + if (boostOptions.debug.timeKDTree) { + console.timeEnd('kd tree building'); // eslint-disable-line no-console + } + } + // Loop over the points to build the k-d tree - skip this if + // exporting + if (!chart.renderer.forExport) { + if (boostOptions.debug.timeKDTree) { + console.time('kd tree building'); // eslint-disable-line no-console + } + eachAsync(isStacked ? series.data : (xData || rawData), processPoint, doneProcessing); + } + } + }); + /* + * We need to handle heatmaps separatly, since we can't perform the + * size/color calculations in the shader easily. + * + * This likely needs future optimization. + */ + ['heatmap', 'treemap'].forEach(function (t) { + if (seriesTypes[t]) { + wrap(seriesTypes[t].prototype, 'drawPoints', pointDrawHandler); + } + }); + /* eslint-disable no-invalid-this */ + if (seriesTypes.bubble) { + // By default, the bubble series does not use the KD-tree, so force it + // to. + delete seriesTypes.bubble.prototype.buildKDTree; + // seriesTypes.bubble.prototype.directTouch = false; + // Needed for markers to work correctly + wrap(seriesTypes.bubble.prototype, 'markerAttribs', function (proceed) { + if (this.isSeriesBoosting) { + return false; + } + return proceed.apply(this, [].slice.call(arguments, 1)); + }); + } + seriesTypes.scatter.prototype.fill = true; + extend(seriesTypes.area.prototype, { + fill: true, + fillOpacity: true, + sampling: true + }); + extend(seriesTypes.column.prototype, { + fill: true, + sampling: true + }); + // Take care of the canvas blitting + Chart.prototype.callbacks.push(function (chart) { + /** + * Convert chart-level canvas to image. + * @private + */ + function canvasToSVG() { + if (chart.ogl && chart.isChartSeriesBoosting()) { + chart.ogl.render(chart); + } + } + /** + * Clear chart-level canvas. + * @private + */ + function preRender() { + // Reset force state + chart.boostForceChartBoost = void 0; + chart.boostForceChartBoost = shouldForceChartSeriesBoosting(chart); + chart.isBoosting = false; + if (!chart.isChartSeriesBoosting() && chart.didBoost) { + chart.didBoost = false; + } + // Clear the canvas + if (chart.boostClear) { + chart.boostClear(); + } + if (chart.canvas && chart.ogl && chart.isChartSeriesBoosting()) { + chart.didBoost = true; + // Allocate + chart.ogl.allocateBuffer(chart); + } + // see #6518 + #6739 + if (chart.markerGroup && + chart.xAxis && + chart.xAxis.length > 0 && + chart.yAxis && + chart.yAxis.length > 0) { + chart.markerGroup.translate(chart.xAxis[0].pos, chart.yAxis[0].pos); + } + } + addEvent(chart, 'predraw', preRender); + addEvent(chart, 'render', canvasToSVG); + // addEvent(chart, 'zoom', function () { + // chart.boostForceChartBoost = + // shouldForceChartSeriesBoosting(chart); + // }); + }); + /* eslint-enable no-invalid-this */ + } + + return init; + }); + _registerModule(_modules, 'Extensions/Boost/BoostOverrides.js', [_modules['Core/Chart/Chart.js'], _modules['Core/Globals.js'], _modules['Core/Series/Point.js'], _modules['Core/Utilities.js'], _modules['Extensions/Boost/BoostUtils.js'], _modules['Extensions/Boost/Boostables.js'], _modules['Extensions/Boost/BoostableMap.js']], function (Chart, H, Point, U, butils, boostable, boostableMap) { + /* * + * + * Copyright (c) 2019-2020 Highsoft AS + * + * Boost module: stripped-down renderer for higher performance + * + * License: highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + error = U.error, + getOptions = U.getOptions, + isArray = U.isArray, + isNumber = U.isNumber, + pick = U.pick, + wrap = U.wrap; + var boostEnabled = butils.boostEnabled, + shouldForceChartSeriesBoosting = butils.shouldForceChartSeriesBoosting, + Series = H.Series, + seriesTypes = H.seriesTypes, + plotOptions = getOptions().plotOptions; + /** + * Returns true if the chart is in series boost mode. + * + * @function Highcharts.Chart#isChartSeriesBoosting + * + * @param {Highcharts.Chart} chart + * the chart to check + * + * @return {boolean} + * true if the chart is in series boost mode + */ + Chart.prototype.isChartSeriesBoosting = function () { + var isSeriesBoosting, + threshold = pick(this.options.boost && this.options.boost.seriesThreshold, 50); + isSeriesBoosting = threshold <= this.series.length || + shouldForceChartSeriesBoosting(this); + return isSeriesBoosting; + }; + /* eslint-disable valid-jsdoc */ + /** + * Get the clip rectangle for a target, either a series or the chart. For the + * chart, we need to consider the maximum extent of its Y axes, in case of + * Highstock panes and navigator. + * + * @private + * @function Highcharts.Chart#getBoostClipRect + * + * @param {Highcharts.Chart} target + * + * @return {Highcharts.BBoxObject} + */ + Chart.prototype.getBoostClipRect = function (target) { + var clipBox = { + x: this.plotLeft, + y: this.plotTop, + width: this.plotWidth, + height: this.plotHeight + }; + if (target === this) { + this.yAxis.forEach(function (yAxis) { + clipBox.y = Math.min(yAxis.pos, clipBox.y); + clipBox.height = Math.max(yAxis.pos - this.plotTop + yAxis.len, clipBox.height); + }, this); + } + return clipBox; + }; + /** + * Return a full Point object based on the index. + * The boost module uses stripped point objects for performance reasons. + * + * @function Highcharts.Series#getPoint + * + * @param {object|Highcharts.Point} boostPoint + * A stripped-down point object + * + * @return {Highcharts.Point} + * A Point object as per https://api.highcharts.com/highcharts#Point + */ + Series.prototype.getPoint = function (boostPoint) { + var point = boostPoint, + xData = (this.xData || this.options.xData || this.processedXData || + false); + if (boostPoint && !(boostPoint instanceof this.pointClass)) { + point = (new this.pointClass()).init(// eslint-disable-line new-cap + this, this.options.data[boostPoint.i], xData ? xData[boostPoint.i] : void 0); + point.category = pick(this.xAxis.categories ? + this.xAxis.categories[point.x] : + point.x, // @todo simplify + point.x); + point.dist = boostPoint.dist; + point.distX = boostPoint.distX; + point.plotX = boostPoint.plotX; + point.plotY = boostPoint.plotY; + point.index = boostPoint.i; + point.isInside = this.isPointInside(boostPoint); + } + return point; + }; + /* eslint-disable no-invalid-this */ + // Return a point instance from the k-d-tree + wrap(Series.prototype, 'searchPoint', function (proceed) { + return this.getPoint(proceed.apply(this, [].slice.call(arguments, 1))); + }); + // For inverted series, we need to swap X-Y values before running base methods + wrap(Point.prototype, 'haloPath', function (proceed) { + var halo, + point = this, + series = point.series, + chart = series.chart, + plotX = point.plotX, + plotY = point.plotY, + inverted = chart.inverted; + if (series.isSeriesBoosting && inverted) { + point.plotX = series.yAxis.len - plotY; + point.plotY = series.xAxis.len - plotX; + } + halo = proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + if (series.isSeriesBoosting && inverted) { + point.plotX = plotX; + point.plotY = plotY; + } + return halo; + }); + wrap(Series.prototype, 'markerAttribs', function (proceed, point) { + var attribs, + series = this, + chart = series.chart, + plotX = point.plotX, + plotY = point.plotY, + inverted = chart.inverted; + if (series.isSeriesBoosting && inverted) { + point.plotX = series.yAxis.len - plotY; + point.plotY = series.xAxis.len - plotX; + } + attribs = proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + if (series.isSeriesBoosting && inverted) { + point.plotX = plotX; + point.plotY = plotY; + } + return attribs; + }); + /* + * Extend series.destroy to also remove the fake k-d-tree points (#5137). + * Normally this is handled by Series.destroy that calls Point.destroy, + * but the fake search points are not registered like that. + */ + addEvent(Series, 'destroy', function () { + var series = this, + chart = series.chart; + if (chart.markerGroup === series.markerGroup) { + series.markerGroup = null; + } + if (chart.hoverPoints) { + chart.hoverPoints = chart.hoverPoints.filter(function (point) { + return point.series === series; + }); + } + if (chart.hoverPoint && chart.hoverPoint.series === series) { + chart.hoverPoint = null; + } + }); + /* + * Do not compute extremes when min and max are set. + * If we use this in the core, we can add the hook + * to hasExtremes to the methods directly. + */ + wrap(Series.prototype, 'getExtremes', function (proceed) { + if (!this.isSeriesBoosting || (!this.hasExtremes || !this.hasExtremes())) { + return proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + } + return {}; + }); + /* + * Override a bunch of methods the same way. If the number of points is + * below the threshold, run the original method. If not, check for a + * canvas version or do nothing. + * + * Note that we're not overriding any of these for heatmaps. + */ + [ + 'translate', + 'generatePoints', + 'drawTracker', + 'drawPoints', + 'render' + ].forEach(function (method) { + /** + * @private + */ + function branch(proceed) { + var letItPass = this.options.stacking && + (method === 'translate' || method === 'generatePoints'); + if (!this.isSeriesBoosting || + letItPass || + !boostEnabled(this.chart) || + this.type === 'heatmap' || + this.type === 'treemap' || + !boostableMap[this.type] || + this.options.boostThreshold === 0) { + proceed.call(this); + // If a canvas version of the method exists, like renderCanvas(), run + } + else if (this[method + 'Canvas']) { + this[method + 'Canvas'](); + } + } + wrap(Series.prototype, method, branch); + // A special case for some types - their translate method is already wrapped + if (method === 'translate') { + [ + 'column', + 'bar', + 'arearange', + 'columnrange', + 'heatmap', + 'treemap' + ].forEach(function (type) { + if (seriesTypes[type]) { + wrap(seriesTypes[type].prototype, method, branch); + } + }); + } + }); + // If the series is a heatmap or treemap, or if the series is not boosting + // do the default behaviour. Otherwise, process if the series has no extremes. + wrap(Series.prototype, 'processData', function (proceed) { + var series = this, + dataToMeasure = this.options.data, + firstPoint; + /** + * Used twice in this function, first on this.options.data, the second + * time it runs the check again after processedXData is built. + * @private + * @todo Check what happens with data grouping + */ + function getSeriesBoosting(data) { + return series.chart.isChartSeriesBoosting() || ((data ? data.length : 0) >= + (series.options.boostThreshold || Number.MAX_VALUE)); + } + if (boostEnabled(this.chart) && boostableMap[this.type]) { + // If there are no extremes given in the options, we also need to + // process the data to read the data extremes. If this is a heatmap, do + // default behaviour. + if (!getSeriesBoosting(dataToMeasure) || // First pass with options.data + this.type === 'heatmap' || + this.type === 'treemap' || + this.options.stacking || // processedYData for the stack (#7481) + !this.hasExtremes || + !this.hasExtremes(true)) { + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + dataToMeasure = this.processedXData; + } + // Set the isBoosting flag, second pass with processedXData to see if we + // have zoomed. + this.isSeriesBoosting = getSeriesBoosting(dataToMeasure); + // Enter or exit boost mode + if (this.isSeriesBoosting) { + // Force turbo-mode: + firstPoint = this.getFirstValidPoint(this.options.data); + if (!isNumber(firstPoint) && !isArray(firstPoint)) { + error(12, false, this.chart); + } + this.enterBoost(); + } + else if (this.exitBoost) { + this.exitBoost(); + } + // The series type is not boostable + } + else { + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + } + }); + addEvent(Series, 'hide', function () { + if (this.canvas && this.renderTarget) { + if (this.ogl) { + this.ogl.clear(); + } + this.boostClear(); + } + }); + /** + * Enter boost mode and apply boost-specific properties. + * + * @function Highcharts.Series#enterBoost + */ + Series.prototype.enterBoost = function () { + this.alteredByBoost = []; + // Save the original values, including whether it was an own property or + // inherited from the prototype. + ['allowDG', 'directTouch', 'stickyTracking'].forEach(function (prop) { + this.alteredByBoost.push({ + prop: prop, + val: this[prop], + own: Object.hasOwnProperty.call(this, prop) + }); + }, this); + this.allowDG = false; + this.directTouch = false; + this.stickyTracking = true; + // Prevent animation when zooming in on boosted series(#13421). + this.finishedAnimating = true; + // Hide series label if any + if (this.labelBySeries) { + this.labelBySeries = this.labelBySeries.destroy(); + } + }; + /** + * Exit from boost mode and restore non-boost properties. + * + * @function Highcharts.Series#exitBoost + */ + Series.prototype.exitBoost = function () { + // Reset instance properties and/or delete instance properties and go back + // to prototype + (this.alteredByBoost || []).forEach(function (setting) { + if (setting.own) { + this[setting.prop] = setting.val; + } + else { + // Revert to prototype + delete this[setting.prop]; + } + }, this); + // Clear previous run + if (this.boostClear) { + this.boostClear(); + } + }; + /** + * @private + * @function Highcharts.Series#hasExtremes + * + * @param {boolean} checkX + * + * @return {boolean} + */ + Series.prototype.hasExtremes = function (checkX) { + var options = this.options, + data = options.data, + xAxis = this.xAxis && this.xAxis.options, + yAxis = this.yAxis && this.yAxis.options, + colorAxis = this.colorAxis && this.colorAxis.options; + return data.length > (options.boostThreshold || Number.MAX_VALUE) && + // Defined yAxis extremes + isNumber(yAxis.min) && + isNumber(yAxis.max) && + // Defined (and required) xAxis extremes + (!checkX || + (isNumber(xAxis.min) && isNumber(xAxis.max))) && + // Defined (e.g. heatmap) colorAxis extremes + (!colorAxis || + (isNumber(colorAxis.min) && isNumber(colorAxis.max))); + }; + /** + * If implemented in the core, parts of this can probably be + * shared with other similar methods in Highcharts. + * + * @function Highcharts.Series#destroyGraphics + */ + Series.prototype.destroyGraphics = function () { + var series = this, + points = this.points, + point, + i; + if (points) { + for (i = 0; i < points.length; i = i + 1) { + point = points[i]; + if (point && point.destroyElements) { + point.destroyElements(); // #7557 + } + } + } + ['graph', 'area', 'tracker'].forEach(function (prop) { + if (series[prop]) { + series[prop] = series[prop].destroy(); + } + }); + }; + // Set default options + boostable.forEach(function (type) { + if (plotOptions[type]) { + plotOptions[type].boostThreshold = 5000; + plotOptions[type].boostData = []; + seriesTypes[type].prototype.fillOpacity = true; + } + }); + + }); + _registerModule(_modules, 'Extensions/Boost/NamedColors.js', [_modules['Core/Color.js']], function (Color) { + /* * + * + * Copyright (c) 2019-2020 Highsoft AS + * + * Boost module: stripped-down renderer for higher performance + * + * License: highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + // Register color names since GL can't render those directly. + // TODO: When supporting modern syntax, make this a const and a named export + var defaultHTMLColorMap = { + 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', + feldspar: '#d19275', + 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', + lightslateblue: '#8470ff', + 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', + violetred: '#d02090', + wheat: '#f5deb3', + white: '#ffffff', + whitesmoke: '#f5f5f5', + yellow: '#ffff00', + yellowgreen: '#9acd32' + }; + Color.names = defaultHTMLColorMap; + + return defaultHTMLColorMap; + }); + _registerModule(_modules, 'Extensions/Boost/Boost.js', [_modules['Core/Globals.js'], _modules['Extensions/Boost/BoostUtils.js'], _modules['Extensions/Boost/BoostInit.js'], _modules['Core/Utilities.js']], function (H, butils, init, U) { + /* * + * + * Copyright (c) 2019-2020 Highsoft AS + * + * Boost module: stripped-down renderer for higher performance + * + * License: highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var error = U.error; + // These need to be fixed when we support named imports + var hasWebGLSupport = butils.hasWebGLSupport; + if (!hasWebGLSupport()) { + if (typeof H.initCanvasBoost !== 'undefined') { + // Fallback to canvas boost + H.initCanvasBoost(); + } + else { + error(26); + } + } + else { + // WebGL support is alright, and we're good to go. + init(); + } + + }); + _registerModule(_modules, 'masters/modules/boost.src.js', [], function () { + + + /* * + * Options for the Boost module. The Boost module allows certain series types + * to be rendered by WebGL instead of the default SVG. This allows hundreds of + * thousands of data points to be rendered in milliseconds. In addition to the + * WebGL rendering it saves time by skipping processing and inspection of the + * data wherever possible. This introduces some limitations to what features are + * available in boost mode. See [the docs]( + * https://www.highcharts.com/docs/advanced-chart-features/boost-module) for + * details. + * + * In addition to the global `boost` option, each series has a + * [boostThreshold](#plotOptions.series.boostThreshold) that defines when the + * boost should kick in. + * + * Requires the `modules/boost.js` module. + * + * @sample {highstock} highcharts/boost/line-series-heavy-stock + * Stock chart + * @sample {highstock} highcharts/boost/line-series-heavy-dynamic + * Dynamic stock chart + * @sample highcharts/boost/line + * Line chart + * @sample highcharts/boost/line-series-heavy + * Line chart with hundreds of series + * @sample highcharts/boost/scatter + * Scatter chart + * @sample highcharts/boost/area + * Area chart + * @sample highcharts/boost/arearange + * Area range chart + * @sample highcharts/boost/column + * Column chart + * @sample highcharts/boost/columnrange + * Column range chart + * @sample highcharts/boost/bubble + * Bubble chart + * @sample highcharts/boost/heatmap + * Heat map + * @sample highcharts/boost/treemap + * Tree map + * + * @product highcharts highstock + * @apioption boost + * */ + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/broken-axis.js b/highcharts/modules/broken-axis.js new file mode 100644 index 0000000..1ff782e --- /dev/null +++ b/highcharts/modules/broken-axis.js @@ -0,0 +1,19 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + (c) 2009-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(c){"object"===typeof module&&module.exports?(c["default"]=c,module.exports=c):"function"===typeof define&&define.amd?define("highcharts/modules/broken-axis",["highcharts"],function(h){c(h);c.Highcharts=h;return c}):c("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(c){function h(c,v,m,h){c.hasOwnProperty(v)||(c[v]=h.apply(null,m))}c=c?c._modules:{};h(c,"Core/Axis/BrokenAxis.js",[c["Core/Axis/Axis.js"],c["Core/Globals.js"],c["Core/Utilities.js"],c["Extensions/Stacking.js"]], +function(c,h,m,A){var q=m.addEvent,v=m.find,x=m.fireEvent,B=m.isArray,y=m.isNumber,r=m.pick,z=h.Series,C=function(){function l(b){this.hasBreaks=!1;this.axis=b}l.isInBreak=function(b,e){var d=b.repeat||Infinity,a=b.from,f=b.to-b.from;e=e>=a?(e-a)%d:d-(a-e)%d;return b.inclusive?e<=f:e=b)break;else a.to=b)break;else if(l.isInBreak(f,b)){d-=b-f.from;break}}return d};l.prototype.findBreakAt=function(b,e){return v(e,function(d){return d.fromp;)n-=k;for(;nb.to||g>b.from&&hb.from&&hb.from&&h>b.to&&ha&&b>=this.basePointRange&&(a=b),g=void 0;d--;)g&&!1!==g.visible||(g=e[d+1]),b=e[d],!1!==g.visible&& +!1!==b.visible&&(g.x-b.x>a&&(g=(b.x+g.x)/2,e.splice(d+1,0,{isNull:!0,x:g}),c.stacking&&this.options.stacking&&(g=c.stacking.stacks[this.stackKey][g]=new A(c,c.options.stackLabels,!1,g,this.stack),g.total=0)),g=b);return this.getGraphPath(e)};q(b,"init",function(){this.brokenAxis||(this.brokenAxis=new C(this))});q(b,"afterInit",function(){"undefined"!==typeof this.brokenAxis&&this.brokenAxis.setBreaks(this.options.breaks,!1)});q(b,"afterSetTickPositions",function(){var a=this.brokenAxis;if(a&&a.hasBreaks){var b= +this.tickPositions,e=this.tickPositions.info,d=[],c;for(c=0;c= from ? + (val - from) % repeat : + repeat - ((from - val) % repeat)); + if (!brk.inclusive) { + ret = test < length && test !== 0; + } + else { + ret = test <= length; + } + return ret; + }; + /** + * @private + */ + BrokenAxisAdditions.lin2Val = function (val) { + var axis = this; + var brokenAxis = axis.brokenAxis; + var breakArray = brokenAxis && brokenAxis.breakArray; + if (!breakArray) { + return val; + } + var nval = val, + brk, + i; + for (i = 0; i < breakArray.length; i++) { + brk = breakArray[i]; + if (brk.from >= nval) { + break; + } + else if (brk.to < nval) { + nval += brk.len; + } + else if (BrokenAxisAdditions.isInBreak(brk, nval)) { + nval += brk.len; + } + } + return nval; + }; + /** + * @private + */ + BrokenAxisAdditions.val2Lin = function (val) { + var axis = this; + var brokenAxis = axis.brokenAxis; + var breakArray = brokenAxis && brokenAxis.breakArray; + if (!breakArray) { + return val; + } + var nval = val, + brk, + i; + for (i = 0; i < breakArray.length; i++) { + brk = breakArray[i]; + if (brk.to <= val) { + nval -= brk.len; + } + else if (brk.from >= val) { + break; + } + else if (BrokenAxisAdditions.isInBreak(brk, val)) { + nval -= (val - brk.from); + break; + } + } + return nval; + }; + /* * + * + * Functions + * + * */ + /** + * Returns the first break found where the x is larger then break.from and + * smaller then break.to. + * + * @param {number} x + * The number which should be within a break. + * + * @param {Array} breaks + * The array of breaks to search within. + * + * @return {Highcharts.XAxisBreaksOptions|undefined} + * Returns the first break found that matches, returns false if no break is + * found. + */ + BrokenAxisAdditions.prototype.findBreakAt = function (x, breaks) { + return find(breaks, function (b) { + return b.from < x && x < b.to; + }); + }; + /** + * @private + */ + BrokenAxisAdditions.prototype.isInAnyBreak = function (val, testKeep) { + var brokenAxis = this; + var axis = brokenAxis.axis; + var breaks = axis.options.breaks, + i = breaks && breaks.length, + inbrk, + keep, + ret; + if (i) { + while (i--) { + if (BrokenAxisAdditions.isInBreak(breaks[i], val)) { + inbrk = true; + if (!keep) { + keep = pick(breaks[i].showPoints, !axis.isXAxis); + } + } + } + if (inbrk && testKeep) { + ret = inbrk && !keep; + } + else { + ret = inbrk; + } + } + return ret; + }; + /** + * Dynamically set or unset breaks in an axis. This function in lighter than + * usin Axis.update, and it also preserves animation. + * + * @private + * @function Highcharts.Axis#setBreaks + * + * @param {Array} [breaks] + * The breaks to add. When `undefined` it removes existing breaks. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart immediately. + * + * @return {void} + */ + BrokenAxisAdditions.prototype.setBreaks = function (breaks, redraw) { + var brokenAxis = this; + var axis = brokenAxis.axis; + var hasBreaks = (isArray(breaks) && !!breaks.length); + axis.isDirty = brokenAxis.hasBreaks !== hasBreaks; + brokenAxis.hasBreaks = hasBreaks; + axis.options.breaks = axis.userOptions.breaks = breaks; + axis.forceRedraw = true; // Force recalculation in setScale + // Recalculate series related to the axis. + axis.series.forEach(function (series) { + series.isDirty = true; + }); + if (!hasBreaks && axis.val2lin === BrokenAxisAdditions.val2Lin) { + // Revert to prototype functions + delete axis.val2lin; + delete axis.lin2val; + } + if (hasBreaks) { + axis.userOptions.ordinal = false; + axis.lin2val = BrokenAxisAdditions.lin2Val; + axis.val2lin = BrokenAxisAdditions.val2Lin; + axis.setExtremes = function (newMin, newMax, redraw, animation, eventArguments) { + // If trying to set extremes inside a break, extend min to + // after, and max to before the break ( #3857 ) + if (brokenAxis.hasBreaks) { + var axisBreak, + breaks = this.options.breaks; + while ((axisBreak = brokenAxis.findBreakAt(newMin, breaks))) { + newMin = axisBreak.to; + } + while ((axisBreak = brokenAxis.findBreakAt(newMax, breaks))) { + newMax = axisBreak.from; + } + // If both min and max is within the same break. + if (newMax < newMin) { + newMax = newMin; + } + } + Axis.prototype.setExtremes.call(this, newMin, newMax, redraw, animation, eventArguments); + }; + axis.setAxisTranslation = function (saveOld) { + Axis.prototype.setAxisTranslation.call(this, saveOld); + brokenAxis.unitLength = null; + if (brokenAxis.hasBreaks) { + var breaks = axis.options.breaks || [], + // Temporary one: + breakArrayT = [], + breakArray = [], + length = 0, + inBrk, + repeat, + min = axis.userMin || axis.min, + max = axis.userMax || axis.max, + pointRangePadding = pick(axis.pointRangePadding, 0), + start, + i; + // Min & max check (#4247) + breaks.forEach(function (brk) { + repeat = brk.repeat || Infinity; + if (BrokenAxisAdditions.isInBreak(brk, min)) { + min += + (brk.to % repeat) - + (min % repeat); + } + if (BrokenAxisAdditions.isInBreak(brk, max)) { + max -= + (max % repeat) - + (brk.from % repeat); + } + }); + // Construct an array holding all breaks in the axis + breaks.forEach(function (brk) { + start = brk.from; + repeat = brk.repeat || Infinity; + while (start - repeat > min) { + start -= repeat; + } + while (start < min) { + start += repeat; + } + for (i = start; i < max; i += repeat) { + breakArrayT.push({ + value: i, + move: 'in' + }); + breakArrayT.push({ + value: i + (brk.to - brk.from), + move: 'out', + size: brk.breakSize + }); + } + }); + breakArrayT.sort(function (a, b) { + return ((a.value === b.value) ? + ((a.move === 'in' ? 0 : 1) - + (b.move === 'in' ? 0 : 1)) : + a.value - b.value); + }); + // Simplify the breaks + inBrk = 0; + start = min; + breakArrayT.forEach(function (brk) { + inBrk += (brk.move === 'in' ? 1 : -1); + if (inBrk === 1 && brk.move === 'in') { + start = brk.value; + } + if (inBrk === 0) { + breakArray.push({ + from: start, + to: brk.value, + len: brk.value - start - (brk.size || 0) + }); + length += brk.value - start - (brk.size || 0); + } + }); + /** + * HC <= 8 backwards compatibility, used by demo samples. + * @deprecated + * @private + * @requires modules/broken-axis + */ + axis.breakArray = brokenAxis.breakArray = breakArray; + // Used with staticScale, and below the actual axis length, + // when breaks are substracted. + brokenAxis.unitLength = max - min - length + pointRangePadding; + fireEvent(axis, 'afterBreaks'); + if (axis.staticScale) { + axis.transA = axis.staticScale; + } + else if (brokenAxis.unitLength) { + axis.transA *= + (max - axis.min + pointRangePadding) / + brokenAxis.unitLength; + } + if (pointRangePadding) { + axis.minPixelPadding = + axis.transA * axis.minPointOffset; + } + axis.min = min; + axis.max = max; + } + }; + } + if (pick(redraw, true)) { + axis.chart.redraw(); + } + }; + return BrokenAxisAdditions; + }()); + /** + * Axis with support of broken data rows. + * @private + * @class + */ + var BrokenAxis = /** @class */ (function () { + function BrokenAxis() { + } + /** + * Adds support for broken axes. + * @private + */ + BrokenAxis.compose = function (AxisClass, SeriesClass) { + AxisClass.keepProps.push('brokenAxis'); + var seriesProto = Series.prototype; + /** + * @private + */ + seriesProto.drawBreaks = function (axis, keys) { + var series = this, + points = series.points, + breaks, + threshold, + eventName, + y; + if (axis && // #5950 + axis.brokenAxis && + axis.brokenAxis.hasBreaks) { + var brokenAxis_1 = axis.brokenAxis; + keys.forEach(function (key) { + breaks = brokenAxis_1 && brokenAxis_1.breakArray || []; + threshold = axis.isXAxis ? + axis.min : + pick(series.options.threshold, axis.min); + points.forEach(function (point) { + y = pick(point['stack' + key.toUpperCase()], point[key]); + breaks.forEach(function (brk) { + if (isNumber(threshold) && isNumber(y)) { + eventName = false; + if ((threshold < brk.from && y > brk.to) || + (threshold > brk.from && y < brk.from)) { + eventName = 'pointBreak'; + } + else if ((threshold < brk.from && y > brk.from && y < brk.to) || + (threshold > brk.from && y > brk.to && y < brk.from)) { + eventName = 'pointInBreak'; + } + if (eventName) { + fireEvent(axis, eventName, { point: point, brk: brk }); + } + } + }); + }); + }); + } + }; + /** + * Extend getGraphPath by identifying gaps in the data so that we can + * draw a gap in the line or area. This was moved from ordinal axis + * module to broken axis module as of #5045. + * + * @private + * @function Highcharts.Series#gappedPath + * + * @return {Highcharts.SVGPathArray} + * Gapped path + */ + seriesProto.gappedPath = function () { + var currentDataGrouping = this.currentDataGrouping, + groupingSize = currentDataGrouping && currentDataGrouping.gapSize, + gapSize = this.options.gapSize, + points = this.points.slice(), + i = points.length - 1, + yAxis = this.yAxis, + stack; + /** + * Defines when to display a gap in the graph, together with the + * [gapUnit](plotOptions.series.gapUnit) option. + * + * In case when `dataGrouping` is enabled, points can be grouped + * into a larger time span. This can make the grouped points to have + * a greater distance than the absolute value of `gapSize` property, + * which will result in disappearing graph completely. To prevent + * this situation the mentioned distance between grouped points is + * used instead of previously defined `gapSize`. + * + * In practice, this option is most often used to visualize gaps in + * time series. In a stock chart, intraday data is available for + * daytime hours, while gaps will appear in nights and weekends. + * + * @see [gapUnit](plotOptions.series.gapUnit) + * @see [xAxis.breaks](#xAxis.breaks) + * + * @sample {highstock} stock/plotoptions/series-gapsize/ + * Setting the gap size to 2 introduces gaps for weekends + * in daily datasets. + * + * @type {number} + * @default 0 + * @product highstock + * @requires modules/broken-axis + * @apioption plotOptions.series.gapSize + */ + /** + * Together with [gapSize](plotOptions.series.gapSize), this option + * defines where to draw gaps in the graph. + * + * When the `gapUnit` is `"relative"` (default), a gap size of 5 + * means that if the distance between two points is greater than + * 5 times that of the two closest points, the graph will be broken. + * + * When the `gapUnit` is `"value"`, the gap is based on absolute + * axis values, which on a datetime axis is milliseconds. This also + * applies to the navigator series that inherits gap options from + * the base series. + * + * @see [gapSize](plotOptions.series.gapSize) + * + * @type {string} + * @default relative + * @since 5.0.13 + * @product highstock + * @validvalue ["relative", "value"] + * @requires modules/broken-axis + * @apioption plotOptions.series.gapUnit + */ + if (gapSize && i > 0) { // #5008 + // Gap unit is relative + if (this.options.gapUnit !== 'value') { + gapSize *= this.basePointRange; + } + // Setting a new gapSize in case dataGrouping is enabled (#7686) + if (groupingSize && + groupingSize > gapSize && + // Except when DG is forced (e.g. from other series) + // and has lower granularity than actual points (#11351) + groupingSize >= this.basePointRange) { + gapSize = groupingSize; + } + // extension for ordinal breaks + var current = void 0, + next = void 0; + while (i--) { + // Reassign next if it is not visible + if (!(next && next.visible !== false)) { + next = points[i + 1]; + } + current = points[i]; + // Skip iteration if one of the points is not visible + if (next.visible === false || current.visible === false) { + continue; + } + if (next.x - current.x > gapSize) { + var xRange = (current.x + next.x) / 2; + points.splice(// insert after this one + i + 1, 0, { + isNull: true, + x: xRange + }); + // For stacked chart generate empty stack items, #6546 + if (yAxis.stacking && this.options.stacking) { + stack = yAxis.stacking.stacks[this.stackKey][xRange] = + new StackItem(yAxis, yAxis.options + .stackLabels, false, xRange, this.stack); + stack.total = 0; + } + } + // Assign current to next for the upcoming iteration + next = current; + } + } + // Call base method + return this.getGraphPath(points); + }; + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'init', function () { + var axis = this; + if (!axis.brokenAxis) { + axis.brokenAxis = new BrokenAxisAdditions(axis); + } + }); + addEvent(AxisClass, 'afterInit', function () { + if (typeof this.brokenAxis !== 'undefined') { + this.brokenAxis.setBreaks(this.options.breaks, false); + } + }); + addEvent(AxisClass, 'afterSetTickPositions', function () { + var axis = this; + var brokenAxis = axis.brokenAxis; + if (brokenAxis && + brokenAxis.hasBreaks) { + var tickPositions = this.tickPositions, + info = this.tickPositions.info, + newPositions = [], + i; + for (i = 0; i < tickPositions.length; i++) { + if (!brokenAxis.isInAnyBreak(tickPositions[i])) { + newPositions.push(tickPositions[i]); + } + } + this.tickPositions = newPositions; + this.tickPositions.info = info; + } + }); + // Force Axis to be not-ordinal when breaks are defined + addEvent(AxisClass, 'afterSetOptions', function () { + if (this.brokenAxis && this.brokenAxis.hasBreaks) { + this.options.ordinal = false; + } + }); + addEvent(SeriesClass, 'afterGeneratePoints', function () { + var _a = this, + isDirty = _a.isDirty, + connectNulls = _a.options.connectNulls, + points = _a.points, + xAxis = _a.xAxis, + yAxis = _a.yAxis; + // Set, or reset visibility of the points. Axis.setBreaks marks the + // series as isDirty + if (isDirty) { + var i = points.length; + while (i--) { + var point = points[i]; + // Respect nulls inside the break (#4275) + var nullGap = point.y === null && connectNulls === false; + var isPointInBreak = (!nullGap && ((xAxis && + xAxis.brokenAxis && + xAxis.brokenAxis.isInAnyBreak(point.x, + true)) || (yAxis && + yAxis.brokenAxis && + yAxis.brokenAxis.isInAnyBreak(point.y, + true)))); + // Set point.visible if in any break. + // If not in break, reset visible to original value. + point.visible = isPointInBreak ? + false : + point.options.visible !== false; + } + } + }); + addEvent(SeriesClass, 'afterRender', function drawPointsWrapped() { + this.drawBreaks(this.xAxis, ['x']); + this.drawBreaks(this.yAxis, pick(this.pointArrayMap, ['y'])); + }); + }; + return BrokenAxis; + }()); + BrokenAxis.compose(Axis, Series); // @todo remove automatism + + return BrokenAxis; + }); + _registerModule(_modules, 'masters/modules/broken-axis.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/bullet.js b/highcharts/modules/bullet.js new file mode 100644 index 0000000..ef1a988 --- /dev/null +++ b/highcharts/modules/bullet.js @@ -0,0 +1,15 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Bullet graph series type for Highcharts + + (c) 2010-2019 Kacper Madej + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/bullet",["highcharts"],function(d){a(d);a.Highcharts=d;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function d(a,b,n,d){a.hasOwnProperty(b)||(a[b]=d.apply(null,n))}a=a?a._modules:{};d(a,"Series/BulletSeries.js",[a["Core/Globals.js"],a["Core/Utilities.js"]],function(a,b){var d=b.isNumber,r=b.merge,k=b.pick,t=b.relativeLength; +b=b.seriesType;var f=a.seriesTypes.column.prototype;b("bullet","column",{targetOptions:{width:"140%",height:3,borderWidth:0},tooltip:{pointFormat:'\u25cf {series.name}: {point.y}. Target: {point.target}
    '}},{pointArrayMap:["y","target"],parallelArrays:["x","y","target"],drawPoints:function(){var a=this,l=a.chart,b=a.options,n=b.animationLimit||250;f.drawPoints.apply(this);a.points.forEach(function(c){var p=c.options,e=c.targetGraphic,f=c.target, +m=c.y;if(d(f)&&null!==f){var g=r(b.targetOptions,p.targetOptions);var u=g.height;var h=c.shapeArgs;var q=t(g.width,h.width);var v=a.yAxis.translate(f,!1,!0,!1,!0)-g.height/2-.5;h=a.crispCol.apply({chart:l,borderWidth:g.borderWidth,options:{crisp:b.crisp}},[h.x+h.width/2-q/2,v,q,u]);e?(e[l.pointCount\u25CF' + + ' {series.name}: {point.y}. Target: {point.target}' + + '
    ' + } + }, { + pointArrayMap: ['y', 'target'], + parallelArrays: ['x', 'y', 'target'], + /* eslint-disable valid-jsdoc */ + /** + * Draws the targets. For inverted chart, the `series.group` is rotated, + * so the same coordinates apply. This method is based on column series + * drawPoints function. + * + * @ignore + * @function Highcharts.Series#drawPoints + */ + drawPoints: function () { + var series = this, + chart = series.chart, + options = series.options, + animationLimit = options.animationLimit || 250; + columnProto.drawPoints.apply(this); + series.points.forEach(function (point) { + var pointOptions = point.options, + shapeArgs, + targetGraphic = point.targetGraphic, + targetShapeArgs, + targetVal = point.target, + pointVal = point.y, + width, + height, + targetOptions, + y; + if (isNumber(targetVal) && targetVal !== null) { + targetOptions = merge(options.targetOptions, pointOptions.targetOptions); + height = targetOptions.height; + shapeArgs = point.shapeArgs; + width = relativeLength(targetOptions.width, shapeArgs.width); + y = series.yAxis.translate(targetVal, false, true, false, true) - targetOptions.height / 2 - 0.5; + targetShapeArgs = series.crispCol.apply({ + // Use fake series object to set borderWidth of target + chart: chart, + borderWidth: targetOptions.borderWidth, + options: { + crisp: options.crisp + } + }, [ + (shapeArgs.x + + shapeArgs.width / 2 - width / 2), + y, + width, + height + ]); + if (targetGraphic) { + // Update + targetGraphic[chart.pointCount < animationLimit ? + 'animate' : + 'attr'](targetShapeArgs); + // Add or remove tooltip reference + if (isNumber(pointVal) && pointVal !== null) { + targetGraphic.element.point = point; + } + else { + targetGraphic.element.point = void 0; + } + } + else { + point.targetGraphic = targetGraphic = chart.renderer + .rect() + .attr(targetShapeArgs) + .add(series.group); + } + // Presentational + if (!chart.styledMode) { + targetGraphic.attr({ + fill: pick(targetOptions.color, pointOptions.color, (series.zones.length && (point.getZone.call({ + series: series, + x: point.x, + y: targetVal, + options: {} + }).color || series.color)) || void 0, point.color, series.color), + stroke: pick(targetOptions.borderColor, point.borderColor, series.options.borderColor), + 'stroke-width': targetOptions.borderWidth + }); + } + // Add tooltip reference + if (isNumber(pointVal) && pointVal !== null) { + targetGraphic.element.point = point; + } + targetGraphic.addClass(point.getClassName() + + ' highcharts-bullet-target', true); + } + else if (targetGraphic) { + // #1269: + point.targetGraphic = targetGraphic.destroy(); + } + }); + }, + /** + * Includes target values to extend extremes from y values. + * + * @ignore + * @function Highcharts.Series#getExtremes + */ + getExtremes: function (yData) { + var series = this, + targetData = series.targetData, + yMax, + yMin; + var dataExtremes = columnProto.getExtremes.call(this, + yData); + if (targetData && targetData.length) { + var targetExtremes = columnProto.getExtremes.call(this, + targetData); + if (isNumber(targetExtremes.dataMin)) { + dataExtremes.dataMin = Math.min(pick(dataExtremes.dataMin, Infinity), targetExtremes.dataMin); + } + if (isNumber(targetExtremes.dataMax)) { + dataExtremes.dataMax = Math.max(pick(dataExtremes.dataMax, -Infinity), targetExtremes.dataMax); + } + } + return dataExtremes; + } + /* eslint-enable valid-jsdoc */ + }, + /** @lends Highcharts.seriesTypes.ohlc.prototype.pointClass.prototype */ + { + // eslint-disable-next-line valid-jsdoc + /** + * Destroys target graphic. + * + * @private + * @function + */ + destroy: function () { + if (this.targetGraphic) { + this.targetGraphic = this.targetGraphic.destroy(); + } + columnProto.pointClass.prototype.destroy + .apply(this, arguments); + return; + } + }); + /** + * A `bullet` series. If the [type](#series.bullet.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.bullet + * @since 6.0.0 + * @product highcharts + * @excluding dataParser, dataURL, marker, dataSorting, boostThreshold, + * boostBlending + * @requires modules/bullet + * @apioption series.bullet + */ + /** + * An array of data points for the series. For the `bullet` series type, + * points can be given in the following ways: + * + * 1. An array of arrays with 3 or 2 values. In this case, the values correspond + * to `x,y,target`. If the first value is a string, it is applied as the name + * of the point, and the `x` value is inferred. The `x` value can also be + * omitted, in which case the inner arrays should be of length 2\. Then the + * `x` value is automatically calculated, either starting at 0 and + * incremented by 1, or from `pointStart` and `pointInterval` given in the + * series options. + * ```js + * data: [ + * [0, 40, 75], + * [1, 50, 50], + * [2, 60, 40] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.bullet.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 0, + * y: 40, + * target: 75, + * name: "Point1", + * color: "#00FF00" + * }, { + * x: 1, + * y: 60, + * target: 40, + * name: "Point2", + * color: "#FF00FF" + * }] + * ``` + * + * @type {Array|Array<(number|string),number,number>|*>} + * @extends series.column.data + * @since 6.0.0 + * @product highcharts + * @apioption series.bullet.data + */ + /** + * The target value of a point. + * + * @type {number} + * @since 6.0.0 + * @product highcharts + * @apioption series.bullet.data.target + */ + /** + * Individual target options for each point. + * + * @extends plotOptions.bullet.targetOptions + * @product highcharts + * @apioption series.bullet.data.targetOptions + */ + /** + * @product highcharts + * @excluding halo, lineWidth, lineWidthPlus, marker + * @apioption series.bullet.states.hover + */ + /** + * @product highcharts + * @excluding halo, lineWidth, lineWidthPlus, marker + * @apioption series.bullet.states.select + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/bullet.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/coloraxis.js b/highcharts/modules/coloraxis.js new file mode 100644 index 0000000..3b1a650 --- /dev/null +++ b/highcharts/modules/coloraxis.js @@ -0,0 +1,30 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + ColorAxis module + + (c) 2012-2019 Pawel Potaczek + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/color-axis",["highcharts"],function(m){b(m);b.Highcharts=m;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function m(b,k,g,n){b.hasOwnProperty(k)||(b[k]=n.apply(null,g))}b=b?b._modules:{};m(b,"Mixins/ColorSeries.js",[b["Core/Globals.js"]],function(b){b.colorPointMixin={setVisible:function(b){var g=this,n=b?"show":"hide"; +g.visible=g.options.visible=!!b;["graphic","dataLabel"].forEach(function(b){if(g[b])g[b][n]()});this.series.buildKDTree()}};b.colorSeriesMixin={optionalAxis:"colorAxis",colorAxis:0,translateColors:function(){var b=this,g=this.options.nullColor,n=this.colorAxis,m=this.colorKey;(this.data.length?this.data:this.points).forEach(function(p){var k=p.getNestedProperty(m);(k=p.options.color||(p.isNull||null===p.value?g:n&&"undefined"!==typeof k?n.toColor(k,p):p.color||b.color))&&p.color!==k&&(p.color=k,"point"=== +b.options.legendType&&p.legendItem&&b.chart.legend.colorizeItem(p,p.visible))})}}});m(b,"Core/Axis/ColorAxis.js",[b["Core/Axis/Axis.js"],b["Core/Chart/Chart.js"],b["Core/Color.js"],b["Core/Globals.js"],b["Core/Legend.js"],b["Mixins/LegendSymbol.js"],b["Core/Series/Point.js"],b["Core/Utilities.js"]],function(b,k,g,n,m,p,A,q){var B=this&&this.__extends||function(){var b=function(d,a){b=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(a,e){a.__proto__=e}||function(a,e){for(var c in e)e.hasOwnProperty(c)&& +(a[c]=e[c])};return b(d,a)};return function(d,a){function f(){this.constructor=d}b(d,a);d.prototype=null===a?Object.create(a):(f.prototype=a.prototype,new f)}}(),u=g.parse,C=n.noop;g=q.addEvent;var z=q.erase,x=q.extend,D=q.Fx,E=q.isNumber,y=q.merge,t=q.pick,F=q.splat;"";var v=n.Series;q=n.colorPointMixin;x(v.prototype,n.colorSeriesMixin);x(A.prototype,q);k.prototype.collectionsWithUpdate.push("colorAxis");k.prototype.collectionsWithInit.colorAxis=[k.prototype.addColorAxis];var w=function(b){function d(a, +f){var e=b.call(this,a,f)||this;e.beforePadding=!1;e.chart=void 0;e.coll="colorAxis";e.dataClasses=void 0;e.legendItem=void 0;e.legendItems=void 0;e.name="";e.options=void 0;e.stops=void 0;e.visible=!0;e.init(a,f);return e}B(d,b);d.buildOptions=function(a,f,e){a=a.options.legend||{};var c=e.layout?"vertical"!==e.layout:"vertical"!==a.layout;return y(f,{side:c?2:1,reversed:!c},e,{opposite:!c,showEmpty:!1,title:null,visible:a.enabled&&(e?!1!==e.visible:!0)})};d.prototype.init=function(a,f){var e=d.buildOptions(a, +d.defaultOptions,f);this.coll="colorAxis";b.prototype.init.call(this,a,e);f.dataClasses&&this.initDataClasses(f);this.initStops();this.horiz=!e.opposite;this.zoomEnabled=!1};d.prototype.initDataClasses=function(a){var f=this.chart,e,c=0,b=f.options.chart.colorCount,d=this.options,h=a.dataClasses.length;this.dataClasses=e=[];this.legendItems=[];a.dataClasses.forEach(function(a,r){a=y(a);e.push(a);if(f.styledMode||!a.color)"category"===d.dataClassColor?(f.styledMode||(r=f.options.colors,b=r.length, +a.color=r[c]),a.colorIndex=c,c++,c===b&&(c=0)):a.color=u(d.minColor).tweenTo(u(d.maxColor),2>h?.5:r/(h-1))})};d.prototype.hasData=function(){return!!(this.tickPositions||[]).length};d.prototype.setTickPositions=function(){if(!this.dataClasses)return b.prototype.setTickPositions.call(this)};d.prototype.initStops=function(){this.stops=this.options.stops||[[0,this.options.minColor],[1,this.options.maxColor]];this.stops.forEach(function(a){a.color=u(a[1])})};d.prototype.setOptions=function(a){b.prototype.setOptions.call(this, +a);this.options.crosshair=this.options.marker};d.prototype.setAxisSize=function(){var a=this.legendSymbol,f=this.chart,e=f.options.legend||{},c,b;a?(this.left=e=a.attr("x"),this.top=c=a.attr("y"),this.width=b=a.attr("width"),this.height=a=a.attr("height"),this.right=f.chartWidth-e-b,this.bottom=f.chartHeight-c-a,this.len=this.horiz?b:a,this.pos=this.horiz?e:c):this.len=(this.horiz?e.symbolWidth:e.symbolHeight)||d.defaultLegendLength};d.prototype.normalizedValue=function(a){this.logarithmic&&(a=this.logarithmic.log2lin(a)); +return 1-(this.max-a)/(this.max-this.min||1)};d.prototype.toColor=function(a,f){var e=this.dataClasses,c=this.stops,b;if(e)for(b=e.length;b--;){var d=e[b];var h=d.from;c=d.to;if(("undefined"===typeof h||a>=h)&&("undefined"===typeof c||a<=c)){var l=d.color;f&&(f.dataClass=b,f.colorIndex=d.colorIndex);break}}else{a=this.normalizedValue(a);for(b=c.length;b--&&!(a>c[b][0]););h=c[b]||c[b+1];c=c[b+1]||h;a=1-(c[0]-a)/(c[0]-h[0]||1);l=h.color.tweenTo(c.color,a)}return l};d.prototype.getOffset=function(){var a= +this.legendGroup,f=this.chart.axisOffset[this.side];a&&(this.axisParent=a,b.prototype.getOffset.call(this),this.added||(this.added=!0,this.labelLeft=0,this.labelRight=this.width),this.chart.axisOffset[this.side]=f)};d.prototype.setLegendColor=function(){var a=this.reversed,f=a?1:0;a=a?0:1;f=this.horiz?[f,0,a,0]:[0,a,0,f];this.legendColor={linearGradient:{x1:f[0],y1:f[1],x2:f[2],y2:f[3]},stops:this.stops}};d.prototype.drawLegendSymbol=function(a,f){var b=a.padding,c=a.options,r=this.horiz,l=t(c.symbolWidth, +r?d.defaultLegendLength:12),h=t(c.symbolHeight,r?12:d.defaultLegendLength),g=t(c.labelPadding,r?16:30);c=t(c.itemDistance,10);this.setLegendColor();f.legendSymbol=this.chart.renderer.rect(0,a.baseline-11,l,h).attr({zIndex:1}).add(f.legendGroup);this.legendItemWidth=l+b+(r?c:g);this.legendItemHeight=h+b+(r?g:0)};d.prototype.setState=function(a){this.series.forEach(function(b){b.setState(a)})};d.prototype.setVisible=function(){};d.prototype.getSeriesExtremes=function(){var a=this.series,b=a.length, +e;this.dataMin=Infinity;for(this.dataMax=-Infinity;b--;){var c=a[b];var d=c.colorKey=t(c.options.colorKey,c.colorKey,c.pointValKey,c.zoneAxis,"y");var l=c.pointArrayMap;var h=c[d+"Min"]&&c[d+"Max"];if(c[d+"Data"])var g=c[d+"Data"];else if(l){g=[];l=l.indexOf(d);var k=c.yData;if(0<=l&&k)for(e=0;el+g&&(h=l+g+2);f.plotX=h;f.plotY=this.len-h;b.prototype.drawCrosshair.call(this,a,f);f.plotX=d;f.plotY=c;this.cross&&!this.cross.addedToColorAxis&&this.legendGroup&& +(this.cross.addClass("highcharts-coloraxis-marker").add(this.legendGroup),this.cross.addedToColorAxis=!0,!this.chart.styledMode&&this.crosshair&&this.cross.attr({fill:this.crosshair.color}))}};d.prototype.getPlotLinePath=function(a){var d=this.left,e=a.translatedValue,c=this.top;return E(e)?this.horiz?[["M",e-4,c-6],["L",e+4,c-6],["L",e,c],["Z"]]:[["M",d,e],["L",d-6,e+6],["L",d-6,e-6],["Z"]]:b.prototype.getPlotLinePath.call(this,a)};d.prototype.update=function(a,f){var e=this.chart,c=e.legend,l=d.buildOptions(e, +{},a);this.series.forEach(function(a){a.isDirtyData=!0});(a.dataClasses&&c.allItems||this.dataClasses)&&this.destroyItems();e.options[this.coll]=y(this.userOptions,l);b.prototype.update.call(this,l,f);this.legendItem&&(this.setLegendColor(),c.colorizeItem(this,!0))};d.prototype.destroyItems=function(){var a=this.chart;this.legendItem?a.legend.destroyItem(this):this.legendItems&&this.legendItems.forEach(function(b){a.legend.destroyItem(b)});a.isDirtyLegend=!0};d.prototype.remove=function(a){this.destroyItems(); +b.prototype.remove.call(this,a)};d.prototype.getDataClassLegendSymbols=function(){var a=this,b=a.chart,d=a.legendItems,c=b.options.legend,l=c.valueDecimals,g=c.valueSuffix||"",h;d.length||a.dataClasses.forEach(function(c,e){var f=!0,k=c.from,m=c.to,n=b.numberFormatter;h="";"undefined"===typeof k?h="< ":"undefined"===typeof m&&(h="> ");"undefined"!==typeof k&&(h+=n(k,l)+g);"undefined"!==typeof k&&"undefined"!==typeof m&&(h+=" - ");"undefined"!==typeof m&&(h+=n(m,l)+g);d.push(x({chart:b,name:h,options:{}, +drawLegendSymbol:p.drawRectangle,visible:!0,setState:C,isDataClass:!0,setVisible:function(){f=a.visible=!f;a.series.forEach(function(a){a.points.forEach(function(a){a.dataClass===e&&a.setVisible(f)})});b.legend.colorizeItem(this,f)}},c))});return d};d.defaultLegendLength=200;d.defaultOptions={lineWidth:0,minPadding:0,maxPadding:0,gridLineWidth:1,tickPixelInterval:72,startOnTick:!0,endOnTick:!0,offset:0,marker:{animation:{duration:50},width:.01,color:"#999999"},labels:{overflow:"justify",rotation:0}, +minColor:"#e6ebf5",maxColor:"#003399",tickLength:5,showInLegend:!0};d.keepProps=["legendGroup","legendItemHeight","legendItemWidth","legendItem","legendSymbol"];return d}(b);Array.prototype.push.apply(b.keepProps,w.keepProps);n.ColorAxis=w;["fill","stroke"].forEach(function(b){D.prototype[b+"Setter"]=function(){this.elem.attr(b,u(this.start).tweenTo(u(this.end),this.pos),null,!0)}});g(k,"afterGetAxes",function(){var b=this,d=b.options;this.colorAxis=[];d.colorAxis&&(d.colorAxis=F(d.colorAxis),d.colorAxis.forEach(function(a, +d){a.index=d;new w(b,a)}))});g(v,"bindAxes",function(){var b=this.axisTypes;b?-1===b.indexOf("colorAxis")&&b.push("colorAxis"):this.axisTypes=["colorAxis"]});g(m,"afterGetAllItems",function(b){var d=[],a,f;(this.chart.colorAxis||[]).forEach(function(e){(a=e.options)&&a.showInLegend&&(a.dataClasses&&a.visible?d=d.concat(e.getDataClassLegendSymbols()):a.visible&&d.push(e),e.series.forEach(function(c){if(!c.options.showInLegend||a.dataClasses)"point"===c.options.legendType?c.points.forEach(function(a){z(b.allItems, +a)}):z(b.allItems,c)}))});for(f=d.length;f--;)b.allItems.unshift(d[f])});g(m,"afterColorizeItem",function(b){b.visible&&b.item.legendColor&&b.item.legendSymbol.attr({fill:b.item.legendColor})});g(m,"afterUpdate",function(){var b=this.chart.colorAxis;b&&b.forEach(function(b,a,f){b.update({},f)})});g(v,"afterTranslate",function(){(this.chart.colorAxis&&this.chart.colorAxis.length||this.colorAttribs)&&this.translateColors()});return w});m(b,"masters/modules/coloraxis.src.js",[],function(){})}); +//# sourceMappingURL=coloraxis.js.map \ No newline at end of file diff --git a/highcharts/modules/coloraxis.js.map b/highcharts/modules/coloraxis.js.map new file mode 100644 index 0000000..99ca76d --- /dev/null +++ b/highcharts/modules/coloraxis.js.map @@ -0,0 +1 @@ +{"version":3,"file":"coloraxis.js.map","lineCount":29,"mappings":"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","sources":["coloraxis.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","colorPointMixin","setVisible","vis","point","method","visible","options","forEach","key","series","buildKDTree","colorSeriesMixin","optionalAxis","colorAxis","translateColors","nullColor","colorKey","data","length","points","value","getNestedProperty","color","isNull","toColor","legendType","legendItem","chart","legend","colorizeItem","Axis","Chart","Color","Legend","LegendSymbolMixin","Point","U","__extends","extendStatics","d","b","Object","setPrototypeOf","__proto__","Array","p","__","constructor","prototype","create","parse","noop","addEvent","erase","extend","Fx","isNumber","merge","pick","splat","Series","collectionsWithUpdate","push","collectionsWithInit","addColorAxis","ColorAxis","_super","userOptions","_this","call","beforePadding","coll","dataClasses","legendItems","name","stops","init","buildOptions","ColorAxis.buildOptions","horiz","layout","side","reversed","opposite","showEmpty","title","enabled","ColorAxis.prototype.init","defaultOptions","axis","initDataClasses","initStops","zoomEnabled","ColorAxis.prototype.initDataClasses","colorCounter","colorCount","len","dataClass","i","styledMode","dataClassColor","colors","colorIndex","minColor","tweenTo","maxColor","hasData","ColorAxis.prototype.hasData","tickPositions","setTickPositions","ColorAxis.prototype.setTickPositions","ColorAxis.prototype.initStops","stop","setOptions","ColorAxis.prototype.setOptions","crosshair","marker","setAxisSize","ColorAxis.prototype.setAxisSize","symbol","legendSymbol","legendOptions","y","width","left","x","attr","top","height","right","chartWidth","bottom","chartHeight","pos","symbolWidth","symbolHeight","defaultLegendLength","normalizedValue","ColorAxis.prototype.normalizedValue","logarithmic","log2lin","max","min","ColorAxis.prototype.toColor","from","to","getOffset","ColorAxis.prototype.getOffset","group","legendGroup","sideOffset","axisOffset","axisParent","added","labelLeft","labelRight","setLegendColor","ColorAxis.prototype.setLegendColor","one","zero","grad","legendColor","linearGradient","x1","y1","x2","y2","drawLegendSymbol","ColorAxis.prototype.drawLegendSymbol","item","padding","labelPadding","itemDistance","renderer","rect","baseline","zIndex","add","legendItemWidth","legendItemHeight","setState","ColorAxis.prototype.setState","state","ColorAxis.prototype.setVisible","getSeriesExtremes","ColorAxis.prototype.getSeriesExtremes","j","dataMin","Infinity","dataMax","cSeries","pointValKey","zoneAxis","pointArrayMap","calculatedExtremes","colorValArray","colorValIndex","indexOf","yData","minColorValue","maxColorValue","cExtremes","getExtremes","Math","applyExtremes","drawCrosshair","ColorAxis.prototype.drawCrosshair","e","plotX","plotY","axisPos","axisLen","crossPos","toPixels","cross","addedToColorAxis","addClass","fill","getPlotLinePath","ColorAxis.prototype.getPlotLinePath","translatedValue","update","ColorAxis.prototype.update","newOptions","redraw","updatedOptions","isDirtyData","allItems","destroyItems","ColorAxis.prototype.destroyItems","destroyItem","isDirtyLegend","remove","ColorAxis.prototype.remove","getDataClassLegendSymbols","ColorAxis.prototype.getDataClassLegendSymbols","valueDecimals","valueSuffix","numberFormatter","drawRectangle","isDataClass","lineWidth","minPadding","maxPadding","gridLineWidth","tickPixelInterval","startOnTick","endOnTick","offset","animation","duration","labels","overflow","rotation","tickLength","showInLegend","keepProps","prop","elem","start","end","axisOptions","index","axisTypes","colorAxisItems","concat","unshift","colorAxes","colorAttribs"]} \ No newline at end of file diff --git a/highcharts/modules/coloraxis.src.js b/highcharts/modules/coloraxis.src.js new file mode 100644 index 0000000..5f09c45 --- /dev/null +++ b/highcharts/modules/coloraxis.src.js @@ -0,0 +1,1331 @@ +/** + * @license Highcharts JS v8.2.0 (2020-08-20) + * + * ColorAxis module + * + * (c) 2012-2019 Pawel Potaczek + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/color-axis', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'Mixins/ColorSeries.js', [_modules['Core/Globals.js']], function (H) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Mixin for maps and heatmaps + * + * @private + * @mixin Highcharts.colorPointMixin + */ + H.colorPointMixin = { + /* eslint-disable valid-jsdoc */ + /** + * Set the visibility of a single point + * @private + * @function Highcharts.colorPointMixin.setVisible + * @param {boolean} visible + * @return {void} + */ + setVisible: function (vis) { + var point = this, + method = vis ? 'show' : 'hide'; + point.visible = point.options.visible = Boolean(vis); + // Show and hide associated elements + ['graphic', 'dataLabel'].forEach(function (key) { + if (point[key]) { + point[key][method](); + } + }); + this.series.buildKDTree(); // rebuild kdtree #13195 + } + /* eslint-enable valid-jsdoc */ + }; + /** + * @private + * @mixin Highcharts.colorSeriesMixin + */ + H.colorSeriesMixin = { + optionalAxis: 'colorAxis', + colorAxis: 0, + /* eslint-disable valid-jsdoc */ + /** + * In choropleth maps, the color is a result of the value, so this needs + * translation too + * @private + * @function Highcharts.colorSeriesMixin.translateColors + * @return {void} + */ + translateColors: function () { + var series = this, + points = this.data.length ? this.data : this.points, + nullColor = this.options.nullColor, + colorAxis = this.colorAxis, + colorKey = this.colorKey; + points.forEach(function (point) { + var value = point.getNestedProperty(colorKey), + color; + color = point.options.color || + (point.isNull || point.value === null ? + nullColor : + (colorAxis && typeof value !== 'undefined') ? + colorAxis.toColor(value, point) : + point.color || series.color); + if (color && point.color !== color) { + point.color = color; + if (series.options.legendType === 'point' && point.legendItem) { + series.chart.legend.colorizeItem(point, point.visible); + } + } + }); + } + /* eslint-enable valid-jsdoc */ + }; + + }); + _registerModule(_modules, 'Core/Axis/ColorAxis.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Chart/Chart.js'], _modules['Core/Color.js'], _modules['Core/Globals.js'], _modules['Core/Legend.js'], _modules['Mixins/LegendSymbol.js'], _modules['Core/Series/Point.js'], _modules['Core/Utilities.js']], function (Axis, Chart, Color, H, Legend, LegendSymbolMixin, Point, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, + b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, + b) { d.__proto__ = b; }) || + function (d, + b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + })(); + var color = Color.parse; + var noop = H.noop; + var addEvent = U.addEvent, + erase = U.erase, + extend = U.extend, + Fx = U.Fx, + isNumber = U.isNumber, + merge = U.merge, + pick = U.pick, + splat = U.splat; + /** + * Color axis types + * + * @typedef {"linear"|"logarithmic"} Highcharts.ColorAxisTypeValue + */ + ''; // detach doclet above + var Series = H.Series, + colorPointMixin = H.colorPointMixin, + colorSeriesMixin = H.colorSeriesMixin; + extend(Series.prototype, colorSeriesMixin); + extend(Point.prototype, colorPointMixin); + Chart.prototype.collectionsWithUpdate.push('colorAxis'); + Chart.prototype.collectionsWithInit.colorAxis = [Chart.prototype.addColorAxis]; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The ColorAxis object for inclusion in gradient legends. + * + * @class + * @name Highcharts.ColorAxis + * @augments Highcharts.Axis + * + * @param {Highcharts.Chart} chart + * The related chart of the color axis. + * + * @param {Highcharts.ColorAxisOptions} userOptions + * The color axis options for initialization. + */ + var ColorAxis = /** @class */ (function (_super) { + __extends(ColorAxis, _super); + /* * + * + * Constructors + * + * */ + /** + * @private + */ + function ColorAxis(chart, userOptions) { + var _this = _super.call(this, + chart, + userOptions) || this; + _this.beforePadding = false; // Prevents unnecessary padding with `hc-more` + _this.chart = void 0; + _this.coll = 'colorAxis'; + _this.dataClasses = void 0; + _this.legendItem = void 0; + _this.legendItems = void 0; + _this.name = ''; // Prevents 'undefined' in legend in IE8 + _this.options = void 0; + _this.stops = void 0; + _this.visible = true; + _this.init(chart, userOptions); + return _this; + } + /* * + * + * Static Functions + * + * */ + /** + * Build options to keep layout params on init and update. + * @private + */ + ColorAxis.buildOptions = function (chart, options, userOptions) { + var legend = chart.options.legend || {}, + horiz = userOptions.layout ? + userOptions.layout !== 'vertical' : + legend.layout !== 'vertical'; + return merge(options, { + side: horiz ? 2 : 1, + reversed: !horiz + }, userOptions, { + opposite: !horiz, + showEmpty: false, + title: null, + visible: legend.enabled && + (userOptions ? userOptions.visible !== false : true) + }); + }; + /* * + * + * Functions + * + * */ + /** + * Initializes the color axis. + * + * @function Highcharts.ColorAxis#init + * + * @param {Highcharts.Chart} chart + * The related chart of the color axis. + * + * @param {Highcharts.ColorAxisOptions} userOptions + * The color axis options for initialization. + */ + ColorAxis.prototype.init = function (chart, userOptions) { + var axis = this; + var options = ColorAxis.buildOptions(// Build the options + chart, + ColorAxis.defaultOptions, + userOptions); + axis.coll = 'colorAxis'; + _super.prototype.init.call(this, chart, options); + // Base init() pushes it to the xAxis array, now pop it again + // chart[this.isXAxis ? 'xAxis' : 'yAxis'].pop(); + // Prepare data classes + if (userOptions.dataClasses) { + axis.initDataClasses(userOptions); + } + axis.initStops(); + // Override original axis properties + axis.horiz = !options.opposite; + axis.zoomEnabled = false; + }; + /** + * @private + */ + ColorAxis.prototype.initDataClasses = function (userOptions) { + var axis = this; + var chart = axis.chart, + dataClasses, + colorCounter = 0, + colorCount = chart.options.chart.colorCount, + options = axis.options, + len = userOptions.dataClasses.length; + axis.dataClasses = dataClasses = []; + axis.legendItems = []; + userOptions.dataClasses.forEach(function (dataClass, i) { + var colors; + dataClass = merge(dataClass); + dataClasses.push(dataClass); + if (!chart.styledMode && dataClass.color) { + return; + } + if (options.dataClassColor === 'category') { + if (!chart.styledMode) { + colors = chart.options.colors; + colorCount = colors.length; + dataClass.color = colors[colorCounter]; + } + dataClass.colorIndex = colorCounter; + // increase and loop back to zero + colorCounter++; + if (colorCounter === colorCount) { + colorCounter = 0; + } + } + else { + dataClass.color = color(options.minColor).tweenTo(color(options.maxColor), len < 2 ? 0.5 : i / (len - 1) // #3219 + ); + } + }); + }; + /** + * Returns true if the series has points at all. + * + * @function Highcharts.ColorAxis#hasData + * + * @return {boolean} + * True, if the series has points, otherwise false. + */ + ColorAxis.prototype.hasData = function () { + return !!(this.tickPositions || []).length; + }; + /** + * Override so that ticks are not added in data class axes (#6914) + * @private + */ + ColorAxis.prototype.setTickPositions = function () { + if (!this.dataClasses) { + return _super.prototype.setTickPositions.call(this); + } + }; + /** + * @private + */ + ColorAxis.prototype.initStops = function () { + var axis = this; + axis.stops = axis.options.stops || [ + [0, axis.options.minColor], + [1, axis.options.maxColor] + ]; + axis.stops.forEach(function (stop) { + stop.color = color(stop[1]); + }); + }; + /** + * Extend the setOptions method to process extreme colors and color stops. + * @private + */ + ColorAxis.prototype.setOptions = function (userOptions) { + var axis = this; + _super.prototype.setOptions.call(this, userOptions); + axis.options.crosshair = axis.options.marker; + }; + /** + * @private + */ + ColorAxis.prototype.setAxisSize = function () { + var axis = this; + var symbol = axis.legendSymbol; + var chart = axis.chart; + var legendOptions = chart.options.legend || {}; + var x, + y, + width, + height; + if (symbol) { + this.left = x = symbol.attr('x'); + this.top = y = symbol.attr('y'); + this.width = width = symbol.attr('width'); + this.height = height = symbol.attr('height'); + this.right = chart.chartWidth - x - width; + this.bottom = chart.chartHeight - y - height; + this.len = this.horiz ? width : height; + this.pos = this.horiz ? x : y; + } + else { + // Fake length for disabled legend to avoid tick issues + // and such (#5205) + this.len = (this.horiz ? + legendOptions.symbolWidth : + legendOptions.symbolHeight) || ColorAxis.defaultLegendLength; + } + }; + /** + * @private + */ + ColorAxis.prototype.normalizedValue = function (value) { + var axis = this; + if (axis.logarithmic) { + value = axis.logarithmic.log2lin(value); + } + return 1 - ((axis.max - value) / + ((axis.max - axis.min) || 1)); + }; + /** + * Translate from a value to a color. + * @private + */ + ColorAxis.prototype.toColor = function (value, point) { + var axis = this; + var dataClasses = axis.dataClasses; + var stops = axis.stops; + var pos, + from, + to, + color, + dataClass, + i; + if (dataClasses) { + i = dataClasses.length; + while (i--) { + dataClass = dataClasses[i]; + from = dataClass.from; + to = dataClass.to; + if ((typeof from === 'undefined' || value >= from) && + (typeof to === 'undefined' || value <= to)) { + color = dataClass.color; + if (point) { + point.dataClass = i; + point.colorIndex = dataClass.colorIndex; + } + break; + } + } + } + else { + pos = axis.normalizedValue(value); + i = stops.length; + while (i--) { + if (pos > stops[i][0]) { + break; + } + } + from = stops[i] || stops[i + 1]; + to = stops[i + 1] || from; + // The position within the gradient + pos = 1 - (to[0] - pos) / ((to[0] - from[0]) || 1); + color = from.color.tweenTo(to.color, pos); + } + return color; + }; + /** + * Override the getOffset method to add the whole axis groups inside the + * legend. + * @private + */ + ColorAxis.prototype.getOffset = function () { + var axis = this; + var group = axis.legendGroup; + var sideOffset = axis.chart.axisOffset[axis.side]; + if (group) { + // Hook for the getOffset method to add groups to this parent + // group + axis.axisParent = group; + // Call the base + _super.prototype.getOffset.call(this); + // First time only + if (!axis.added) { + axis.added = true; + axis.labelLeft = 0; + axis.labelRight = axis.width; + } + // Reset it to avoid color axis reserving space + axis.chart.axisOffset[axis.side] = sideOffset; + } + }; + /** + * Create the color gradient. + * @private + */ + ColorAxis.prototype.setLegendColor = function () { + var axis = this; + var horiz = axis.horiz; + var reversed = axis.reversed; + var one = reversed ? 1 : 0; + var zero = reversed ? 0 : 1; + var grad = horiz ? [one, 0, + zero, 0] : [0, + zero, 0, + one]; // #3190 + axis.legendColor = { + linearGradient: { + x1: grad[0], + y1: grad[1], + x2: grad[2], + y2: grad[3] + }, + stops: axis.stops + }; + }; + /** + * The color axis appears inside the legend and has its own legend symbol. + * @private + */ + ColorAxis.prototype.drawLegendSymbol = function (legend, item) { + var axis = this; + var padding = legend.padding; + var legendOptions = legend.options; + var horiz = axis.horiz; + var width = pick(legendOptions.symbolWidth, + horiz ? ColorAxis.defaultLegendLength : 12); + var height = pick(legendOptions.symbolHeight, + horiz ? 12 : ColorAxis.defaultLegendLength); + var labelPadding = pick(legendOptions.labelPadding, + horiz ? 16 : 30); + var itemDistance = pick(legendOptions.itemDistance, 10); + this.setLegendColor(); + // Create the gradient + item.legendSymbol = this.chart.renderer.rect(0, legend.baseline - 11, width, height).attr({ + zIndex: 1 + }).add(item.legendGroup); + // Set how much space this legend item takes up + axis.legendItemWidth = width + padding + (horiz ? itemDistance : labelPadding); + axis.legendItemHeight = height + padding + (horiz ? labelPadding : 0); + }; + /** + * Fool the legend. + * @private + */ + ColorAxis.prototype.setState = function (state) { + this.series.forEach(function (series) { + series.setState(state); + }); + }; + /** + * @private + */ + ColorAxis.prototype.setVisible = function () { + }; + /** + * @private + */ + ColorAxis.prototype.getSeriesExtremes = function () { + var axis = this; + var series = axis.series; + var colorValArray, + colorKey, + colorValIndex, + pointArrayMap, + calculatedExtremes, + cSeries, + i = series.length, + yData, + j; + this.dataMin = Infinity; + this.dataMax = -Infinity; + while (i--) { // x, y, value, other + cSeries = series[i]; + colorKey = cSeries.colorKey = pick(cSeries.options.colorKey, cSeries.colorKey, cSeries.pointValKey, cSeries.zoneAxis, 'y'); + pointArrayMap = cSeries.pointArrayMap; + calculatedExtremes = cSeries[colorKey + 'Min'] && + cSeries[colorKey + 'Max']; + if (cSeries[colorKey + 'Data']) { + colorValArray = cSeries[colorKey + 'Data']; + } + else { + if (!pointArrayMap) { + colorValArray = cSeries.yData; + } + else { + colorValArray = []; + colorValIndex = pointArrayMap.indexOf(colorKey); + yData = cSeries.yData; + if (colorValIndex >= 0 && yData) { + for (j = 0; j < yData.length; j++) { + colorValArray.push(pick(yData[j][colorValIndex], yData[j])); + } + } + } + } + // If color key extremes are already calculated, use them. + if (calculatedExtremes) { + cSeries.minColorValue = cSeries[colorKey + 'Min']; + cSeries.maxColorValue = cSeries[colorKey + 'Max']; + } + else { + var cExtremes = Series.prototype.getExtremes.call(cSeries, + colorValArray); + cSeries.minColorValue = cExtremes.dataMin; + cSeries.maxColorValue = cExtremes.dataMax; + } + if (typeof cSeries.minColorValue !== 'undefined') { + this.dataMin = + Math.min(this.dataMin, cSeries.minColorValue); + this.dataMax = + Math.max(this.dataMax, cSeries.maxColorValue); + } + if (!calculatedExtremes) { + Series.prototype.applyExtremes.call(cSeries); + } + } + }; + /** + * Internal function to draw a crosshair. + * + * @function Highcharts.ColorAxis#drawCrosshair + * + * @param {Highcharts.PointerEventObject} [e] + * The event arguments from the modified pointer event, extended with + * `chartX` and `chartY` + * + * @param {Highcharts.Point} [point] + * The Point object if the crosshair snaps to points. + * + * @fires Highcharts.ColorAxis#event:afterDrawCrosshair + * @fires Highcharts.ColorAxis#event:drawCrosshair + */ + ColorAxis.prototype.drawCrosshair = function (e, point) { + var axis = this; + var plotX = point && point.plotX; + var plotY = point && point.plotY; + var axisPos = axis.pos; + var axisLen = axis.len; + var crossPos; + if (point) { + crossPos = axis.toPixels(point.getNestedProperty(point.series.colorKey)); + if (crossPos < axisPos) { + crossPos = axisPos - 2; + } + else if (crossPos > axisPos + axisLen) { + crossPos = axisPos + axisLen + 2; + } + point.plotX = crossPos; + point.plotY = axis.len - crossPos; + _super.prototype.drawCrosshair.call(this, e, point); + point.plotX = plotX; + point.plotY = plotY; + if (axis.cross && + !axis.cross.addedToColorAxis && + axis.legendGroup) { + axis.cross + .addClass('highcharts-coloraxis-marker') + .add(axis.legendGroup); + axis.cross.addedToColorAxis = true; + if (!axis.chart.styledMode && + axis.crosshair) { + axis.cross.attr({ + fill: axis.crosshair.color + }); + } + } + } + }; + /** + * @private + */ + ColorAxis.prototype.getPlotLinePath = function (options) { + var axis = this, + left = axis.left, + pos = options.translatedValue, + top = axis.top; + // crosshairs only + return isNumber(pos) ? // pos can be 0 (#3969) + (axis.horiz ? [ + ['M', pos - 4, top - 6], + ['L', pos + 4, top - 6], + ['L', pos, top], + ['Z'] + ] : [ + ['M', left, pos], + ['L', left - 6, pos + 6], + ['L', left - 6, pos - 6], + ['Z'] + ]) : + _super.prototype.getPlotLinePath.call(this, options); + }; + /** + * Updates a color axis instance with a new set of options. The options are + * merged with the existing options, so only new or altered options need to + * be specified. + * + * @function Highcharts.ColorAxis#update + * + * @param {Highcharts.ColorAxisOptions} newOptions + * The new options that will be merged in with existing options on the color + * axis. + * + * @param {boolean} [redraw] + * Whether to redraw the chart after the color axis is altered. If doing + * more operations on the chart, it is a good idea to set redraw to `false` + * and call {@link Highcharts.Chart#redraw} after. + */ + ColorAxis.prototype.update = function (newOptions, redraw) { + var axis = this, + chart = axis.chart, + legend = chart.legend, + updatedOptions = ColorAxis.buildOptions(chart, {}, + newOptions); + this.series.forEach(function (series) { + // Needed for Axis.update when choropleth colors change + series.isDirtyData = true; + }); + // When updating data classes, destroy old items and make sure new + // ones are created (#3207) + if (newOptions.dataClasses && legend.allItems || axis.dataClasses) { + axis.destroyItems(); + } + // Keep the options structure updated for export. Unlike xAxis and + // yAxis, the colorAxis is not an array. (#3207) + chart.options[axis.coll] = + merge(axis.userOptions, updatedOptions); + _super.prototype.update.call(this, updatedOptions, redraw); + if (axis.legendItem) { + axis.setLegendColor(); + legend.colorizeItem(this, true); + } + }; + /** + * Destroy color axis legend items. + * @private + */ + ColorAxis.prototype.destroyItems = function () { + var axis = this; + var chart = axis.chart; + if (axis.legendItem) { + chart.legend.destroyItem(axis); + } + else if (axis.legendItems) { + axis.legendItems.forEach(function (item) { + chart.legend.destroyItem(item); + }); + } + chart.isDirtyLegend = true; + }; + /** + * Removes the color axis and the related legend item. + * + * @function Highcharts.ColorAxis#remove + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart following the remove. + */ + ColorAxis.prototype.remove = function (redraw) { + this.destroyItems(); + _super.prototype.remove.call(this, redraw); + }; + /** + * Get the legend item symbols for data classes. + * @private + */ + ColorAxis.prototype.getDataClassLegendSymbols = function () { + var axis = this; + var chart = axis.chart; + var legendItems = axis.legendItems; + var legendOptions = chart.options.legend; + var valueDecimals = legendOptions.valueDecimals; + var valueSuffix = legendOptions.valueSuffix || ''; + var name; + if (!legendItems.length) { + axis.dataClasses.forEach(function (dataClass, i) { + var vis = true, + from = dataClass.from, + to = dataClass.to; + var numberFormatter = chart.numberFormatter; + // Assemble the default name. This can be overridden + // by legend.options.labelFormatter + name = ''; + if (typeof from === 'undefined') { + name = '< '; + } + else if (typeof to === 'undefined') { + name = '> '; + } + if (typeof from !== 'undefined') { + name += numberFormatter(from, valueDecimals) + valueSuffix; + } + if (typeof from !== 'undefined' && typeof to !== 'undefined') { + name += ' - '; + } + if (typeof to !== 'undefined') { + name += numberFormatter(to, valueDecimals) + valueSuffix; + } + // Add a mock object to the legend items + legendItems.push(extend({ + chart: chart, + name: name, + options: {}, + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + visible: true, + setState: noop, + isDataClass: true, + setVisible: function () { + vis = axis.visible = !vis; + axis.series.forEach(function (series) { + series.points.forEach(function (point) { + if (point.dataClass === i) { + point.setVisible(vis); + } + }); + }); + chart.legend.colorizeItem(this, vis); + } + }, dataClass)); + }); + } + return legendItems; + }; + /* * + * + * Static Functions + * + * */ + ColorAxis.defaultLegendLength = 200; + /** + * A color axis for series. Visually, the color + * axis will appear as a gradient or as separate items inside the + * legend, depending on whether the axis is scalar or based on data + * classes. + * + * For supported color formats, see the + * [docs article about colors](https://www.highcharts.com/docs/chart-design-and-style/colors). + * + * A scalar color axis is represented by a gradient. The colors either + * range between the [minColor](#colorAxis.minColor) and the + * [maxColor](#colorAxis.maxColor), or for more fine grained control the + * colors can be defined in [stops](#colorAxis.stops). Often times, the + * color axis needs to be adjusted to get the right color spread for the + * data. In addition to stops, consider using a logarithmic + * [axis type](#colorAxis.type), or setting [min](#colorAxis.min) and + * [max](#colorAxis.max) to avoid the colors being determined by + * outliers. + * + * When [dataClasses](#colorAxis.dataClasses) are used, the ranges are + * subdivided into separate classes like categories based on their + * values. This can be used for ranges between two values, but also for + * a true category. However, when your data is categorized, it may be as + * convenient to add each category to a separate series. + * + * Color axis does not work with: `sankey`, `sunburst`, `dependencywheel`, + * `networkgraph`, `wordcloud`, `venn`, `gauge` and `solidgauge` series + * types. + * + * Since v7.2.0 `colorAxis` can also be an array of options objects. + * + * See [the Axis object](/class-reference/Highcharts.Axis) for + * programmatic access to the axis. + * + * @sample {highcharts} highcharts/coloraxis/custom-color-key + * Column chart with color axis + * @sample {highcharts} highcharts/coloraxis/horizontal-layout + * Horizontal layout + * @sample {highmaps} maps/coloraxis/dataclasscolor + * With data classes + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor + * Min color and max color + * + * @extends xAxis + * @excluding alignTicks, allowDecimals, alternateGridColor, breaks, + * categories, crosshair, dateTimeLabelFormats, height, left, + * lineWidth, linkedTo, maxZoom, minRange, minTickInterval, + * offset, opposite, pane, plotBands, plotLines, + * reversedStacks, showEmpty, title, top, width, zoomEnabled + * @product highcharts highstock highmaps + * @type {*|Array<*>} + * @optionparent colorAxis + * @ignore + */ + ColorAxis.defaultOptions = { + /** + * Whether to allow decimals on the color axis. + * @type {boolean} + * @default true + * @product highcharts highstock highmaps + * @apioption colorAxis.allowDecimals + */ + /** + * Determines how to set each data class' color if no individual + * color is set. The default value, `tween`, computes intermediate + * colors between `minColor` and `maxColor`. The other possible + * value, `category`, pulls colors from the global or chart specific + * [colors](#colors) array. + * + * @sample {highmaps} maps/coloraxis/dataclasscolor/ + * Category colors + * + * @type {string} + * @default tween + * @product highcharts highstock highmaps + * @validvalue ["tween", "category"] + * @apioption colorAxis.dataClassColor + */ + /** + * An array of data classes or ranges for the choropleth map. If + * none given, the color axis is scalar and values are distributed + * as a gradient between the minimum and maximum colors. + * + * @sample {highmaps} maps/demo/data-class-ranges/ + * Multiple ranges + * + * @sample {highmaps} maps/demo/data-class-two-ranges/ + * Two ranges + * + * @type {Array<*>} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses + */ + /** + * The layout of the color axis. Can be `'horizontal'` or `'vertical'`. + * If none given, the color axis has the same layout as the legend. + * + * @sample highcharts/coloraxis/horizontal-layout/ + * Horizontal color axis layout with vertical legend + * + * @type {string|undefined} + * @since 7.2.0 + * @product highcharts highstock highmaps + * @apioption colorAxis.layout + */ + /** + * The color of each data class. If not set, the color is pulled + * from the global or chart-specific [colors](#colors) array. In + * styled mode, this option is ignored. Instead, use colors defined + * in CSS. + * + * @sample {highmaps} maps/demo/data-class-two-ranges/ + * Explicit colors + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.color + */ + /** + * The start of the value range that the data class represents, + * relating to the point value. + * + * The range of each `dataClass` is closed in both ends, but can be + * overridden by the next `dataClass`. + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.from + */ + /** + * The name of the data class as it appears in the legend. + * If no name is given, it is automatically created based on the + * `from` and `to` values. For full programmatic control, + * [legend.labelFormatter](#legend.labelFormatter) can be used. + * In the formatter, `this.from` and `this.to` can be accessed. + * + * @sample {highmaps} maps/coloraxis/dataclasses-name/ + * Named data classes + * + * @sample {highmaps} maps/coloraxis/dataclasses-labelformatter/ + * Formatted data classes + * + * @type {string} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.name + */ + /** + * The end of the value range that the data class represents, + * relating to the point value. + * + * The range of each `dataClass` is closed in both ends, but can be + * overridden by the next `dataClass`. + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.to + */ + /** @ignore-option */ + lineWidth: 0, + /** + * Padding of the min value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. + * + * @product highcharts highstock highmaps + */ + minPadding: 0, + /** + * The maximum value of the axis in terms of map point values. If + * `null`, the max value is automatically calculated. If the + * `endOnTick` option is true, the max value might be rounded up. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Explicit min and max to reduce the effect of outliers + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.max + */ + /** + * The minimum value of the axis in terms of map point values. If + * `null`, the min value is automatically calculated. If the + * `startOnTick` option is true, the min value might be rounded + * down. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Explicit min and max to reduce the effect of outliers + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.min + */ + /** + * Padding of the max value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. + * + * @product highcharts highstock highmaps + */ + maxPadding: 0, + /** + * Color of the grid lines extending from the axis across the + * gradient. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Grid lines demonstrated + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #e6e6e6 + * @product highcharts highstock highmaps + * @apioption colorAxis.gridLineColor + */ + /** + * The width of the grid lines extending from the axis across the + * gradient of a scalar color axis. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Grid lines demonstrated + * + * @product highcharts highstock highmaps + */ + gridLineWidth: 1, + /** + * The interval of the tick marks in axis units. When `null`, the + * tick interval is computed to approximately follow the + * `tickPixelInterval`. + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.tickInterval + */ + /** + * If [tickInterval](#colorAxis.tickInterval) is `null` this option + * sets the approximate pixel interval of the tick marks. + * + * @product highcharts highstock highmaps + */ + tickPixelInterval: 72, + /** + * Whether to force the axis to start on a tick. Use this option + * with the `maxPadding` option to control the axis start. + * + * @product highcharts highstock highmaps + */ + startOnTick: true, + /** + * Whether to force the axis to end on a tick. Use this option with + * the [maxPadding](#colorAxis.maxPadding) option to control the + * axis end. + * + * @product highcharts highstock highmaps + */ + endOnTick: true, + /** @ignore */ + offset: 0, + /** + * The triangular marker on a scalar color axis that points to the + * value of the hovered area. To disable the marker, set + * `marker: null`. + * + * @sample {highmaps} maps/coloraxis/marker/ + * Black marker + * + * @declare Highcharts.PointMarkerOptionsObject + * @product highcharts highstock highmaps + */ + marker: { + /** + * Animation for the marker as it moves between values. Set to + * `false` to disable animation. Defaults to `{ duration: 50 }`. + * + * @type {boolean|Partial} + * @product highcharts highstock highmaps + */ + animation: { + /** @internal */ + duration: 50 + }, + /** @internal */ + width: 0.01, + /** + * The color of the marker. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + */ + color: '#999999' + }, + /** + * The axis labels show the number for each tick. + * + * For more live examples on label options, see [xAxis.labels in the + * Highcharts API.](/highcharts#xAxis.labels) + * + * @extends xAxis.labels + * @product highcharts highstock highmaps + */ + labels: { + /** + * How to handle overflowing labels on horizontal color axis. If set + * to `"allow"`, it will not be aligned at all. By default it + * `"justify"` labels inside the chart area. If there is room to + * move it, it will be aligned to the edge, else it will be removed. + * + * @validvalue ["allow", "justify"] + * @product highcharts highstock highmaps + */ + overflow: 'justify', + rotation: 0 + }, + /** + * The color to represent the minimum of the color axis. Unless + * [dataClasses](#colorAxis.dataClasses) or + * [stops](#colorAxis.stops) are set, the gradient starts at this + * value. + * + * If dataClasses are set, the color is based on minColor and + * maxColor unless a color is set for each data class, or the + * [dataClassColor](#colorAxis.dataClassColor) is set. + * + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor/ + * Min and max colors on scalar (gradient) axis + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor-dataclasses/ + * On data classes + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + */ + minColor: '#e6ebf5', + /** + * The color to represent the maximum of the color axis. Unless + * [dataClasses](#colorAxis.dataClasses) or + * [stops](#colorAxis.stops) are set, the gradient ends at this + * value. + * + * If dataClasses are set, the color is based on minColor and + * maxColor unless a color is set for each data class, or the + * [dataClassColor](#colorAxis.dataClassColor) is set. + * + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor/ + * Min and max colors on scalar (gradient) axis + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor-dataclasses/ + * On data classes + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + */ + maxColor: '#003399', + /** + * Color stops for the gradient of a scalar color axis. Use this in + * cases where a linear gradient between a `minColor` and `maxColor` + * is not sufficient. The stops is an array of tuples, where the + * first item is a float between 0 and 1 assigning the relative + * position in the gradient, and the second item is the color. + * + * @sample {highmaps} maps/demo/heatmap/ + * Heatmap with three color stops + * + * @type {Array>} + * @product highcharts highstock highmaps + * @apioption colorAxis.stops + */ + /** + * The pixel length of the main tick marks on the color axis. + */ + tickLength: 5, + /** + * The type of interpolation to use for the color axis. Can be + * `linear` or `logarithmic`. + * + * @sample highcharts/coloraxis/logarithmic-with-emulate-negative-values/ + * Logarithmic color axis with extension to emulate negative + * values + * + * @type {Highcharts.ColorAxisTypeValue} + * @default linear + * @product highcharts highstock highmaps + * @apioption colorAxis.type + */ + /** + * Whether to reverse the axis so that the highest number is closest + * to the origin. Defaults to `false` in a horizontal legend and + * `true` in a vertical legend, where the smallest value starts on + * top. + * + * @type {boolean} + * @product highcharts highstock highmaps + * @apioption colorAxis.reversed + */ + /** + * @product highcharts highstock highmaps + * @excluding afterBreaks, pointBreak, pointInBreak + * @apioption colorAxis.events + */ + /** + * Fires when the legend item belonging to the colorAxis is clicked. + * One parameter, `event`, is passed to the function. + * + * @type {Function} + * @product highcharts highstock highmaps + * @apioption colorAxis.events.legendItemClick + */ + /** + * Whether to display the colorAxis in the legend. + * + * @sample highcharts/coloraxis/hidden-coloraxis-with-3d-chart/ + * Hidden color axis with 3d chart + * + * @see [heatmap.showInLegend](#series.heatmap.showInLegend) + * + * @since 4.2.7 + * @product highcharts highstock highmaps + */ + showInLegend: true + }; + /** + * @private + */ + ColorAxis.keepProps = [ + 'legendGroup', + 'legendItemHeight', + 'legendItemWidth', + 'legendItem', + 'legendSymbol' + ]; + return ColorAxis; + }(Axis)); + // Properties to preserve after destroy, for Axis.update (#5881, #6025). + Array.prototype.push.apply(Axis.keepProps, ColorAxis.keepProps); + H.ColorAxis = ColorAxis; + /** + * Handle animation of the color attributes directly + * + * @private + * @function Highcharts.Fx#fillSetter + */ /** + * Handle animation of the color attributes directly + * + * @private + * @function Highcharts.Fx#strokeSetter + */ + ['fill', 'stroke'].forEach(function (prop) { + Fx.prototype[prop + 'Setter'] = function () { + this.elem.attr(prop, color(this.start).tweenTo(color(this.end), this.pos), null, true); + }; + }); + // Extend the chart getAxes method to also get the color axis + addEvent(Chart, 'afterGetAxes', function () { + var chart = this, + options = chart.options; + this.colorAxis = []; + if (options.colorAxis) { + options.colorAxis = splat(options.colorAxis); + options.colorAxis.forEach(function (axisOptions, i) { + axisOptions.index = i; + new ColorAxis(chart, axisOptions); // eslint-disable-line no-new + }); + } + }); + // Add colorAxis to series axisTypes + addEvent(Series, 'bindAxes', function () { + var axisTypes = this.axisTypes; + if (!axisTypes) { + this.axisTypes = ['colorAxis']; + } + else if (axisTypes.indexOf('colorAxis') === -1) { + axisTypes.push('colorAxis'); + } + }); + // Add the color axis. This also removes the axis' own series to prevent + // them from showing up individually. + addEvent(Legend, 'afterGetAllItems', function (e) { + var colorAxisItems = [], + colorAxes = this.chart.colorAxis || [], + options, + i; + colorAxes.forEach(function (colorAxis) { + options = colorAxis.options; + if (options && options.showInLegend) { + // Data classes + if (options.dataClasses && options.visible) { + colorAxisItems = colorAxisItems.concat(colorAxis.getDataClassLegendSymbols()); + // Gradient legend + } + else if (options.visible) { + // Add this axis on top + colorAxisItems.push(colorAxis); + } + // If dataClasses are defined or showInLegend option is not set to + // true, do not add color axis' series to legend. + colorAxis.series.forEach(function (series) { + if (!series.options.showInLegend || options.dataClasses) { + if (series.options.legendType === 'point') { + series.points.forEach(function (point) { + erase(e.allItems, point); + }); + } + else { + erase(e.allItems, series); + } + } + }); + } + }); + i = colorAxisItems.length; + while (i--) { + e.allItems.unshift(colorAxisItems[i]); + } + }); + addEvent(Legend, 'afterColorizeItem', function (e) { + if (e.visible && e.item.legendColor) { + e.item.legendSymbol.attr({ + fill: e.item.legendColor + }); + } + }); + // Updates in the legend need to be reflected in the color axis (6888) + addEvent(Legend, 'afterUpdate', function () { + var colorAxes = this.chart.colorAxis; + if (colorAxes) { + colorAxes.forEach(function (colorAxis) { + colorAxis.update({}, arguments[2]); + }); + } + }); + // Calculate and set colors for points + addEvent(Series, 'afterTranslate', function () { + if (this.chart.colorAxis && + this.chart.colorAxis.length || + this.colorAttribs) { + this.translateColors(); + } + }); + + return ColorAxis; + }); + _registerModule(_modules, 'masters/modules/coloraxis.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/current-date-indicator.js b/highcharts/modules/current-date-indicator.js new file mode 100644 index 0000000..4754f5d --- /dev/null +++ b/highcharts/modules/current-date-indicator.js @@ -0,0 +1,13 @@ +/* + Highcharts Gantt JS v8.2.0 (2020-08-20) + + CurrentDateIndicator + + (c) 2010-2019 Lars A. V. Cabrera + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/current-date-indicator",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,d,c,b){a.hasOwnProperty(d)||(a[d]=b.apply(null,c))}a=a?a._modules:{};b(a,"Extensions/CurrentDateIndication.js",[a["Core/Globals.js"],a["Core/Options.js"],a["Core/Utilities.js"],a["Core/Axis/PlotLineOrBand.js"]], +function(a,b,c,e){var d=b.dateFormat;b=c.addEvent;var f=c.merge;c=c.wrap;var g={currentDateIndicator:!0,color:"#ccd6eb",width:2,label:{format:"%a, %b %d %Y, %H:%M",formatter:function(a,b){return d(b,a)},rotation:0,style:{fontSize:"10px"}}};b(a.Axis,"afterSetOptions",function(){var a=this.options,b=a.currentDateIndicator;b&&(b="object"===typeof b?f(g,b):f(g),b.value=new Date,a.plotLines||(a.plotLines=[]),a.plotLines.push(b))});b(e,"render",function(){this.label&&this.label.attr({text:this.getLabelText(this.options.label)})}); +c(e.prototype,"getLabelText",function(a,b){var c=this.options;return c.currentDateIndicator&&c.label&&"function"===typeof c.label.formatter?(c.value=new Date,c.label.formatter.call(this,c.value,c.label.format)):a.call(this,b)})});b(a,"masters/modules/current-date-indicator.src.js",[],function(){})}); +//# sourceMappingURL=current-date-indicator.js.map \ No newline at end of file diff --git a/highcharts/modules/current-date-indicator.js.map b/highcharts/modules/current-date-indicator.js.map new file mode 100644 index 0000000..04a965a --- /dev/null +++ b/highcharts/modules/current-date-indicator.js.map @@ -0,0 +1 @@ +{"version":3,"file":"current-date-indicator.js.map","lineCount":12,"mappings":"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","sources":["current-date-indicator.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","O","U","PlotLineOrBand","dateFormat","addEvent","merge","wrap","defaultConfig","currentDateIndicator","color","width","label","format","formatter","value","rotation","style","fontSize","Axis","options","cdiOptions","Date","plotLines","push","attr","text","getLabelText","prototype","defaultMethod","defaultLabelOptions","call"]} \ No newline at end of file diff --git a/highcharts/modules/current-date-indicator.src.js b/highcharts/modules/current-date-indicator.src.js new file mode 100644 index 0000000..fb4025c --- /dev/null +++ b/highcharts/modules/current-date-indicator.src.js @@ -0,0 +1,135 @@ +/** + * @license Highcharts Gantt JS v8.2.0 (2020-08-20) + * + * CurrentDateIndicator + * + * (c) 2010-2019 Lars A. V. Cabrera + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/current-date-indicator', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'Extensions/CurrentDateIndication.js', [_modules['Core/Globals.js'], _modules['Core/Options.js'], _modules['Core/Utilities.js'], _modules['Core/Axis/PlotLineOrBand.js']], function (H, O, U, PlotLineOrBand) { + /* * + * + * (c) 2016-2020 Highsoft AS + * + * Author: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var dateFormat = O.dateFormat; + var addEvent = U.addEvent, + merge = U.merge, + wrap = U.wrap; + var Axis = H.Axis; + var defaultConfig = { + /** + * Show an indicator on the axis for the current date and time. Can be a + * boolean or a configuration object similar to + * [xAxis.plotLines](#xAxis.plotLines). + * + * @sample gantt/current-date-indicator/demo + * Current date indicator enabled + * @sample gantt/current-date-indicator/object-config + * Current date indicator with custom options + * + * @declare Highcharts.AxisCurrentDateIndicatorOptions + * @type {boolean|*} + * @default true + * @extends xAxis.plotLines + * @excluding value + * @product gantt + * @apioption xAxis.currentDateIndicator + */ + currentDateIndicator: true, + color: '#ccd6eb', + width: 2, + /** + * @declare Highcharts.AxisCurrentDateIndicatorLabelOptions + */ + label: { + /** + * Format of the label. This options is passed as the fist argument to + * [dateFormat](/class-reference/Highcharts#dateFormat) function. + * + * @type {string} + * @default '%a, %b %d %Y, %H:%M' + * @product gantt + * @apioption xAxis.currentDateIndicator.label.format + */ + format: '%a, %b %d %Y, %H:%M', + formatter: function (value, format) { + return dateFormat(format, value); + }, + rotation: 0, + /** + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + fontSize: '10px' + } + } + }; + /* eslint-disable no-invalid-this */ + addEvent(Axis, 'afterSetOptions', function () { + var options = this.options, + cdiOptions = options.currentDateIndicator; + if (cdiOptions) { + cdiOptions = typeof cdiOptions === 'object' ? + merge(defaultConfig, cdiOptions) : merge(defaultConfig); + cdiOptions.value = new Date(); + if (!options.plotLines) { + options.plotLines = []; + } + options.plotLines.push(cdiOptions); + } + }); + addEvent(PlotLineOrBand, 'render', function () { + // If the label already exists, update its text + if (this.label) { + this.label.attr({ + text: this.getLabelText(this.options.label) + }); + } + }); + wrap(PlotLineOrBand.prototype, 'getLabelText', function (defaultMethod, defaultLabelOptions) { + var options = this.options; + if (options.currentDateIndicator && options.label && + typeof options.label.formatter === 'function') { + options.value = new Date(); + return options.label.formatter + .call(this, options.value, options.label.format); + } + return defaultMethod.call(this, defaultLabelOptions); + }); + + }); + _registerModule(_modules, 'masters/modules/current-date-indicator.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/cylinder.js b/highcharts/modules/cylinder.js new file mode 100644 index 0000000..78f04c8 --- /dev/null +++ b/highcharts/modules/cylinder.js @@ -0,0 +1,17 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Highcharts cylinder module + + (c) 2010-2019 Kacper Madej + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/cylinder",["highcharts","highcharts/highcharts-3d"],function(g){b(g);b.Highcharts=g;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function g(b,h,g,f){b.hasOwnProperty(h)||(b[h]=f.apply(null,g))}b=b?b._modules:{};g(b,"Series/CylinderSeries.js",[b["Core/Globals.js"],b["Core/Color.js"],b["Extensions/Math3D.js"],b["Core/Utilities.js"]], +function(b,g,l,f){var h=g.parse,r=l.perspective;g=f.merge;var t=f.pick;l=f.seriesType;var u=b.charts,v=b.deg2rad;f=b.Renderer.prototype;var w=f.cuboidPath,k=function(a){return!a.some(function(a){return"C"===a[0]})};l("cylinder","column",{},{},{shapeType:"cylinder",hasNewShapeType:b.seriesTypes.column.prototype.pointClass.prototype.hasNewShapeType});b=g(f.elements3d.cuboid,{parts:["top","bottom","front","back"],pathType:"cylinder",fillSetter:function(a){this.singleSetterForParts("fill",null,{front:a, +back:a,top:h(a).brighten(.1).get(),bottom:h(a).brighten(-.1).get()});this.color=this.fill=a;return this}});f.elements3d.cylinder=b;f.cylinder=function(a){return this.element3d("cylinder",a)};f.cylinderPath=function(a){var c=u[this.chartIndex],d=w.call(this,a),e=!d.isTop,b=!d.isFront,f=this.getCylinderEnd(c,a);a=this.getCylinderEnd(c,a,!0);return{front:this.getCylinderFront(f,a),back:this.getCylinderBack(f,a),top:f,bottom:a,zIndexes:{top:e?3:0,bottom:e?0:3,front:b?2:1,back:b?1:2,group:d.zIndexes.group}}}; +f.getCylinderFront=function(a,c){a=a.slice(0,3);if(k(c)){var d=c[0];"M"===d[0]&&(a.push(c[2]),a.push(c[1]),a.push(["L",d[1],d[2]]))}else{d=c[0];var e=c[1];c=c[2];"M"===d[0]&&"C"===e[0]&&"C"===c[0]&&(a.push(["L",c[5],c[6]]),a.push(["C",c[3],c[4],c[1],c[2],e[5],e[6]]),a.push(["C",e[3],e[4],e[1],e[2],d[1],d[2]]))}a.push(["Z"]);return a};f.getCylinderBack=function(a,c){var d=[];if(k(a)){var e=a[0],b=a[2];"M"===e[0]&&"L"===b[0]&&(d.push(["M",b[1],b[2]]),d.push(a[3]),d.push(["L",e[1],e[2]]))}else"C"=== +a[2][0]&&d.push(["M",a[2][5],a[2][6]]),d.push(a[3],a[4]);k(c)?(e=c[0],"M"===e[0]&&(d.push(["L",e[1],e[2]]),d.push(c[3]),d.push(c[2]))):(a=c[2],e=c[3],c=c[4],"C"===a[0]&&"C"===e[0]&&"C"===c[0]&&(d.push(["L",c[5],c[6]]),d.push(["C",c[3],c[4],c[1],c[2],e[5],e[6]]),d.push(["C",e[3],e[4],e[1],e[2],a[5],a[6]])));d.push(["Z"]);return d};f.getCylinderEnd=function(a,c,d){var e=t(c.depth,c.width),b=Math.min(c.width,e)/2,f=v*(a.options.chart.options3d.beta-90+(c.alphaCorrection||0));d=c.y+(d?c.height:0);var g= +.5519*b,h=c.width/2+c.x,l=e/2+c.z,m=[{x:0,y:d,z:b},{x:g,y:d,z:b},{x:b,y:d,z:g},{x:b,y:d,z:0},{x:b,y:d,z:-g},{x:g,y:d,z:-b},{x:0,y:d,z:-b},{x:-g,y:d,z:-b},{x:-b,y:d,z:-g},{x:-b,y:d,z:0},{x:-b,y:d,z:g},{x:-g,y:d,z:b},{x:0,y:d,z:b}],k=Math.cos(f),q=Math.sin(f),n,p;m.forEach(function(a,b){n=a.x;p=a.z;m[b].x=n*k-p*q+h;m[b].z=p*k+n*q+l});a=r(m,a,!0);return 2.5>Math.abs(a[3].y-a[9].y)&&2.5>Math.abs(a[0].y-a[6].y)?this.toLinePath([a[0],a[3],a[6],a[9]],!0):this.getCurvedPath(a)};f.getCurvedPath=function(a){var b= +[["M",a[0].x,a[0].y]],d=a.length-2,e;for(e=1;e|null|*>} + * @extends series.column.data + * @product highcharts highstock + * @apioption series.cylinder.data + */ + // cylinder extends cuboid + cylinderMethods = merge(RendererProto.elements3d.cuboid, { + parts: ['top', 'bottom', 'front', 'back'], + pathType: 'cylinder', + fillSetter: function (fill) { + this.singleSetterForParts('fill', null, { + front: fill, + back: fill, + top: color(fill).brighten(0.1).get(), + bottom: color(fill).brighten(-0.1).get() + }); + // fill for animation getter (#6776) + this.color = this.fill = fill; + return this; + } + }); + RendererProto.elements3d.cylinder = cylinderMethods; + RendererProto.cylinder = function (shapeArgs) { + return this.element3d('cylinder', shapeArgs); + }; + // Generates paths and zIndexes. + RendererProto.cylinderPath = function (shapeArgs) { + var renderer = this, + chart = charts[renderer.chartIndex], + // decide zIndexes of parts based on cubiod logic, for consistency. + cuboidData = cuboidPath.call(renderer, + shapeArgs), + isTopFirst = !cuboidData.isTop, + isFronFirst = !cuboidData.isFront, + top = renderer.getCylinderEnd(chart, + shapeArgs), + bottom = renderer.getCylinderEnd(chart, + shapeArgs, + true); + return { + front: renderer.getCylinderFront(top, bottom), + back: renderer.getCylinderBack(top, bottom), + top: top, + bottom: bottom, + zIndexes: { + top: isTopFirst ? 3 : 0, + bottom: isTopFirst ? 0 : 3, + front: isFronFirst ? 2 : 1, + back: isFronFirst ? 1 : 2, + group: cuboidData.zIndexes.group + } + }; + }; + // Returns cylinder Front path + RendererProto.getCylinderFront = function (topPath, bottomPath) { + var path = topPath.slice(0, 3); + if (isSimplified(bottomPath)) { + var move = bottomPath[0]; + if (move[0] === 'M') { + path.push(bottomPath[2]); + path.push(bottomPath[1]); + path.push(['L', move[1], move[2]]); + } + } + else { + var move = bottomPath[0], + curve1 = bottomPath[1], + curve2 = bottomPath[2]; + if (move[0] === 'M' && curve1[0] === 'C' && curve2[0] === 'C') { + path.push(['L', curve2[5], curve2[6]]); + path.push(['C', curve2[3], curve2[4], curve2[1], curve2[2], curve1[5], curve1[6]]); + path.push(['C', curve1[3], curve1[4], curve1[1], curve1[2], move[1], move[2]]); + } + } + path.push(['Z']); + return path; + }; + // Returns cylinder Back path + RendererProto.getCylinderBack = function (topPath, bottomPath) { + var path = []; + if (isSimplified(topPath)) { + var move = topPath[0], + line2 = topPath[2]; + if (move[0] === 'M' && line2[0] === 'L') { + path.push(['M', line2[1], line2[2]]); + path.push(topPath[3]); + // End at start + path.push(['L', move[1], move[2]]); + } + } + else { + if (topPath[2][0] === 'C') { + path.push(['M', topPath[2][5], topPath[2][6]]); + } + path.push(topPath[3], topPath[4]); + } + if (isSimplified(bottomPath)) { + var move = bottomPath[0]; + if (move[0] === 'M') { + path.push(['L', move[1], move[2]]); + path.push(bottomPath[3]); + path.push(bottomPath[2]); + } + } + else { + var curve2 = bottomPath[2], + curve3 = bottomPath[3], + curve4 = bottomPath[4]; + if (curve2[0] === 'C' && curve3[0] === 'C' && curve4[0] === 'C') { + path.push(['L', curve4[5], curve4[6]]); + path.push(['C', curve4[3], curve4[4], curve4[1], curve4[2], curve3[5], curve3[6]]); + path.push(['C', curve3[3], curve3[4], curve3[1], curve3[2], curve2[5], curve2[6]]); + } + } + path.push(['Z']); + return path; + }; + // Retruns cylinder path for top or bottom + RendererProto.getCylinderEnd = function (chart, shapeArgs, isBottom) { + // A half of the smaller one out of width or depth (optional, because + // there's no depth for a funnel that reuses the code) + var depth = pick(shapeArgs.depth, + shapeArgs.width), + radius = Math.min(shapeArgs.width, + depth) / 2, + // Approximated longest diameter + angleOffset = deg2rad * (chart.options.chart.options3d.beta - 90 + + (shapeArgs.alphaCorrection || 0)), + // Could be top or bottom of the cylinder + y = shapeArgs.y + (isBottom ? shapeArgs.height : 0), + // Use cubic Bezier curve to draw a cricle in x,z (y is constant). + // More math. at spencermortensen.com/articles/bezier-circle/ + c = 0.5519 * radius, + centerX = shapeArgs.width / 2 + shapeArgs.x, + centerZ = depth / 2 + shapeArgs.z, + // points could be generated in a loop, but readability will plummet + points = [{ + x: 0, + y: y, + z: radius + }, { + x: c, + y: y, + z: radius + }, { + x: radius, + y: y, + z: c + }, { + x: radius, + y: y, + z: 0 + }, { + x: radius, + y: y, + z: -c + }, { + x: c, + y: y, + z: -radius + }, { + x: 0, + y: y, + z: -radius + }, { + x: -c, + y: y, + z: -radius + }, { + x: -radius, + y: y, + z: -c + }, { + x: -radius, + y: y, + z: 0 + }, { + x: -radius, + y: y, + z: c + }, { + x: -c, + y: y, + z: radius + }, { + x: 0, + y: y, + z: radius + }], + cosTheta = Math.cos(angleOffset), + sinTheta = Math.sin(angleOffset), + perspectivePoints, + path, + x, + z; + // rotete to match chart's beta and translate to the shape center + points.forEach(function (point, i) { + x = point.x; + z = point.z; + // x′ = (x * cosθ − z * sinθ) + centerX + // z′ = (z * cosθ + x * sinθ) + centerZ + points[i].x = (x * cosTheta - z * sinTheta) + centerX; + points[i].z = (z * cosTheta + x * sinTheta) + centerZ; + }); + perspectivePoints = perspective(points, chart, true); + // check for sub-pixel curve issue, compare front and back edges + if (Math.abs(perspectivePoints[3].y - perspectivePoints[9].y) < 2.5 && + Math.abs(perspectivePoints[0].y - perspectivePoints[6].y) < 2.5) { + // use simplied shape + path = this.toLinePath([ + perspectivePoints[0], + perspectivePoints[3], + perspectivePoints[6], + perspectivePoints[9] + ], true); + } + else { + // or default curved path to imitate ellipse (2D circle) + path = this.getCurvedPath(perspectivePoints); + } + return path; + }; + // Returns curved path in format of: + // [ M, x, y, ...[C, cp1x, cp2y, cp2x, cp2y, epx, epy]*n_times ] + // (cp - control point, ep - end point) + RendererProto.getCurvedPath = function (points) { + var path = [['M', + points[0].x, + points[0].y]], + limit = points.length - 2, + i; + for (i = 1; i < limit; i += 3) { + path.push([ + 'C', + points[i].x, points[i].y, + points[i + 1].x, points[i + 1].y, + points[i + 2].x, points[i + 2].y + ]); + } + return path; + }; + + }); + _registerModule(_modules, 'masters/modules/cylinder.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/data.js b/highcharts/modules/data.js new file mode 100644 index 0000000..44f0a94 --- /dev/null +++ b/highcharts/modules/data.js @@ -0,0 +1,41 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Data module + + (c) 2012-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/data",["highcharts"],function(v){b(v);b.Highcharts=v;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function v(b,l,v,t){b.hasOwnProperty(l)||(b[l]=t.apply(null,v))}b=b?b._modules:{};v(b,"Extensions/Ajax.js",[b["Core/Globals.js"],b["Core/Utilities.js"]],function(b,l){var v=l.merge,t=l.objectEach;b.ajax=function(b){var p= +v(!0,{url:!1,type:"get",dataType:"json",success:!1,error:!1,data:!1,headers:{}},b);b={json:"application/json",xml:"application/xml",text:"text/plain",octet:"application/octet-stream"};var l=new XMLHttpRequest;if(!p.url)return!1;l.open(p.type.toUpperCase(),p.url,!0);p.headers["Content-Type"]||l.setRequestHeader("Content-Type",b[p.dataType]||b.text);t(p.headers,function(b,p){l.setRequestHeader(p,b)});l.onreadystatechange=function(){if(4===l.readyState){if(200===l.status){var b=l.responseText;if("json"=== +p.dataType)try{b=JSON.parse(b)}catch(C){p.error&&p.error(l,C);return}return p.success&&p.success(b)}p.error&&p.error(l,l.responseText)}};try{p.data=JSON.stringify(p.data)}catch(D){}l.send(p.data||!0)};b.getJSON=function(l,p){b.ajax({url:l,success:p,dataType:"json",headers:{"Content-Type":"text/plain"}})};return{ajax:b.ajax,getJSON:b.getJSON}});v(b,"Extensions/Data.js",[b["Core/Chart/Chart.js"],b["Core/Globals.js"],b["Core/Series/Point.js"],b["Core/Utilities.js"],b["Extensions/Ajax.js"]],function(b, +l,v,t,H){var p=t.addEvent,I=t.defined,D=t.extend,C=t.fireEvent,E=t.isNumber,A=t.merge,J=t.objectEach,K=t.pick,L=t.splat,F=H.ajax,M=l.win.document;t=function(){function b(a,c,f){this.options=this.rawColumns=this.firstRowAsNames=this.chartOptions=this.chart=void 0;this.dateFormats={"YYYY/mm/dd":{regex:/^([0-9]{4})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{1,2})$/,parser:function(a){return a?Date.UTC(+a[1],a[2]-1,+a[3]):NaN}},"dd/mm/YYYY":{regex:/^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{4})$/,parser:function(a){return a? +Date.UTC(+a[3],a[2]-1,+a[1]):NaN},alternative:"mm/dd/YYYY"},"mm/dd/YYYY":{regex:/^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{4})$/,parser:function(a){return a?Date.UTC(+a[3],a[1]-1,+a[2]):NaN}},"dd/mm/YY":{regex:/^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{2})$/,parser:function(a){if(!a)return NaN;var c=+a[3];c=c>(new Date).getFullYear()-2E3?c+1900:c+2E3;return Date.UTC(c,a[2]-1,+a[1])},alternative:"mm/dd/YY"},"mm/dd/YY":{regex:/^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{2})$/,parser:function(a){return a? +Date.UTC(+a[3]+2E3,a[1]-1,+a[2]):NaN}}};this.init(a,c,f)}b.prototype.init=function(a,c,f){var d=a.decimalPoint;c&&(this.chartOptions=c);f&&(this.chart=f);"."!==d&&","!==d&&(d=void 0);this.options=a;this.columns=a.columns||this.rowsToColumns(a.rows)||[];this.firstRowAsNames=K(a.firstRowAsNames,this.firstRowAsNames,!0);this.decimalRegex=d&&new RegExp("^(-?[0-9]+)"+d+"([0-9]+)$");this.rawColumns=[];if(this.columns.length){this.dataFound();var g=!0}this.hasURLOption(a)&&(clearTimeout(this.liveDataTimeout), +g=!1);g||(g=this.fetchLiveData());g||(g=!!this.parseCSV().length);g||(g=!!this.parseTable().length);g||(g=this.parseGoogleSpreadsheet());!g&&a.afterComplete&&a.afterComplete()};b.prototype.hasURLOption=function(a){return!(!a||!(a.rowsURL||a.csvURL||a.columnsURL))};b.prototype.getColumnDistribution=function(){var a=this.chartOptions,c=this.options,f=[],d=function(a){return(l.seriesTypes[a||"line"].prototype.pointArrayMap||[0]).length},g=a&&a.chart&&a.chart.type,e=[],b=[],h=0;c=c&&c.seriesMapping|| +a&&a.series&&a.series.map(function(){return{x:0}})||[];var k;(a&&a.series||[]).forEach(function(a){e.push(d(a.type||g))});c.forEach(function(a){f.push(a.x||0)});0===f.length&&f.push(0);c.forEach(function(c){var f=new G,u=e[h]||d(g),r=(a&&a.series||[])[h]||{},w=l.seriesTypes[r.type||g||"line"].prototype.pointArrayMap,z=w||["y"];(I(c.x)||r.isCartesian||!w)&&f.addColumnReader(c.x,"x");J(c,function(a,c){"x"!==c&&f.addColumnReader(a,c)});for(k=0;ky||y>l?(++y,q=""):(!isNaN(parseFloat(q))&&isFinite(q)?(q=parseFloat(q),b("number")):isNaN(Date.parse(q))?b("string"):(q=q.replace(/\//g,"-"),b("date")),w.lengthr[","]?";":",";e.decimalPoint|| +(e.decimalPoint=c>f?".":",",g.decimalRegex=new RegExp("^(-?[0-9]+)"+e.decimalPoint+"([0-9]+)$"));return d}function d(a,c){var d=[],f=0,b=!1,h=[],k=[],n;if(!c||c>a.length)c=a.length;for(;fm[n]?"YY":"YYYY":12=m[n]?(d[n]="dd",b=!0):d[n].length||(d[n]="mm")))}if(b){for(n=0;na)a=0;if(!h||h>=b.length)h=b.length-1;if(e.itemDelimiter)var z=e.itemDelimiter;else z=null,z=f(b);var y=0;for(m=a;m<=h;m++)"#"===b[m][0]?y++:c(b[m],m-a-y);e.columnTypes&&0!==e.columnTypes.length||!x.length||!x[0].length|| +"date"!==x[0][1]||e.dateFormat||(e.dateFormat=d(w[0]));this.dataFound()}return w};b.prototype.parseTable=function(){var a=this.options,c=a.table,f=this.columns||[],d=a.startRow||0,b=a.endRow||Number.MAX_VALUE,e=a.startColumn||0,u=a.endColumn||Number.MAX_VALUE;c&&("string"===typeof c&&(c=M.getElementById(c)),[].forEach.call(c.getElementsByTagName("tr"),function(a,c){c>=d&&c<=b&&[].forEach.call(a.children,function(a,b){var g=f[b-e],h=1;if(("TD"===a.tagName||"TH"===a.tagName)&&b>=e&&b<=u)for(f[b-e]|| +(f[b-e]=[]),f[b-e][c-d]=a.innerHTML;c-d>=h&&void 0===g[c-d-h];)g[c-d-h]=null,h++})}),this.dataFound());return f};b.prototype.fetchLiveData=function(){function a(g){function k(h,k,l){function m(){e&&f.liveDataURL===h&&(c.liveDataTimeout=setTimeout(a,u))}if(!h||0!==h.indexOf("http"))return h&&d.error&&d.error("Invalid URL"),!1;g&&(clearTimeout(c.liveDataTimeout),f.liveDataURL=h);F({url:h,dataType:l||"json",success:function(a){f&&f.series&&k(a);m()},error:function(a,c){3>++b&&m();return d.error&&d.error(c, +a)}});return!0}k(h.csvURL,function(a){f.update({data:{csv:a}})},"text")||k(h.rowsURL,function(a){f.update({data:{rows:a}})})||k(h.columnsURL,function(a){f.update({data:{columns:a}})})}var c=this,f=this.chart,d=this.options,b=0,e=d.enablePolling,u=1E3*(d.dataRefreshRate||2),h=A(d);if(!this.hasURLOption(d))return!1;1E3>u&&(u=1E3);delete d.csvURL;delete d.rowsURL;delete d.columnsURL;a(!0);return this.hasURLOption(d)};b.prototype.parseGoogleSpreadsheet=function(){function a(c){var b=["https://spreadsheets.google.com/feeds/cells", +d,e,"public/values?alt=json"].join("/");F({url:b,dataType:"json",success:function(d){c(d);f.enablePolling&&setTimeout(function(){a(c)},1E3*(f.dataRefreshRate||2))},error:function(a,c){return f.error&&f.error(c,a)}})}var c=this,f=this.options,d=f.googleSpreadsheetKey,b=this.chart,e=f.googleSpreadsheetWorksheet||1,u=f.startRow||0,h=f.endRow||Number.MAX_VALUE,k=f.startColumn||0,l=f.endColumn||Number.MAX_VALUE,m=1E3*(f.dataRefreshRate||2);4E3>m&&(m=4E3);d&&(delete f.googleSpreadsheetKey,a(function(a){var d= +[];a=a.feed.entry;var f=(a||[]).length,g=0,e;if(!a||0===a.length)return!1;for(e=0;e=k&&e<=l&&(d[e-k]=[]);for(e=0;e=k&&p<=l&&g>=u&&g<=h){var q=m.gs$cell||m.content;m=null;q.numericValue?m=0<=q.$t.indexOf("/")||0<=q.$t.indexOf("-")?q.$t:0a[b+1])): +(w&&w.length&&(h=this.parseDate(r)),l&&E(h)&&"float"!==t?(k[b]=r,a[b]=h,a.isDatetime=!0,"undefined"!==typeof a[b+1]&&(r=h>a[b+1],r!==m&&"undefined"!==typeof m&&(this.alternativeFormat?(this.dateFormat=this.alternativeFormat,b=a.length,this.alternativeFormat=this.dateFormats[this.dateFormat].alternative):a.unsorted=!0),m=r)):(a[b]=""===w?null:w,0!==b&&(a.isDatetime||a.isNumeric)&&(a.mixed=!0)))}l&&a.mixed&&(d[c]=f[c]);if(l&&m&&this.options.sort)for(c=0;c} + */ /** + * The data type expected. + * @name Highcharts.AjaxSettingsObject#dataType + * @type {"json"|"xml"|"text"|"octet"} + */ /** + * Function to call on error. + * @name Highcharts.AjaxSettingsObject#error + * @type {Function} + */ /** + * The headers; keyed on header name. + * @name Highcharts.AjaxSettingsObject#headers + * @type {Highcharts.Dictionary} + */ /** + * Function to call on success. + * @name Highcharts.AjaxSettingsObject#success + * @type {Function} + */ /** + * The HTTP method to use. For example GET or POST. + * @name Highcharts.AjaxSettingsObject#type + * @type {string} + */ /** + * The URL to call. + * @name Highcharts.AjaxSettingsObject#url + * @type {string} + */ + /** + * Perform an Ajax call. + * + * @function Highcharts.ajax + * + * @param {Partial} attr + * The Ajax settings to use. + * + * @return {false|undefined} + * Returns false, if error occured. + */ + H.ajax = function (attr) { + var options = merge(true, { + url: false, + type: 'get', + dataType: 'json', + success: false, + error: false, + data: false, + headers: {} + }, + attr), + headers = { + json: 'application/json', + xml: 'application/xml', + text: 'text/plain', + octet: 'application/octet-stream' + }, + r = new XMLHttpRequest(); + /** + * @private + * @param {XMLHttpRequest} xhr - Internal request object. + * @param {string|Error} err - Occured error. + * @return {void} + */ + function handleError(xhr, err) { + if (options.error) { + options.error(xhr, err); + } + else { + // @todo Maybe emit a highcharts error event here + } + } + if (!options.url) { + return false; + } + r.open(options.type.toUpperCase(), options.url, true); + if (!options.headers['Content-Type']) { + r.setRequestHeader('Content-Type', headers[options.dataType] || headers.text); + } + objectEach(options.headers, function (val, key) { + r.setRequestHeader(key, val); + }); + // @todo lacking timeout handling + r.onreadystatechange = function () { + var res; + if (r.readyState === 4) { + if (r.status === 200) { + res = r.responseText; + if (options.dataType === 'json') { + try { + res = JSON.parse(res); + } + catch (e) { + return handleError(r, e); + } + } + return options.success && options.success(res); + } + handleError(r, r.responseText); + } + }; + try { + options.data = JSON.stringify(options.data); + } + catch (e) { + // empty + } + r.send(options.data || true); + }; + /** + * Get a JSON resource over XHR, also supporting CORS without preflight. + * + * @function Highcharts.getJSON + * @param {string} url + * The URL to load. + * @param {Function} success + * The success callback. For error handling, use the `Highcharts.ajax` + * function instead. + * @return {void} + */ + H.getJSON = function (url, success) { + H.ajax({ + url: url, + success: success, + dataType: 'json', + headers: { + // Override the Content-Type to avoid preflight problems with CORS + // in the Highcharts demos + 'Content-Type': 'text/plain' + } + }); + }; + var exports = { + ajax: H.ajax, + getJSON: H.getJSON + }; + + return exports; + }); + _registerModule(_modules, 'Extensions/Data.js', [_modules['Core/Chart/Chart.js'], _modules['Core/Globals.js'], _modules['Core/Series/Point.js'], _modules['Core/Utilities.js'], _modules['Extensions/Ajax.js']], function (Chart, H, Point, U, Ajax) { + /* * + * + * Data module + * + * (c) 2012-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + defined = U.defined, + extend = U.extend, + fireEvent = U.fireEvent, + isNumber = U.isNumber, + merge = U.merge, + objectEach = U.objectEach, + pick = U.pick, + splat = U.splat; + /** + * Callback function to modify the CSV before parsing it by the data module. + * + * @callback Highcharts.DataBeforeParseCallbackFunction + * + * @param {string} csv + * The CSV to modify. + * + * @return {string} + * The CSV to parse. + */ + /** + * Callback function that gets called after parsing data. + * + * @callback Highcharts.DataCompleteCallbackFunction + * + * @param {Highcharts.Options} chartOptions + * The chart options that were used. + */ + /** + * Callback function that returns the correspondig Date object to a match. + * + * @callback Highcharts.DataDateFormatCallbackFunction + * + * @param {Array} match + * + * @return {number} + */ + /** + * Structure for alternative date formats to parse. + * + * @interface Highcharts.DataDateFormatObject + */ /** + * @name Highcharts.DataDateFormatObject#alternative + * @type {string|undefined} + */ /** + * @name Highcharts.DataDateFormatObject#parser + * @type {Highcharts.DataDateFormatCallbackFunction} + */ /** + * @name Highcharts.DataDateFormatObject#regex + * @type {global.RegExp} + */ + /** + * Possible types for a data item in a column or row. + * + * @typedef {number|string|null} Highcharts.DataValueType + */ + /** + * Callback function to parse string representations of dates into + * JavaScript timestamps (milliseconds since 1.1.1970). + * + * @callback Highcharts.DataParseDateCallbackFunction + * + * @param {string} dateValue + * + * @return {number} + * Timestamp (milliseconds since 1.1.1970) as integer for Date class. + */ + /** + * Callback function to access the parsed columns, the two-dimentional + * input data array directly, before they are interpreted into series + * data and categories. + * + * @callback Highcharts.DataParsedCallbackFunction + * + * @param {Array>} columns + * The parsed columns by the data module. + * + * @return {boolean|undefined} + * Return `false` to stop completion, or call `this.complete()` to + * continue async. + */ + var ajax = Ajax.ajax; + // Utilities + var win = H.win, + doc = win.document; + /** + * The Data module provides a simplified interface for adding data to + * a chart from sources like CVS, HTML tables or grid views. See also + * the [tutorial article on the Data module]( + * https://www.highcharts.com/docs/working-with-data/data-module). + * + * It requires the `modules/data.js` file to be loaded. + * + * Please note that the default way of adding data in Highcharts, without + * the need of a module, is through the [series._type_.data](#series.line.data) + * option. + * + * @sample {highcharts} highcharts/demo/column-parsed/ + * HTML table + * @sample {highcharts} highcharts/data/csv/ + * CSV + * + * @since 4.0 + * @requires modules/data + * @apioption data + */ + /** + * A callback function to modify the CSV before parsing it. Return the modified + * string. + * + * @sample {highcharts} highcharts/demo/line-ajax/ + * Modify CSV before parse + * + * @type {Highcharts.DataBeforeParseCallbackFunction} + * @since 6.1 + * @apioption data.beforeParse + */ + /** + * A two-dimensional array representing the input data on tabular form. + * This input can be used when the data is already parsed, for example + * from a grid view component. Each cell can be a string or number. + * If not switchRowsAndColumns is set, the columns are interpreted as + * series. + * + * @see [data.rows](#data.rows) + * + * @sample {highcharts} highcharts/data/columns/ + * Columns + * + * @type {Array>} + * @since 4.0 + * @apioption data.columns + */ + /** + * The callback that is evaluated when the data is finished loading, + * optionally from an external source, and parsed. The first argument + * passed is a finished chart options object, containing the series. + * These options can be extended with additional options and passed + * directly to the chart constructor. + * + * @see [data.parsed](#data.parsed) + * + * @sample {highcharts} highcharts/data/complete/ + * Modify data on complete + * + * @type {Highcharts.DataCompleteCallbackFunction} + * @since 4.0 + * @apioption data.complete + */ + /** + * A comma delimited string to be parsed. Related options are [startRow]( + * #data.startRow), [endRow](#data.endRow), [startColumn](#data.startColumn) + * and [endColumn](#data.endColumn) to delimit what part of the table + * is used. The [lineDelimiter](#data.lineDelimiter) and [itemDelimiter]( + * #data.itemDelimiter) options define the CSV delimiter formats. + * + * The built-in CSV parser doesn't support all flavours of CSV, so in + * some cases it may be necessary to use an external CSV parser. See + * [this example](https://jsfiddle.net/highcharts/u59176h4/) of parsing + * CSV through the MIT licensed [Papa Parse](http://papaparse.com/) + * library. + * + * @sample {highcharts} highcharts/data/csv/ + * Data from CSV + * + * @type {string} + * @since 4.0 + * @apioption data.csv + */ + /** + * Which of the predefined date formats in Date.prototype.dateFormats + * to use to parse date values. Defaults to a best guess based on what + * format gives valid and ordered dates. Valid options include: `YYYY/mm/dd`, + * `dd/mm/YYYY`, `mm/dd/YYYY`, `dd/mm/YY`, `mm/dd/YY`. + * + * @see [data.parseDate](#data.parseDate) + * + * @sample {highcharts} highcharts/data/dateformat-auto/ + * Best guess date format + * + * @type {string} + * @since 4.0 + * @validvalue ["YYYY/mm/dd", "dd/mm/YYYY", "mm/dd/YYYY", "dd/mm/YYYY", + * "dd/mm/YY", "mm/dd/YY"] + * @apioption data.dateFormat + */ + /** + * The decimal point used for parsing numbers in the CSV. + * + * If both this and data.delimiter is set to `undefined`, the parser will + * attempt to deduce the decimal point automatically. + * + * @sample {highcharts} highcharts/data/delimiters/ + * Comma as decimal point + * + * @type {string} + * @default . + * @since 4.1.0 + * @apioption data.decimalPoint + */ + /** + * In tabular input data, the last column (indexed by 0) to use. Defaults + * to the last column containing data. + * + * @sample {highcharts} highcharts/data/start-end/ + * Limited data + * + * @type {number} + * @since 4.0 + * @apioption data.endColumn + */ + /** + * In tabular input data, the last row (indexed by 0) to use. Defaults + * to the last row containing data. + * + * @sample {highcharts} highcharts/data/start-end/ + * Limited data + * + * @type {number} + * @since 4.0.4 + * @apioption data.endRow + */ + /** + * Whether to use the first row in the data set as series names. + * + * @sample {highcharts} highcharts/data/start-end/ + * Don't get series names from the CSV + * @sample {highstock} highcharts/data/start-end/ + * Don't get series names from the CSV + * + * @type {boolean} + * @default true + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption data.firstRowAsNames + */ + /** + * The key for a Google Spreadsheet to load. See [general information + * on GS](https://developers.google.com/gdata/samples/spreadsheet_sample). + * + * @sample {highcharts} highcharts/data/google-spreadsheet/ + * Load a Google Spreadsheet + * + * @type {string} + * @since 4.0 + * @apioption data.googleSpreadsheetKey + */ + /** + * The Google Spreadsheet worksheet to use in combination with + * [googleSpreadsheetKey](#data.googleSpreadsheetKey). The available id's from + * your sheet can be read from `https://spreadsheets.google.com/feeds/worksheets/{key}/public/basic`. + * + * @sample {highcharts} highcharts/data/google-spreadsheet/ + * Load a Google Spreadsheet + * + * @type {string} + * @since 4.0 + * @apioption data.googleSpreadsheetWorksheet + */ + /** + * Item or cell delimiter for parsing CSV. Defaults to the tab character + * `\t` if a tab character is found in the CSV string, if not it defaults + * to `,`. + * + * If this is set to false or undefined, the parser will attempt to deduce + * the delimiter automatically. + * + * @sample {highcharts} highcharts/data/delimiters/ + * Delimiters + * + * @type {string} + * @since 4.0 + * @apioption data.itemDelimiter + */ + /** + * Line delimiter for parsing CSV. + * + * @sample {highcharts} highcharts/data/delimiters/ + * Delimiters + * + * @type {string} + * @default \n + * @since 4.0 + * @apioption data.lineDelimiter + */ + /** + * A callback function to access the parsed columns, the two-dimentional + * input data array directly, before they are interpreted into series + * data and categories. Return `false` to stop completion, or call + * `this.complete()` to continue async. + * + * @see [data.complete](#data.complete) + * + * @sample {highcharts} highcharts/data/parsed/ + * Modify data after parse + * + * @type {Highcharts.DataParsedCallbackFunction} + * @since 4.0 + * @apioption data.parsed + */ + /** + * A callback function to parse string representations of dates into + * JavaScript timestamps. Should return an integer timestamp on success. + * + * @see [dateFormat](#data.dateFormat) + * + * @type {Highcharts.DataParseDateCallbackFunction} + * @since 4.0 + * @apioption data.parseDate + */ + /** + * The same as the columns input option, but defining rows intead of + * columns. + * + * @see [data.columns](#data.columns) + * + * @sample {highcharts} highcharts/data/rows/ + * Data in rows + * + * @type {Array>} + * @since 4.0 + * @apioption data.rows + */ + /** + * An array containing dictionaries for each series. A dictionary exists of + * Point property names as the key and the CSV column index as the value. + * + * @sample {highcharts} highcharts/data/seriesmapping-label/ + * Label from data set + * + * @type {Array>} + * @since 4.0.4 + * @apioption data.seriesMapping + */ + /** + * In tabular input data, the first column (indexed by 0) to use. + * + * @sample {highcharts} highcharts/data/start-end/ + * Limited data + * + * @type {number} + * @default 0 + * @since 4.0 + * @apioption data.startColumn + */ + /** + * In tabular input data, the first row (indexed by 0) to use. + * + * @sample {highcharts} highcharts/data/start-end/ + * Limited data + * + * @type {number} + * @default 0 + * @since 4.0 + * @apioption data.startRow + */ + /** + * Switch rows and columns of the input data, so that `this.columns` + * effectively becomes the rows of the data set, and the rows are interpreted + * as series. + * + * @sample {highcharts} highcharts/data/switchrowsandcolumns/ + * Switch rows and columns + * + * @type {boolean} + * @default false + * @since 4.0 + * @apioption data.switchRowsAndColumns + */ + /** + * An HTML table or the id of such to be parsed as input data. Related + * options are `startRow`, `endRow`, `startColumn` and `endColumn` to + * delimit what part of the table is used. + * + * @sample {highcharts} highcharts/demo/column-parsed/ + * Parsed table + * + * @type {string|global.HTMLElement} + * @since 4.0 + * @apioption data.table + */ + /** + * An URL to a remote CSV dataset. Will be fetched when the chart is created + * using Ajax. + * + * @sample highcharts/data/livedata-columns + * Categorized bar chart with CSV and live polling + * @sample highcharts/data/livedata-csv + * Time based line chart with CSV and live polling + * + * @type {string} + * @apioption data.csvURL + */ + /** + * A URL to a remote JSON dataset, structured as a row array. + * Will be fetched when the chart is created using Ajax. + * + * @sample highcharts/data/livedata-rows + * Rows with live polling + * + * @type {string} + * @apioption data.rowsURL + */ + /** + * A URL to a remote JSON dataset, structured as a column array. + * Will be fetched when the chart is created using Ajax. + * + * @sample highcharts/data/livedata-columns + * Columns with live polling + * + * @type {string} + * @apioption data.columnsURL + */ + /** + * Sets the refresh rate for data polling when importing remote dataset by + * setting [data.csvURL](data.csvURL), [data.rowsURL](data.rowsURL), + * [data.columnsURL](data.columnsURL), or + * [data.googleSpreadsheetKey](data.googleSpreadsheetKey). + * + * Note that polling must be enabled by setting + * [data.enablePolling](data.enablePolling) to true. + * + * The value is the number of seconds between pollings. + * It cannot be set to less than 1 second. + * + * @sample highcharts/demo/live-data + * Live data with user set refresh rate + * + * @default 1 + * @type {number} + * @apioption data.dataRefreshRate + */ + /** + * Enables automatic refetching of remote datasets every _n_ seconds (defined by + * setting [data.dataRefreshRate](data.dataRefreshRate)). + * + * Only works when either [data.csvURL](data.csvURL), + * [data.rowsURL](data.rowsURL), [data.columnsURL](data.columnsURL), or + * [data.googleSpreadsheetKey](data.googleSpreadsheetKey). + * + * @sample highcharts/demo/live-data + * Live data + * @sample highcharts/data/livedata-columns + * Categorized bar chart with CSV and live polling + * + * @type {boolean} + * @default false + * @apioption data.enablePolling + */ + /* eslint-disable valid-jsdoc */ + /** + * The Data class + * + * @requires module:modules/data + * + * @class + * @name Highcharts.Data + * + * @param {Highcharts.DataOptions} dataOptions + * + * @param {Highcharts.Options} [chartOptions] + * + * @param {Highcharts.Chart} [chart] + */ + var Data = /** @class */ (function () { + function Data(dataOptions, chartOptions, chart) { + this.chart = void 0; + this.chartOptions = void 0; + this.firstRowAsNames = void 0; + this.rawColumns = void 0; + this.options = void 0; + /** + * A collection of available date formats, extendable from the outside to + * support custom date formats. + * + * @name Highcharts.Data#dateFormats + * @type {Highcharts.Dictionary} + */ + this.dateFormats = { + 'YYYY/mm/dd': { + regex: /^([0-9]{4})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{1,2})$/, + parser: function (match) { + return (match ? + Date.UTC(+match[1], match[2] - 1, +match[3]) : + NaN); + } + }, + 'dd/mm/YYYY': { + regex: /^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{4})$/, + parser: function (match) { + return (match ? + Date.UTC(+match[3], match[2] - 1, +match[1]) : + NaN); + }, + alternative: 'mm/dd/YYYY' // different format with the same regex + }, + 'mm/dd/YYYY': { + regex: /^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{4})$/, + parser: function (match) { + return (match ? + Date.UTC(+match[3], match[1] - 1, +match[2]) : + NaN); + } + }, + 'dd/mm/YY': { + regex: /^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{2})$/, + parser: function (match) { + if (!match) { + return NaN; + } + var year = +match[3], + d = new Date(); + if (year > (d.getFullYear() - 2000)) { + year += 1900; + } + else { + year += 2000; + } + return Date.UTC(year, match[2] - 1, +match[1]); + }, + alternative: 'mm/dd/YY' // different format with the same regex + }, + 'mm/dd/YY': { + regex: /^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{2})$/, + parser: function (match) { + return (match ? + Date.UTC(+match[3] + 2000, match[1] - 1, +match[2]) : + NaN); + } + } + }; + this.init(dataOptions, chartOptions, chart); + } + /** + * Initialize the Data object with the given options + * + * @private + * @function Highcharts.Data#init + * @param {Highcharts.DataOptions} options + * @param {Highcharts.Options} [chartOptions] + * @param {Highcharts.Chart} [chart] + */ + Data.prototype.init = function (options, chartOptions, chart) { + var decimalPoint = options.decimalPoint, + hasData; + if (chartOptions) { + this.chartOptions = chartOptions; + } + if (chart) { + this.chart = chart; + } + if (decimalPoint !== '.' && decimalPoint !== ',') { + decimalPoint = void 0; + } + this.options = options; + this.columns = (options.columns || + this.rowsToColumns(options.rows) || + []); + this.firstRowAsNames = pick(options.firstRowAsNames, this.firstRowAsNames, true); + this.decimalRegex = (decimalPoint && + new RegExp('^(-?[0-9]+)' + decimalPoint + '([0-9]+)$')); + // This is a two-dimensional array holding the raw, trimmed string + // values with the same organisation as the columns array. It makes it + // possible for example to revert from interpreted timestamps to + // string-based categories. + this.rawColumns = []; + // No need to parse or interpret anything + if (this.columns.length) { + this.dataFound(); + hasData = true; + } + if (this.hasURLOption(options)) { + clearTimeout(this.liveDataTimeout); + hasData = false; + } + if (!hasData) { + // Fetch live data + hasData = this.fetchLiveData(); + } + if (!hasData) { + // Parse a CSV string if options.csv is given. The parseCSV function + // returns a columns array, if it has no length, we have no data + hasData = Boolean(this.parseCSV().length); + } + if (!hasData) { + // Parse a HTML table if options.table is given + hasData = Boolean(this.parseTable().length); + } + if (!hasData) { + // Parse a Google Spreadsheet + hasData = this.parseGoogleSpreadsheet(); + } + if (!hasData && options.afterComplete) { + options.afterComplete(); + } + }; + Data.prototype.hasURLOption = function (options) { + return Boolean(options && + (options.rowsURL || options.csvURL || options.columnsURL)); + }; + /** + * Get the column distribution. For example, a line series takes a single + * column for Y values. A range series takes two columns for low and high + * values respectively, and an OHLC series takes four columns. + * + * @function Highcharts.Data#getColumnDistribution + */ + Data.prototype.getColumnDistribution = function () { + var chartOptions = this.chartOptions, + options = this.options, + xColumns = [], + getValueCount = function (type) { + return (H.seriesTypes[type || 'line'].prototype + .pointArrayMap || + [0]).length; + }, getPointArrayMap = function (type) { + return H.seriesTypes[type || 'line'] + .prototype.pointArrayMap; + }, globalType = (chartOptions && + chartOptions.chart && + chartOptions.chart.type), individualCounts = [], seriesBuilders = [], seriesIndex = 0, + // If no series mapping is defined, check if the series array is + // defined with types. + seriesMapping = ((options && options.seriesMapping) || + (chartOptions && + chartOptions.series && + chartOptions.series.map(function () { + return { x: 0 }; + })) || + []), i; + ((chartOptions && chartOptions.series) || []).forEach(function (series) { + individualCounts.push(getValueCount(series.type || globalType)); + }); + // Collect the x-column indexes from seriesMapping + seriesMapping.forEach(function (mapping) { + xColumns.push(mapping.x || 0); + }); + // If there are no defined series with x-columns, use the first column + // as x column + if (xColumns.length === 0) { + xColumns.push(0); + } + // Loop all seriesMappings and constructs SeriesBuilders from + // the mapping options. + seriesMapping.forEach(function (mapping) { + var builder = new SeriesBuilder(), + numberOfValueColumnsNeeded = individualCounts[seriesIndex] || + getValueCount(globalType), + seriesArr = (chartOptions && chartOptions.series) || [], + series = seriesArr[seriesIndex] || {}, + defaultPointArrayMap = getPointArrayMap(series.type || globalType), + pointArrayMap = defaultPointArrayMap || ['y']; + if ( + // User-defined x.mapping + defined(mapping.x) || + // All non cartesian don't need 'x' + series.isCartesian || + // Except pie series: + !defaultPointArrayMap) { + // Add an x reader from the x property or from an undefined + // column if the property is not set. It will then be auto + // populated later. + builder.addColumnReader(mapping.x, 'x'); + } + // Add all column mappings + objectEach(mapping, function (val, name) { + if (name !== 'x') { + builder.addColumnReader(val, name); + } + }); + // Add missing columns + for (i = 0; i < numberOfValueColumnsNeeded; i++) { + if (!builder.hasReader(pointArrayMap[i])) { + // Create and add a column reader for the next free column + // index + builder.addColumnReader(void 0, pointArrayMap[i]); + } + } + seriesBuilders.push(builder); + seriesIndex++; + }); + var globalPointArrayMap = getPointArrayMap(globalType); + if (typeof globalPointArrayMap === 'undefined') { + globalPointArrayMap = ['y']; + } + this.valueCount = { + global: getValueCount(globalType), + xColumns: xColumns, + individual: individualCounts, + seriesBuilders: seriesBuilders, + globalPointArrayMap: globalPointArrayMap + }; + }; + /** + * When the data is parsed into columns, either by CSV, table, GS or direct + * input, continue with other operations. + * + * @private + * @function Highcharts.Data#dataFound + */ + Data.prototype.dataFound = function () { + if (this.options.switchRowsAndColumns) { + this.columns = this.rowsToColumns(this.columns); + } + // Interpret the info about series and columns + this.getColumnDistribution(); + // Interpret the values into right types + this.parseTypes(); + // Handle columns if a handleColumns callback is given + if (this.parsed() !== false) { + // Complete if a complete callback is given + this.complete(); + } + }; + /** + * Parse a CSV input string + * + * @function Highcharts.Data#parseCSV + * + * @param {Highcharts.DataOptions} [inOptions] + * + * @return {Array>} + */ + Data.prototype.parseCSV = function (inOptions) { + var self = this, options = inOptions || this.options, csv = options.csv, columns, startRow = (typeof options.startRow !== 'undefined' && options.startRow ? + options.startRow : + 0), endRow = options.endRow || Number.MAX_VALUE, startColumn = (typeof options.startColumn !== 'undefined' && + options.startColumn) ? options.startColumn : 0, endColumn = options.endColumn || Number.MAX_VALUE, itemDelimiter, lines, rowIt = 0, + // activeRowNo = 0, + dataTypes = [], + // We count potential delimiters in the prepass, and use the + // result as the basis of half-intelligent guesses. + potDelimiters = { + ',': 0, + ';': 0, + '\t': 0 + }; + columns = this.columns = []; + /* + This implementation is quite verbose. It will be shortened once + it's stable and passes all the test. + + It's also not written with speed in mind, instead everything is + very seggregated, and there a several redundant loops. + This is to make it easier to stabilize the code initially. + + We do a pre-pass on the first 4 rows to make some intelligent + guesses on the set. Guessed delimiters are in this pass counted. + + Auto detecting delimiters + - If we meet a quoted string, the next symbol afterwards + (that's not \s, \t) is the delimiter + - If we meet a date, the next symbol afterwards is the delimiter + + Date formats + - If we meet a column with date formats, check all of them to + see if one of the potential months crossing 12. If it does, + we now know the format + + It would make things easier to guess the delimiter before + doing the actual parsing. + + General rules: + - Quoting is allowed, e.g: "Col 1",123,321 + - Quoting is optional, e.g.: Col1,123,321 + - Doubble quoting is escaping, e.g. "Col ""Hello world""",123 + - Spaces are considered part of the data: Col1 ,123 + - New line is always the row delimiter + - Potential column delimiters are , ; \t + - First row may optionally contain headers + - The last row may or may not have a row delimiter + - Comments are optionally supported, in which case the comment + must start at the first column, and the rest of the line will + be ignored + */ + /** + * Parse a single row. + * @private + */ + function parseRow(columnStr, rowNumber, noAdd, callbacks) { + var i = 0, c = '', cl = '', cn = '', token = '', actualColumn = 0, column = 0; + /** + * @private + */ + function read(j) { + c = columnStr[j]; + cl = columnStr[j - 1]; + cn = columnStr[j + 1]; + } + /** + * @private + */ + function pushType(type) { + if (dataTypes.length < column + 1) { + dataTypes.push([type]); + } + if (dataTypes[column][dataTypes[column].length - 1] !== type) { + dataTypes[column].push(type); + } + } + /** + * @private + */ + function push() { + if (startColumn > actualColumn || actualColumn > endColumn) { + // Skip this column, but increment the column count (#7272) + ++actualColumn; + token = ''; + return; + } + if (!isNaN(parseFloat(token)) && isFinite(token)) { + token = parseFloat(token); + pushType('number'); + } + else if (!isNaN(Date.parse(token))) { + token = token.replace(/\//g, '-'); + pushType('date'); + } + else { + pushType('string'); + } + if (columns.length < column + 1) { + columns.push([]); + } + if (!noAdd) { + // Don't push - if there's a varrying amount of columns + // for each row, pushing will skew everything down n slots + columns[column][rowNumber] = token; + } + token = ''; + ++column; + ++actualColumn; + } + if (!columnStr.trim().length) { + return; + } + if (columnStr.trim()[0] === '#') { + return; + } + for (; i < columnStr.length; i++) { + read(i); + // Quoted string + if (c === '#') { + // The rest of the row is a comment + push(); + return; + } + if (c === '"') { + read(++i); + while (i < columnStr.length) { + if (c === '"' && cl !== '"' && cn !== '"') { + break; + } + if (c !== '"' || (c === '"' && cl !== '"')) { + token += c; + } + read(++i); + } + // Perform "plugin" handling + } + else if (callbacks && callbacks[c]) { + if (callbacks[c](c, token)) { + push(); + } + // Delimiter - push current token + } + else if (c === itemDelimiter) { + push(); + // Actual column data + } + else { + token += c; + } + } + push(); + } + /** + * Attempt to guess the delimiter. We do a separate parse pass here + * because we need to count potential delimiters softly without making + * any assumptions. + * @private + */ + function guessDelimiter(lines) { + var points = 0, + commas = 0, + guessed = false; + lines.some(function (columnStr, i) { + var inStr = false, + c, + cn, + cl, + token = ''; + // We should be able to detect dateformats within 13 rows + if (i > 13) { + return true; + } + for (var j = 0; j < columnStr.length; j++) { + c = columnStr[j]; + cn = columnStr[j + 1]; + cl = columnStr[j - 1]; + if (c === '#') { + // Skip the rest of the line - it's a comment + return; + } + if (c === '"') { + if (inStr) { + if (cl !== '"' && cn !== '"') { + while (cn === ' ' && j < columnStr.length) { + cn = columnStr[++j]; + } + // After parsing a string, the next non-blank + // should be a delimiter if the CSV is properly + // formed. + if (typeof potDelimiters[cn] !== 'undefined') { + potDelimiters[cn]++; + } + inStr = false; + } + } + else { + inStr = true; + } + } + else if (typeof potDelimiters[c] !== 'undefined') { + token = token.trim(); + if (!isNaN(Date.parse(token))) { + potDelimiters[c]++; + } + else if (isNaN(token) || + !isFinite(token)) { + potDelimiters[c]++; + } + token = ''; + } + else { + token += c; + } + if (c === ',') { + commas++; + } + if (c === '.') { + points++; + } + } + }); + // Count the potential delimiters. + // This could be improved by checking if the number of delimiters + // equals the number of columns - 1 + if (potDelimiters[';'] > potDelimiters[',']) { + guessed = ';'; + } + else if (potDelimiters[','] > potDelimiters[';']) { + guessed = ','; + } + else { + // No good guess could be made.. + guessed = ','; + } + // Try to deduce the decimal point if it's not explicitly set. + // If both commas or points is > 0 there is likely an issue + if (!options.decimalPoint) { + if (points > commas) { + options.decimalPoint = '.'; + } + else { + options.decimalPoint = ','; + } + // Apply a new decimal regex based on the presumed decimal sep. + self.decimalRegex = new RegExp('^(-?[0-9]+)' + + options.decimalPoint + + '([0-9]+)$'); + } + return guessed; + } + /** + * Tries to guess the date format + * - Check if either month candidate exceeds 12 + * - Check if year is missing (use current year) + * - Check if a shortened year format is used (e.g. 1/1/99) + * - If no guess can be made, the user must be prompted + * data is the data to deduce a format based on + * @private + */ + function deduceDateFormat(data, limit) { + var format = 'YYYY/mm/dd', + thing, + guessedFormat = [], + calculatedFormat, + i = 0, + madeDeduction = false, + // candidates = {}, + stable = [], + max = [], + j; + if (!limit || limit > data.length) { + limit = data.length; + } + for (; i < limit; i++) { + if (typeof data[i] !== 'undefined' && + data[i] && data[i].length) { + thing = data[i] + .trim() + .replace(/\//g, ' ') + .replace(/\-/g, ' ') + .replace(/\./g, ' ') + .split(' '); + guessedFormat = [ + '', + '', + '' + ]; + for (j = 0; j < thing.length; j++) { + if (j < guessedFormat.length) { + thing[j] = parseInt(thing[j], 10); + if (thing[j]) { + max[j] = (!max[j] || max[j] < thing[j]) ? + thing[j] : + max[j]; + if (typeof stable[j] !== 'undefined') { + if (stable[j] !== thing[j]) { + stable[j] = false; + } + } + else { + stable[j] = thing[j]; + } + if (thing[j] > 31) { + if (thing[j] < 100) { + guessedFormat[j] = 'YY'; + } + else { + guessedFormat[j] = 'YYYY'; + } + // madeDeduction = true; + } + else if (thing[j] > 12 && + thing[j] <= 31) { + guessedFormat[j] = 'dd'; + madeDeduction = true; + } + else if (!guessedFormat[j].length) { + guessedFormat[j] = 'mm'; + } + } + } + } + } + } + if (madeDeduction) { + // This handles a few edge cases with hard to guess dates + for (j = 0; j < stable.length; j++) { + if (stable[j] !== false) { + if (max[j] > 12 && + guessedFormat[j] !== 'YY' && + guessedFormat[j] !== 'YYYY') { + guessedFormat[j] = 'YY'; + } + } + else if (max[j] > 12 && guessedFormat[j] === 'mm') { + guessedFormat[j] = 'dd'; + } + } + // If the middle one is dd, and the last one is dd, + // the last should likely be year. + if (guessedFormat.length === 3 && + guessedFormat[1] === 'dd' && + guessedFormat[2] === 'dd') { + guessedFormat[2] = 'YY'; + } + calculatedFormat = guessedFormat.join('/'); + // If the caculated format is not valid, we need to present an + // error. + if (!(options.dateFormats || self.dateFormats)[calculatedFormat]) { + // This should emit an event instead + fireEvent('deduceDateFailed'); + return format; + } + return calculatedFormat; + } + return format; + } + /** + * @todo + * Figure out the best axis types for the data + * - If the first column is a number, we're good + * - If the first column is a date, set to date/time + * - If the first column is a string, set to categories + * @private + */ + function deduceAxisTypes() { + } + if (csv && options.beforeParse) { + csv = options.beforeParse.call(this, csv); + } + if (csv) { + lines = csv + .replace(/\r\n/g, '\n') // Unix + .replace(/\r/g, '\n') // Mac + .split(options.lineDelimiter || '\n'); + if (!startRow || startRow < 0) { + startRow = 0; + } + if (!endRow || endRow >= lines.length) { + endRow = lines.length - 1; + } + if (options.itemDelimiter) { + itemDelimiter = options.itemDelimiter; + } + else { + itemDelimiter = null; + itemDelimiter = guessDelimiter(lines); + } + var offset = 0; + for (rowIt = startRow; rowIt <= endRow; rowIt++) { + if (lines[rowIt][0] === '#') { + offset++; + } + else { + parseRow(lines[rowIt], rowIt - startRow - offset); + } + } + // //Make sure that there's header columns for everything + // columns.forEach(function (col) { + // }); + deduceAxisTypes(); + if ((!options.columnTypes || options.columnTypes.length === 0) && + dataTypes.length && + dataTypes[0].length && + dataTypes[0][1] === 'date' && + !options.dateFormat) { + options.dateFormat = deduceDateFormat(columns[0]); + } + // lines.forEach(function (line, rowNo) { + // var trimmed = self.trim(line), + // isComment = trimmed.indexOf('#') === 0, + // isBlank = trimmed === '', + // items; + // if ( + // rowNo >= startRow && + // rowNo <= endRow && + // !isComment && !isBlank + // ) { + // items = line.split(itemDelimiter); + // items.forEach(function (item, colNo) { + // if (colNo >= startColumn && colNo <= endColumn) { + // if (!columns[colNo - startColumn]) { + // columns[colNo - startColumn] = []; + // } + // columns[colNo - startColumn][activeRowNo] = item; + // } + // }); + // activeRowNo += 1; + // } + // }); + // + this.dataFound(); + } + return columns; + }; + /** + * Parse a HTML table + * + * @function Highcharts.Data#parseTable + * + * @return {Array>} + */ + Data.prototype.parseTable = function () { + var options = this.options, + table = options.table, + columns = this.columns || [], + startRow = options.startRow || 0, + endRow = options.endRow || Number.MAX_VALUE, + startColumn = options.startColumn || 0, + endColumn = options.endColumn || Number.MAX_VALUE; + if (table) { + if (typeof table === 'string') { + table = doc.getElementById(table); + } + [].forEach.call(table.getElementsByTagName('tr'), function (tr, rowNo) { + if (rowNo >= startRow && rowNo <= endRow) { + [].forEach.call(tr.children, function (item, colNo) { + var row = columns[colNo - startColumn]; + var i = 1; + if ((item.tagName === 'TD' || + item.tagName === 'TH') && + colNo >= startColumn && + colNo <= endColumn) { + if (!columns[colNo - startColumn]) { + columns[colNo - startColumn] = []; + } + columns[colNo - startColumn][rowNo - startRow] = item.innerHTML; + // Loop over all previous indices and make sure + // they are nulls, not undefined. + while (rowNo - startRow >= i && + row[rowNo - startRow - i] === void 0) { + row[rowNo - startRow - i] = null; + i++; + } + } + }); + } + }); + this.dataFound(); // continue + } + return columns; + }; + /** + * Fetch or refetch live data + * + * @function Highcharts.Data#fetchLiveData + * + * @return {boolean} + * The URLs that were tried can be found in the options + */ + Data.prototype.fetchLiveData = function () { + var data = this, + chart = this.chart, + options = this.options, + maxRetries = 3, + currentRetries = 0, + pollingEnabled = options.enablePolling, + updateIntervalMs = (options.dataRefreshRate || 2) * 1000, + originalOptions = merge(options); + if (!this.hasURLOption(options)) { + return false; + } + // Do not allow polling more than once a second + if (updateIntervalMs < 1000) { + updateIntervalMs = 1000; + } + delete options.csvURL; + delete options.rowsURL; + delete options.columnsURL; + /** + * @private + */ + function performFetch(initialFetch) { + /** + * Helper function for doing the data fetch + polling. + * @private + */ + function request(url, done, tp) { + if (!url || url.indexOf('http') !== 0) { + if (url && options.error) { + options.error('Invalid URL'); + } + return false; + } + if (initialFetch) { + clearTimeout(data.liveDataTimeout); + chart.liveDataURL = url; + } + /** + * @private + */ + function poll() { + // Poll + if (pollingEnabled && chart.liveDataURL === url) { + // We need to stop doing this if the URL has changed + data.liveDataTimeout = + setTimeout(performFetch, updateIntervalMs); + } + } + ajax({ + url: url, + dataType: tp || 'json', + success: function (res) { + if (chart && chart.series) { + done(res); + } + poll(); + }, + error: function (xhr, text) { + if (++currentRetries < maxRetries) { + poll(); + } + return options.error && options.error(text, xhr); + } + }); + return true; + } + if (!request(originalOptions.csvURL, function (res) { + chart.update({ + data: { + csv: res + } + }); + }, 'text')) { + if (!request(originalOptions.rowsURL, function (res) { + chart.update({ + data: { + rows: res + } + }); + })) { + request(originalOptions.columnsURL, function (res) { + chart.update({ + data: { + columns: res + } + }); + }); + } + } + } + performFetch(true); + return this.hasURLOption(options); + }; + /** + * Parse a Google spreadsheet. + * + * @function Highcharts.Data#parseGoogleSpreadsheet + * + * @return {boolean} + * Always returns false, because it is an intermediate fetch. + */ + Data.prototype.parseGoogleSpreadsheet = function () { + var data = this, + options = this.options, + googleSpreadsheetKey = options.googleSpreadsheetKey, + chart = this.chart, + // use sheet 1 as the default rather than od6 + // as the latter sometimes cause issues (it looks like it can + // be renamed in some cases, ref. a fogbugz case). + worksheet = options.googleSpreadsheetWorksheet || 1, + startRow = options.startRow || 0, + endRow = options.endRow || Number.MAX_VALUE, + startColumn = options.startColumn || 0, + endColumn = options.endColumn || Number.MAX_VALUE, + refreshRate = (options.dataRefreshRate || 2) * 1000; + if (refreshRate < 4000) { + refreshRate = 4000; + } + /** + * Fetch the actual spreadsheet using XMLHttpRequest. + * @private + */ + function fetchSheet(fn) { + var url = [ + 'https://spreadsheets.google.com/feeds/cells', + googleSpreadsheetKey, + worksheet, + 'public/values?alt=json' + ].join('/'); + ajax({ + url: url, + dataType: 'json', + success: function (json) { + fn(json); + if (options.enablePolling) { + setTimeout(function () { + fetchSheet(fn); + }, (options.dataRefreshRate || 2) * 1000); + } + }, + error: function (xhr, text) { + return options.error && options.error(text, xhr); + } + }); + } + if (googleSpreadsheetKey) { + delete options.googleSpreadsheetKey; + fetchSheet(function (json) { + // Prepare the data from the spreadsheat + var columns = [], + cells = json.feed.entry, + cell, + cellCount = (cells || []).length, + colCount = 0, + rowCount = 0, + val, + gr, + gc, + cellInner, + i; + if (!cells || cells.length === 0) { + return false; + } + // First, find the total number of columns and rows that + // are actually filled with data + for (i = 0; i < cellCount; i++) { + cell = cells[i]; + colCount = Math.max(colCount, cell.gs$cell.col); + rowCount = Math.max(rowCount, cell.gs$cell.row); + } + // Set up arrays containing the column data + for (i = 0; i < colCount; i++) { + if (i >= startColumn && i <= endColumn) { + // Create new columns with the length of either + // end-start or rowCount + columns[i - startColumn] = []; + } + } + // Loop over the cells and assign the value to the right + // place in the column arrays + for (i = 0; i < cellCount; i++) { + cell = cells[i]; + gr = cell.gs$cell.row - 1; // rows start at 1 + gc = cell.gs$cell.col - 1; // columns start at 1 + // If both row and col falls inside start and end set the + // transposed cell value in the newly created columns + if (gc >= startColumn && gc <= endColumn && + gr >= startRow && gr <= endRow) { + cellInner = cell.gs$cell || cell.content; + val = null; + if (cellInner.numericValue) { + if (cellInner.$t.indexOf('/') >= 0 || + cellInner.$t.indexOf('-') >= 0) { + // This is a date - for future reference. + val = cellInner.$t; + } + else if (cellInner.$t.indexOf('%') > 0) { + // Percentage + val = parseFloat(cellInner.numericValue) * 100; + } + else { + val = parseFloat(cellInner.numericValue); + } + } + else if (cellInner.$t && cellInner.$t.length) { + val = cellInner.$t; + } + columns[gc - startColumn][gr - startRow] = val; + } + } + // Insert null for empty spreadsheet cells (#5298) + columns.forEach(function (column) { + for (i = 0; i < column.length; i++) { + if (typeof column[i] === 'undefined') { + column[i] = null; + } + } + }); + if (chart && chart.series) { + chart.update({ + data: { + columns: columns + } + }); + } + else { // #8245 + data.columns = columns; + data.dataFound(); + } + }); + } + // This is an intermediate fetch, so always return false. + return false; + }; + /** + * Trim a string from whitespaces. + * + * @function Highcharts.Data#trim + * + * @param {string} str + * String to trim + * + * @param {boolean} [inside=false] + * Remove all spaces between numbers. + * + * @return {string} + * Trimed string + */ + Data.prototype.trim = function (str, inside) { + if (typeof str === 'string') { + str = str.replace(/^\s+|\s+$/g, ''); + // Clear white space insdie the string, like thousands separators + if (inside && /^[0-9\s]+$/.test(str)) { + str = str.replace(/\s/g, ''); + } + if (this.decimalRegex) { + str = str.replace(this.decimalRegex, '$1.$2'); + } + } + return str; + }; + /** + * Parse numeric cells in to number types and date types in to true dates. + * + * @function Highcharts.Data#parseTypes + */ + Data.prototype.parseTypes = function () { + var columns = this.columns, + col = columns.length; + while (col--) { + this.parseColumn(columns[col], col); + } + }; + /** + * Parse a single column. Set properties like .isDatetime and .isNumeric. + * + * @function Highcharts.Data#parseColumn + * + * @param {Array} column + * Column to parse + * + * @param {number} col + * Column index + */ + Data.prototype.parseColumn = function (column, col) { + var rawColumns = this.rawColumns, + columns = this.columns, + row = column.length, + val, + floatVal, + trimVal, + trimInsideVal, + firstRowAsNames = this.firstRowAsNames, + isXColumn = this.valueCount.xColumns.indexOf(col) !== -1, + dateVal, + backup = [], + diff, + chartOptions = this.chartOptions, + descending, + columnTypes = this.options.columnTypes || [], + columnType = columnTypes[col], + forceCategory = isXColumn && ((chartOptions && + chartOptions.xAxis && + splat(chartOptions.xAxis)[0].type === 'category') || columnType === 'string'); + if (!rawColumns[col]) { + rawColumns[col] = []; + } + while (row--) { + val = backup[row] || column[row]; + trimVal = this.trim(val); + trimInsideVal = this.trim(val, true); + floatVal = parseFloat(trimInsideVal); + // Set it the first time + if (typeof rawColumns[col][row] === 'undefined') { + rawColumns[col][row] = trimVal; + } + // Disable number or date parsing by setting the X axis type to + // category + if (forceCategory || (row === 0 && firstRowAsNames)) { + column[row] = '' + trimVal; + } + else if (+trimInsideVal === floatVal) { // is numeric + column[row] = floatVal; + // If the number is greater than milliseconds in a year, assume + // datetime + if (floatVal > 365 * 24 * 3600 * 1000 && + columnType !== 'float') { + column.isDatetime = true; + } + else { + column.isNumeric = true; + } + if (typeof column[row + 1] !== 'undefined') { + descending = floatVal > column[row + 1]; + } + // String, continue to determine if it is a date string or really a + // string + } + else { + if (trimVal && trimVal.length) { + dateVal = this.parseDate(val); + } + // Only allow parsing of dates if this column is an x-column + if (isXColumn && isNumber(dateVal) && columnType !== 'float') { + backup[row] = val; + column[row] = dateVal; + column.isDatetime = true; + // Check if the dates are uniformly descending or ascending. + // If they are not, chances are that they are a different + // time format, so check for alternative. + if (typeof column[row + 1] !== 'undefined') { + diff = dateVal > column[row + 1]; + if (diff !== descending && + typeof descending !== 'undefined') { + if (this.alternativeFormat) { + this.dateFormat = this.alternativeFormat; + row = column.length; + this.alternativeFormat = + this.dateFormats[this.dateFormat] + .alternative; + } + else { + column.unsorted = true; + } + } + descending = diff; + } + } + else { // string + column[row] = trimVal === '' ? null : trimVal; + if (row !== 0 && + (column.isDatetime || + column.isNumeric)) { + column.mixed = true; + } + } + } + } + // If strings are intermixed with numbers or dates in a parsed column, + // it is an indication that parsing went wrong or the data was not + // intended to display as numbers or dates and parsing is too + // aggressive. Fall back to categories. Demonstrated in the + // highcharts/demo/column-drilldown sample. + if (isXColumn && column.mixed) { + columns[col] = rawColumns[col]; + } + // If the 0 column is date or number and descending, reverse all + // columns. + if (isXColumn && descending && this.options.sort) { + for (col = 0; col < columns.length; col++) { + columns[col].reverse(); + if (firstRowAsNames) { + columns[col].unshift(columns[col].pop()); + } + } + } + }; + /** + * Parse a date and return it as a number. Overridable through + * `options.parseDate`. + * + * @function Highcharts.Data#parseDate + * + * @param {string} val + * + * @return {number} + */ + Data.prototype.parseDate = function (val) { + var parseDate = this.options.parseDate, + ret, + key, + format, + dateFormat = this.options.dateFormat || this.dateFormat, + match; + if (parseDate) { + ret = parseDate(val); + } + else if (typeof val === 'string') { + // Auto-detect the date format the first time + if (!dateFormat) { + for (key in this.dateFormats) { // eslint-disable-line guard-for-in + format = this.dateFormats[key]; + match = val.match(format.regex); + if (match) { + this.dateFormat = dateFormat = key; + this.alternativeFormat = format.alternative; + ret = format.parser(match); + break; + } + } + // Next time, use the one previously found + } + else { + format = this.dateFormats[dateFormat]; + if (!format) { + // The selected format is invalid + format = this.dateFormats['YYYY/mm/dd']; + } + match = val.match(format.regex); + if (match) { + ret = format.parser(match); + } + } + // Fall back to Date.parse + if (!match) { + match = Date.parse(val); + // External tools like Date.js and MooTools extend Date object + // and returns a date. + if (typeof match === 'object' && + match !== null && + match.getTime) { + ret = (match.getTime() - + match.getTimezoneOffset() * + 60000); + // Timestamp + } + else if (isNumber(match)) { + ret = match - (new Date(match)).getTimezoneOffset() * 60000; + } + } + } + return ret; + }; + /** + * Reorganize rows into columns. + * + * @function Highcharts.Data#rowsToColumns + * + * @param {Array>} rows + * + * @return {Array>|undefined} + */ + Data.prototype.rowsToColumns = function (rows) { + var row, + rowsLength, + col, + colsLength, + columns; + if (rows) { + columns = []; + rowsLength = rows.length; + for (row = 0; row < rowsLength; row++) { + colsLength = rows[row].length; + for (col = 0; col < colsLength; col++) { + if (!columns[col]) { + columns[col] = []; + } + columns[col][row] = rows[row][col]; + } + } + } + return columns; + }; + /** + * Get the parsed data in a form that we can apply directly to the + * `series.data` config. Array positions can be mapped using the + * `series.keys` option. + * + * @example + * const data = Highcharts.data({ + * csv: document.getElementById('data').innerHTML + * }).getData(); + * + * @function Highcharts.Data#getData + * + * @return {Array>|undefined} Data rows + */ + Data.prototype.getData = function () { + if (this.columns) { + return this.rowsToColumns(this.columns).slice(1); + } + }; + /** + * A hook for working directly on the parsed columns + * + * @function Highcharts.Data#parsed + * + * @return {boolean|undefined} + */ + Data.prototype.parsed = function () { + if (this.options.parsed) { + return this.options.parsed.call(this, this.columns); + } + }; + /** + * @private + * @function Highcharts.Data#getFreeIndexes + */ + Data.prototype.getFreeIndexes = function (numberOfColumns, seriesBuilders) { + var s, + i, + freeIndexes = [], + freeIndexValues = [], + referencedIndexes; + // Add all columns as free + for (i = 0; i < numberOfColumns; i = i + 1) { + freeIndexes.push(true); + } + // Loop all defined builders and remove their referenced columns + for (s = 0; s < seriesBuilders.length; s = s + 1) { + referencedIndexes = seriesBuilders[s].getReferencedColumnIndexes(); + for (i = 0; i < referencedIndexes.length; i = i + 1) { + freeIndexes[referencedIndexes[i]] = false; + } + } + // Collect the values for the free indexes + for (i = 0; i < freeIndexes.length; i = i + 1) { + if (freeIndexes[i]) { + freeIndexValues.push(i); + } + } + return freeIndexValues; + }; + /** + * If a complete callback function is provided in the options, interpret the + * columns into a Highcharts options object. + * + * @function Highcharts.Data#complete + */ + Data.prototype.complete = function () { + var columns = this.columns, + xColumns = [], + type, + options = this.options, + series, + data, + i, + j, + r, + seriesIndex, + chartOptions, + allSeriesBuilders = [], + builder, + freeIndexes, + typeCol, + index; + xColumns.length = columns.length; + if (options.complete || options.afterComplete) { + // Get the names and shift the top row + if (this.firstRowAsNames) { + for (i = 0; i < columns.length; i++) { + columns[i].name = columns[i].shift(); + } + } + // Use the next columns for series + series = []; + freeIndexes = this.getFreeIndexes(columns.length, this.valueCount.seriesBuilders); + // Populate defined series + for (seriesIndex = 0; seriesIndex < this.valueCount.seriesBuilders.length; seriesIndex++) { + builder = this.valueCount.seriesBuilders[seriesIndex]; + // If the builder can be populated with remaining columns, then + // add it to allBuilders + if (builder.populateColumns(freeIndexes)) { + allSeriesBuilders.push(builder); + } + } + // Populate dynamic series + while (freeIndexes.length > 0) { + builder = new SeriesBuilder(); + builder.addColumnReader(0, 'x'); + // Mark index as used (not free) + index = freeIndexes.indexOf(0); + if (index !== -1) { + freeIndexes.splice(index, 1); + } + for (i = 0; i < this.valueCount.global; i++) { + // Create and add a column reader for the next free column + // index + builder.addColumnReader(void 0, this.valueCount.globalPointArrayMap[i]); + } + // If the builder can be populated with remaining columns, then + // add it to allBuilders + if (builder.populateColumns(freeIndexes)) { + allSeriesBuilders.push(builder); + } + } + // Get the data-type from the first series x column + if (allSeriesBuilders.length > 0 && + allSeriesBuilders[0].readers.length > 0) { + typeCol = columns[allSeriesBuilders[0].readers[0].columnIndex]; + if (typeof typeCol !== 'undefined') { + if (typeCol.isDatetime) { + type = 'datetime'; + } + else if (!typeCol.isNumeric) { + type = 'category'; + } + } + } + // Axis type is category, then the "x" column should be called + // "name" + if (type === 'category') { + for (seriesIndex = 0; seriesIndex < allSeriesBuilders.length; seriesIndex++) { + builder = allSeriesBuilders[seriesIndex]; + for (r = 0; r < builder.readers.length; r++) { + if (builder.readers[r].configName === 'x') { + builder.readers[r].configName = 'name'; + } + } + } + } + // Read data for all builders + for (seriesIndex = 0; seriesIndex < allSeriesBuilders.length; seriesIndex++) { + builder = allSeriesBuilders[seriesIndex]; + // Iterate down the cells of each column and add data to the + // series + data = []; + for (j = 0; j < columns[0].length; j++) { + data[j] = builder.read(columns, j); + } + // Add the series + series[seriesIndex] = { + data: data + }; + if (builder.name) { + series[seriesIndex].name = builder.name; + } + if (type === 'category') { + series[seriesIndex].turboThreshold = 0; + } + } + // Do the callback + chartOptions = { + series: series + }; + if (type) { + chartOptions.xAxis = { + type: type + }; + if (type === 'category') { + chartOptions.xAxis.uniqueNames = false; + } + } + if (options.complete) { + options.complete(chartOptions); + } + // The afterComplete hook is used internally to avoid conflict with + // the externally available complete option. + if (options.afterComplete) { + options.afterComplete(chartOptions); + } + } + }; + /** + * Updates the chart with new data options. + * + * @function Highcharts.Data#update + * + * @param {Highcharts.DataOptions} options + * + * @param {boolean} [redraw=true] + */ + Data.prototype.update = function (options, redraw) { + var chart = this.chart; + if (options) { + // Set the complete handler + options.afterComplete = function (dataOptions) { + // Avoid setting axis options unless the type changes. Running + // Axis.update will cause the whole structure to be destroyed + // and rebuilt, and animation is lost. + if (dataOptions) { + if (dataOptions.xAxis && + chart.xAxis[0] && + dataOptions.xAxis.type === + chart.xAxis[0].options.type) { + delete dataOptions.xAxis; + } + // @todo looks not right: + chart.update(dataOptions, redraw, true); + } + }; + // Apply it + merge(true, chart.options.data, options); + this.init(chart.options.data); + } + }; + return Data; + }()); + // Register the Data prototype and data function on Highcharts + // Highcharts.Data = Data as any; + /** + * Creates a data object to parse data for a chart. + * + * @function Highcharts.data + * + * @param {Highcharts.DataOptions} dataOptions + * + * @param {Highcharts.Options} [chartOptions] + * + * @param {Highcharts.Chart} [chart] + * + * @return {Highcharts.Data} + */ + H.data = function (dataOptions, chartOptions, chart) { + return new H.Data(dataOptions, chartOptions, chart); + }; + // Extend Chart.init so that the Chart constructor accepts a new configuration + // option group, data. + addEvent(Chart, 'init', function (e) { + var chart = this, // eslint-disable-line no-invalid-this + userOptions = (e.args[0] || {}), + callback = e.args[1]; + if (userOptions && userOptions.data && !chart.hasDataDef) { + chart.hasDataDef = true; + /** + * The data parser for this chart. + * + * @name Highcharts.Chart#data + * @type {Highcharts.Data|undefined} + */ + chart.data = new H.Data(extend(userOptions.data, { + afterComplete: function (dataOptions) { + var i, + series; + // Merge series configs + if (Object.hasOwnProperty.call(userOptions, 'series')) { + if (typeof userOptions.series === 'object') { + i = Math.max(userOptions.series.length, dataOptions && dataOptions.series ? + dataOptions.series.length : + 0); + while (i--) { + series = userOptions.series[i] || {}; + userOptions.series[i] = merge(series, dataOptions && dataOptions.series ? + dataOptions.series[i] : + {}); + } + } + else { // Allow merging in dataOptions.series (#2856) + delete userOptions.series; + } + } + // Do the merge + userOptions = merge(dataOptions, userOptions); + // Run chart.init again + chart.init(userOptions, callback); + } + }), userOptions, chart); + e.preventDefault(); + } + }); + /** + * Creates a new SeriesBuilder. A SeriesBuilder consists of a number + * of ColumnReaders that reads columns and give them a name. + * Ex: A series builder can be constructed to read column 3 as 'x' and + * column 7 and 8 as 'y1' and 'y2'. + * The output would then be points/rows of the form {x: 11, y1: 22, y2: 33} + * + * The name of the builder is taken from the second column. In the above + * example it would be the column with index 7. + * + * @private + * @class + * @name SeriesBuilder + */ + var SeriesBuilder = /** @class */ (function () { + function SeriesBuilder() { + /* eslint-disable no-invalid-this */ + this.readers = []; + this.pointIsArray = true; + /* eslint-enable no-invalid-this */ + this.name = void 0; + } + /** + * Populates readers with column indexes. A reader can be added without + * a specific index and for those readers the index is taken sequentially + * from the free columns (this is handled by the ColumnCursor instance). + * + * @function SeriesBuilder#populateColumns + * + * @param {Array} freeIndexes + * + * @returns {boolean} + */ + SeriesBuilder.prototype.populateColumns = function (freeIndexes) { + var builder = this, + enoughColumns = true; + // Loop each reader and give it an index if its missing. + // The freeIndexes.shift() will return undefined if there + // are no more columns. + builder.readers.forEach(function (reader) { + if (typeof reader.columnIndex === 'undefined') { + reader.columnIndex = freeIndexes.shift(); + } + }); + // Now, all readers should have columns mapped. If not + // then return false to signal that this series should + // not be added. + builder.readers.forEach(function (reader) { + if (typeof reader.columnIndex === 'undefined') { + enoughColumns = false; + } + }); + return enoughColumns; + }; + /** + * Reads a row from the dataset and returns a point or array depending + * on the names of the readers. + * + * @function SeriesBuilder#read + * + * @param {Array>} columns + * + * @param {number} rowIndex + * + * @returns {Array|Highcharts.Dictionary} + */ + SeriesBuilder.prototype.read = function (columns, rowIndex) { + var builder = this, + pointIsArray = builder.pointIsArray, + point = pointIsArray ? [] : {}, + columnIndexes; + // Loop each reader and ask it to read its value. + // Then, build an array or point based on the readers names. + builder.readers.forEach(function (reader) { + var value = columns[reader.columnIndex][rowIndex]; + if (pointIsArray) { + point.push(value); + } + else { + if (reader.configName.indexOf('.') > 0) { + // Handle nested property names + Point.prototype.setNestedProperty(point, value, reader.configName); + } + else { + point[reader.configName] = value; + } + } + }); + // The name comes from the first column (excluding the x column) + if (typeof this.name === 'undefined' && builder.readers.length >= 2) { + columnIndexes = builder.getReferencedColumnIndexes(); + if (columnIndexes.length >= 2) { + // remove the first one (x col) + columnIndexes.shift(); + // Sort the remaining + columnIndexes.sort(function (a, b) { + return a - b; + }); + // Now use the lowest index as name column + this.name = columns[columnIndexes.shift()].name; + } + } + return point; + }; + /** + * Creates and adds ColumnReader from the given columnIndex and configName. + * ColumnIndex can be undefined and in that case the reader will be given + * an index when columns are populated. + * + * @function SeriesBuilder#addColumnReader + * + * @param {number} columnIndex + * + * @param {string} configName + */ + SeriesBuilder.prototype.addColumnReader = function (columnIndex, configName) { + this.readers.push({ + columnIndex: columnIndex, + configName: configName + }); + if (!(configName === 'x' || + configName === 'y' || + typeof configName === 'undefined')) { + this.pointIsArray = false; + } + }; + /** + * Returns an array of column indexes that the builder will use when + * reading data. + * + * @function SeriesBuilder#getReferencedColumnIndexes + * + * @returns {Array} + */ + SeriesBuilder.prototype.getReferencedColumnIndexes = function () { + var i, + referencedColumnIndexes = [], + columnReader; + for (i = 0; i < this.readers.length; i = i + 1) { + columnReader = this.readers[i]; + if (typeof columnReader.columnIndex !== 'undefined') { + referencedColumnIndexes.push(columnReader.columnIndex); + } + } + return referencedColumnIndexes; + }; + /** + * Returns true if the builder has a reader for the given configName. + * + * @function SeriesBuider#hasReader + * + * @param {string} configName + * + * @returns {boolean|undefined} + */ + SeriesBuilder.prototype.hasReader = function (configName) { + var i, + columnReader; + for (i = 0; i < this.readers.length; i = i + 1) { + columnReader = this.readers[i]; + if (columnReader.configName === configName) { + return true; + } + } + // Else return undefined + }; + return SeriesBuilder; + }()); + H.Data = Data; + + return H.Data; + }); + _registerModule(_modules, 'masters/modules/data.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/datagrouping.js b/highcharts/modules/datagrouping.js new file mode 100644 index 0000000..deff7ff --- /dev/null +++ b/highcharts/modules/datagrouping.js @@ -0,0 +1,26 @@ +/* + Highstock JS v8.2.0 (2020-08-20) + + Data grouping module + + (c) 2010-2019 Torstein Hnsi + + License: www.highcharts.com/license +*/ +(function(d){"object"===typeof module&&module.exports?(d["default"]=d,module.exports=d):"function"===typeof define&&define.amd?define("highcharts/modules/datagrouping",["highcharts"],function(g){d(g);d.Highcharts=g;return d}):d("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(d){function g(d,m,g,D){d.hasOwnProperty(m)||(d[m]=D.apply(null,g))}d=d?d._modules:{};g(d,"Extensions/DataGrouping.js",[d["Core/Axis/DateTimeAxis.js"],d["Core/Globals.js"],d["Core/Options.js"],d["Core/Series/Point.js"], +d["Core/Tooltip.js"],d["Core/Utilities.js"]],function(d,m,g,D,K,f){"";var y=f.addEvent,C=f.arrayMax,L=f.arrayMin,M=f.correctFloat,E=f.defined,N=f.error,O=f.extend,P=f.format,x=f.isNumber,F=f.merge,G=f.pick,B=m.Axis;f=m.Series;var u=m.approximations={sum:function(a){var c=a.length;if(!c&&a.hasNulls)var b=null;else if(c)for(b=0;c--;)b+=a[c];return b},average:function(a){var c=a.length;a=u.sum(a);x(a)&&c&&(a=M(a/c));return a},averages:function(){var a=[];[].forEach.call(arguments,function(c){a.push(u.average(c))}); +return"undefined"===typeof a[0]?void 0:a},open:function(a){return a.length?a[0]:a.hasNulls?null:void 0},high:function(a){return a.length?C(a):a.hasNulls?null:void 0},low:function(a){return a.length?L(a):a.hasNulls?null:void 0},close:function(a){return a.length?a[a.length-1]:a.hasNulls?null:void 0},ohlc:function(a,c,b,h){a=u.open(a);c=u.high(c);b=u.low(b);h=u.close(h);if(x(a)||x(c)||x(b)||x(h))return[a,c,b,h]},range:function(a,c){a=u.low(a);c=u.high(c);if(x(a)||x(c))return[a,c];if(null===a&&null=== +c)return null}},H=function(a,c,b,h){var e=this,d=e.data,v=e.options&&e.options.data,A=[],n=[],f=[],p=a.length,q=!!c,r=[],k=e.pointArrayMap,g=k&&k.length,w=["x"].concat(k||["y"]),m=0,y=0,t;h="function"===typeof h?h:u[h]?u[h]:u[e.getDGApproximation&&e.getDGApproximation()||"average"];g?k.forEach(function(){r.push([])}):r.push([]);var B=g||1;for(t=0;t<=p&&!(a[t]>=b[0]);t++);for(t;t<=p;t++){for(;"undefined"!==typeof b[m+1]&&a[t]>=b[m+1]||t===p;){var l=b[m];e.dataGroupInfo={start:e.cropStart+y,length:r[0].length}; +var z=h.apply(e,r);e.pointClass&&!E(e.dataGroupInfo.options)&&(e.dataGroupInfo.options=F(e.pointClass.prototype.optionsToObject.call({series:e},e.options.data[e.cropStart+y])),w.forEach(function(a){delete e.dataGroupInfo.options[a]}));"undefined"!==typeof z&&(A.push(l),n.push(z),f.push(e.dataGroupInfo));y=t;for(l=0;lthis.chart.plotSizeX/d||c&&f.forced)&&(e=!0);return e?d:0};B.prototype.setDataGrouping=function(a,c){var b;c=G(c,!0);a||(a={forced:!1,units:null});if(this instanceof B)for(b=this.series.length;b--;)this.series[b].update({dataGrouping:a},!1);else this.chart.options.series.forEach(function(b){b.dataGrouping=a},!1);this.ordinal&& +(this.ordinal.slope=void 0);c&&this.chart.redraw()};m.dataGrouping=I;"";return I});g(d,"masters/modules/datagrouping.src.js",[d["Extensions/DataGrouping.js"]],function(d){return d})}); +//# sourceMappingURL=datagrouping.js.map \ No newline at end of file diff --git a/highcharts/modules/datagrouping.js.map b/highcharts/modules/datagrouping.js.map new file mode 100644 index 0000000..312349d --- /dev/null +++ b/highcharts/modules/datagrouping.js.map @@ -0,0 +1 @@ +{"version":3,"file":"datagrouping.js.map","lineCount":25,"mappings":"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","sources":["datagrouping.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","DateTimeAxis","H","O","Point","Tooltip","U","addEvent","arrayMax","arrayMin","correctFloat","defined","error","extend","format","isNumber","merge","pick","Axis","Series","approximations","sum","arr","len","length","hasNulls","ret","average","averages","forEach","call","arguments","push","open","high","low","close","ohlc","range","groupData","xData","yData","groupPositions","approximation","series","data","dataOptions","options","groupedXData","groupedYData","groupMap","dataLength","handleYData","values","pointArrayMap","pointArrayMapLength","extendedPointArrayMap","concat","pos","start","i","getDGApproximation","valuesLen","pointX","dataGroupInfo","cropStart","groupedY","approximationFn","pointClass","prototype","optionsToObject","key","j","index","point","applyOptions","val","pointY","dataGrouping","seriesProto","baseProcessData","processData","baseGeneratePoints","generatePoints","commonOptions","groupPixelWidth","dateTimeLabelFormats","millisecond","second","minute","hour","day","week","month","year","specificOptions","line","spline","area","areaspline","arearange","column","columnrange","candlestick","defaultDataGroupingUnits","seriesProto.getDGApproximation","is","seriesProto.processData","chart","dataGroupingOptions","groupingEnabled","allowDG","enabled","isStock","visible","ignoreHiddenSeries","hasGroupedData","lastDataGrouping","currentDataGrouping","revertRequireSorting","forceCrop","hasProcessed","requireSorting","skip","destroyGroupedData","processedXData","groupAll","processedYData","plotSizeX","xAxis","ordinal","getGroupPixelWidth","isDirty","points","extremes","getExtremes","xMin","min","xMax","max","groupIntervalFactor","getGroupIntervalFactor","interval","getTimeTicks","AdditionsClass","normalizeTimeTickInterval","units","Math","startOfWeek","closestPointRange","groupedData","gapSize","smoothed","info","segmentStarts","indexOf","totalRange","dataMin","croppedData","cropData","preventGraphAnimation","seriesProto.destroyGroupedData","destroy","seriesProto.generatePoints","dataGroup","e","time","labelConfig","tooltipOptions","xDateFormat","formatString","isFooter","type","labelFormats","unitName","count","xDateFormatEnd","tooltip","getXDateFormat","formattedKey","dateFormat","styledMode","styledModeFormat","text","preventDefault","plotOptions","defaultOptions","baseOptions","useCommonDataGrouping","userOptions","Axis.prototype.getGroupPixelWidth","doGrouping","dgOptions","forced","setDataGrouping","Axis.prototype.setDataGrouping","redraw","update","seriesOptions","axis","slope"]} \ No newline at end of file diff --git a/highcharts/modules/datagrouping.src.js b/highcharts/modules/datagrouping.src.js new file mode 100644 index 0000000..589cf5e --- /dev/null +++ b/highcharts/modules/datagrouping.src.js @@ -0,0 +1,1025 @@ +/** + * @license Highstock JS v8.2.0 (2020-08-20) + * + * Data grouping module + * + * (c) 2010-2019 Torstein Hønsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/datagrouping', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'Extensions/DataGrouping.js', [_modules['Core/Axis/DateTimeAxis.js'], _modules['Core/Globals.js'], _modules['Core/Options.js'], _modules['Core/Series/Point.js'], _modules['Core/Tooltip.js'], _modules['Core/Utilities.js']], function (DateTimeAxis, H, O, Point, Tooltip, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * @typedef {"average"|"averages"|"open"|"high"|"low"|"close"|"sum"} Highcharts.DataGroupingApproximationValue + */ + /** + * @interface Highcharts.DataGroupingInfoObject + */ /** + * @name Highcharts.DataGroupingInfoObject#length + * @type {number} + */ /** + * @name Highcharts.DataGroupingInfoObject#options + * @type {Highcharts.SeriesOptionsType|undefined} + */ /** + * @name Highcharts.DataGroupingInfoObject#start + * @type {number} + */ + ''; // detach doclets above + var defaultOptions = O.defaultOptions; + var addEvent = U.addEvent, + arrayMax = U.arrayMax, + arrayMin = U.arrayMin, + correctFloat = U.correctFloat, + defined = U.defined, + error = U.error, + extend = U.extend, + format = U.format, + isNumber = U.isNumber, + merge = U.merge, + pick = U.pick; + var Axis = H.Axis, + Series = H.Series; + /* ************************************************************************** * + * Start data grouping module * + * ************************************************************************** */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Define the available approximation types. The data grouping + * approximations takes an array or numbers as the first parameter. In case + * of ohlc, four arrays are sent in as four parameters. Each array consists + * only of numbers. In case null values belong to the group, the property + * .hasNulls will be set to true on the array. + * + * @product highstock + * + * @private + * @name Highcharts.approximations + * @type {Highcharts.Dictionary} + */ + var approximations = H.approximations = { + sum: function (arr) { + var len = arr.length, + ret; + // 1. it consists of nulls exclusive + if (!len && arr.hasNulls) { + ret = null; + // 2. it has a length and real values + } + else if (len) { + ret = 0; + while (len--) { + ret += arr[len]; + } + } + // 3. it has zero length, so just return undefined + // => doNothing() + return ret; + }, + average: function (arr) { + var len = arr.length, + ret = approximations.sum(arr); + // If we have a number, return it divided by the length. If not, + // return null or undefined based on what the sum method finds. + if (isNumber(ret) && len) { + ret = correctFloat(ret / len); + } + return ret; + }, + // The same as average, but for series with multiple values, like area + // ranges. + averages: function () { + var ret = []; + [].forEach.call(arguments, function (arr) { + ret.push(approximations.average(arr)); + }); + // Return undefined when first elem. is undefined and let + // sum method handle null (#7377) + return typeof ret[0] === 'undefined' ? void 0 : ret; + }, + open: function (arr) { + return arr.length ? arr[0] : (arr.hasNulls ? null : void 0); + }, + high: function (arr) { + return arr.length ? + arrayMax(arr) : + (arr.hasNulls ? null : void 0); + }, + low: function (arr) { + return arr.length ? + arrayMin(arr) : + (arr.hasNulls ? null : void 0); + }, + close: function (arr) { + return arr.length ? + arr[arr.length - 1] : + (arr.hasNulls ? null : void 0); + }, + // ohlc and range are special cases where a multidimensional array is + // input and an array is output + ohlc: function (open, high, low, close) { + open = approximations.open(open); + high = approximations.high(high); + low = approximations.low(low); + close = approximations.close(close); + if (isNumber(open) || + isNumber(high) || + isNumber(low) || + isNumber(close)) { + return [open, high, low, close]; + } + // else, return is undefined + }, + range: function (low, high) { + low = approximations.low(low); + high = approximations.high(high); + if (isNumber(low) || isNumber(high)) { + return [low, high]; + } + if (low === null && high === null) { + return null; + } + // else, return is undefined + } + }; + var groupData = function (xData, + yData, + groupPositions, + approximation) { + var series = this, + data = series.data, + dataOptions = series.options && series.options.data, + groupedXData = [], + groupedYData = [], + groupMap = [], + dataLength = xData.length, + pointX, + pointY, + groupedY, + // when grouping the fake extended axis for panning, + // we don't need to consider y + handleYData = !!yData, + values = [], + approximationFn, + pointArrayMap = series.pointArrayMap, + pointArrayMapLength = pointArrayMap && pointArrayMap.length, + extendedPointArrayMap = ['x'].concat(pointArrayMap || ['y']), + pos = 0, + start = 0, + valuesLen, + i, + j; + /** + * @private + */ + function getApproximation(approx) { + if (typeof approx === 'function') { + return approx; + } + if (approximations[approx]) { + return approximations[approx]; + } + return approximations[(series.getDGApproximation && series.getDGApproximation()) || + 'average']; + } + approximationFn = getApproximation(approximation); + // Calculate values array size from pointArrayMap length + if (pointArrayMapLength) { + pointArrayMap.forEach(function () { + values.push([]); + }); + } + else { + values.push([]); + } + valuesLen = pointArrayMapLength || 1; + // Start with the first point within the X axis range (#2696) + for (i = 0; i <= dataLength; i++) { + if (xData[i] >= groupPositions[0]) { + break; + } + } + for (i; i <= dataLength; i++) { + // when a new group is entered, summarize and initialize + // the previous group + while ((typeof groupPositions[pos + 1] !== 'undefined' && + xData[i] >= groupPositions[pos + 1]) || + i === dataLength) { // get the last group + // get group x and y + pointX = groupPositions[pos]; + series.dataGroupInfo = { + start: series.cropStart + start, + length: values[0].length + }; + groupedY = approximationFn.apply(series, values); + // By default, let options of the first grouped point be passed over + // to the grouped point. This allows preserving properties like + // `name` and `color` or custom properties. Implementers can + // override this from the approximation function, where they can + // write custom options to `this.dataGroupInfo.options`. + if (series.pointClass && !defined(series.dataGroupInfo.options)) { + // Convert numbers and arrays into objects + series.dataGroupInfo.options = merge(series.pointClass.prototype + .optionsToObject.call({ series: series }, series.options.data[series.cropStart + start])); + // Make sure the raw data (x, y, open, high etc) is not copied + // over and overwriting approximated data. + extendedPointArrayMap.forEach(function (key) { + delete series.dataGroupInfo.options[key]; + }); + } + // push the grouped data + if (typeof groupedY !== 'undefined') { + groupedXData.push(pointX); + groupedYData.push(groupedY); + groupMap.push(series.dataGroupInfo); + } + // reset the aggregate arrays + start = i; + for (j = 0; j < valuesLen; j++) { + values[j].length = 0; // faster than values[j] = [] + values[j].hasNulls = false; + } + // Advance on the group positions + pos += 1; + // don't loop beyond the last group + if (i === dataLength) { + break; + } + } + // break out + if (i === dataLength) { + break; + } + // for each raw data point, push it to an array that contains all values + // for this specific group + if (pointArrayMap) { + var index = series.cropStart + i, + point = (data && data[index]) || + series.pointClass.prototype.applyOptions.apply({ + series: series + }, + [dataOptions[index]]), + val; + for (j = 0; j < pointArrayMapLength; j++) { + val = point[pointArrayMap[j]]; + if (isNumber(val)) { + values[j].push(val); + } + else if (val === null) { + values[j].hasNulls = true; + } + } + } + else { + pointY = handleYData ? yData[i] : null; + if (isNumber(pointY)) { + values[0].push(pointY); + } + else if (pointY === null) { + values[0].hasNulls = true; + } + } + } + return { + groupedXData: groupedXData, + groupedYData: groupedYData, + groupMap: groupMap + }; + }; + var dataGrouping = { + approximations: approximations, + groupData: groupData + }; + // ----------------------------------------------------------------------------- + // The following code applies to implementation of data grouping on a Series + var seriesProto = Series.prototype, baseProcessData = seriesProto.processData, baseGeneratePoints = seriesProto.generatePoints, + /** @ignore */ + commonOptions = { + // enabled: null, // (true for stock charts, false for basic), + // forced: undefined, + groupPixelWidth: 2, + // the first one is the point or start value, the second is the start + // value if we're dealing with range, the third one is the end value if + // dealing with a range + dateTimeLabelFormats: { + millisecond: [ + '%A, %b %e, %H:%M:%S.%L', + '%A, %b %e, %H:%M:%S.%L', + '-%H:%M:%S.%L' + ], + second: [ + '%A, %b %e, %H:%M:%S', + '%A, %b %e, %H:%M:%S', + '-%H:%M:%S' + ], + minute: [ + '%A, %b %e, %H:%M', + '%A, %b %e, %H:%M', + '-%H:%M' + ], + hour: [ + '%A, %b %e, %H:%M', + '%A, %b %e, %H:%M', + '-%H:%M' + ], + day: [ + '%A, %b %e, %Y', + '%A, %b %e', + '-%A, %b %e, %Y' + ], + week: [ + 'Week from %A, %b %e, %Y', + '%A, %b %e', + '-%A, %b %e, %Y' + ], + month: [ + '%B %Y', + '%B', + '-%B %Y' + ], + year: [ + '%Y', + '%Y', + '-%Y' + ] + } + // smoothed = false, // enable this for navigator series only + }, specificOptions = { + line: {}, + spline: {}, + area: {}, + areaspline: {}, + arearange: {}, + column: { + groupPixelWidth: 10 + }, + columnrange: { + groupPixelWidth: 10 + }, + candlestick: { + groupPixelWidth: 10 + }, + ohlc: { + groupPixelWidth: 5 + } + }, + // units are defined in a separate array to allow complete overriding in + // case of a user option + defaultDataGroupingUnits = H.defaultDataGroupingUnits = [ + [ + 'millisecond', + [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples + ], [ + 'second', + [1, 2, 5, 10, 15, 30] + ], [ + 'minute', + [1, 2, 5, 10, 15, 30] + ], [ + 'hour', + [1, 2, 3, 4, 6, 8, 12] + ], [ + 'day', + [1] + ], [ + 'week', + [1] + ], [ + 'month', + [1, 3, 6] + ], [ + 'year', + null + ] + ]; + // Set default approximations to the prototypes if present. Properties are + // inherited down. Can be overridden for individual series types. + seriesProto.getDGApproximation = function () { + if (this.is('arearange')) { + return 'range'; + } + if (this.is('ohlc')) { + return 'ohlc'; + } + if (this.is('column')) { + return 'sum'; + } + return 'average'; + }; + /** + * Takes parallel arrays of x and y data and groups the data into intervals + * defined by groupPositions, a collection of starting x values for each group. + * + * @private + * @function Highcharts.Series#groupData + * + * @param {Array} xData + * + * @param {Array|Array>} yData + * + * @param {boolean} groupPositions + * + * @param {string|Function} approximation + * + * @return {void} + */ + seriesProto.groupData = groupData; + // Extend the basic processData method, that crops the data to the current zoom + // range, with data grouping logic. + seriesProto.processData = function () { + var series = this, + chart = series.chart, + options = series.options, + dataGroupingOptions = options.dataGrouping, + groupingEnabled = series.allowDG !== false && dataGroupingOptions && + pick(dataGroupingOptions.enabled, + chart.options.isStock), + visible = (series.visible || !chart.options.chart.ignoreHiddenSeries), + hasGroupedData, + skip, + lastDataGrouping = this.currentDataGrouping, + currentDataGrouping, + croppedData, + revertRequireSorting = false; + // Run base method + series.forceCrop = groupingEnabled; // #334 + series.groupPixelWidth = null; // #2110 + series.hasProcessed = true; // #2692 + // Data needs to be sorted for dataGrouping + if (groupingEnabled && !series.requireSorting) { + series.requireSorting = revertRequireSorting = true; + } + // Skip if processData returns false or if grouping is disabled (in that + // order) + skip = (baseProcessData.apply(series, arguments) === false || + !groupingEnabled); + // Revert original requireSorting value if changed + if (revertRequireSorting) { + series.requireSorting = false; + } + if (!skip) { + series.destroyGroupedData(); + var i, + processedXData = dataGroupingOptions.groupAll ? + series.xData : + series.processedXData, + processedYData = dataGroupingOptions.groupAll ? + series.yData : + series.processedYData, + plotSizeX = chart.plotSizeX, + xAxis = series.xAxis, + ordinal = xAxis.options.ordinal, + groupPixelWidth = series.groupPixelWidth = + xAxis.getGroupPixelWidth && xAxis.getGroupPixelWidth(); + // Execute grouping if the amount of points is greater than the limit + // defined in groupPixelWidth + if (groupPixelWidth) { + hasGroupedData = true; + // Force recreation of point instances in series.translate, #5699 + series.isDirty = true; + series.points = null; // #6709 + var extremes = xAxis.getExtremes(), + xMin = extremes.min, + xMax = extremes.max, + groupIntervalFactor = (ordinal && + xAxis.ordinal && + xAxis.ordinal.getGroupIntervalFactor(xMin, + xMax, + series)) || 1, + interval = (groupPixelWidth * (xMax - xMin) / plotSizeX) * + groupIntervalFactor, + groupPositions = xAxis.getTimeTicks(DateTimeAxis.AdditionsClass.prototype.normalizeTimeTickInterval(interval, + dataGroupingOptions.units || + defaultDataGroupingUnits), + // Processed data may extend beyond axis (#4907) + Math.min(xMin, + processedXData[0]), + Math.max(xMax, + processedXData[processedXData.length - 1]), + xAxis.options.startOfWeek, + processedXData, + series.closestPointRange), + groupedData = seriesProto.groupData.apply(series, + [ + processedXData, + processedYData, + groupPositions, + dataGroupingOptions.approximation + ]), + groupedXData = groupedData.groupedXData, + groupedYData = groupedData.groupedYData, + gapSize = 0; + // Prevent the smoothed data to spill out left and right, and make + // sure data is not shifted to the left + if (dataGroupingOptions.smoothed && groupedXData.length) { + i = groupedXData.length - 1; + groupedXData[i] = Math.min(groupedXData[i], xMax); + while (i-- && i > 0) { + groupedXData[i] += interval / 2; + } + groupedXData[0] = Math.max(groupedXData[0], xMin); + } + // Record what data grouping values were used + for (i = 1; i < groupPositions.length; i++) { + // The grouped gapSize needs to be the largest distance between + // the group to capture varying group sizes like months or DST + // crossing (#10000). Also check that the gap is not at the + // start of a segment. + if (!groupPositions.info.segmentStarts || + groupPositions.info.segmentStarts.indexOf(i) === -1) { + gapSize = Math.max(groupPositions[i] - groupPositions[i - 1], gapSize); + } + } + currentDataGrouping = groupPositions.info; + currentDataGrouping.gapSize = gapSize; + series.closestPointRange = groupPositions.info.totalRange; + series.groupMap = groupedData.groupMap; + // Make sure the X axis extends to show the first group (#2533) + // But only for visible series (#5493, #6393) + if (defined(groupedXData[0]) && + groupedXData[0] < xAxis.min && + visible) { + if ((!defined(xAxis.options.min) && + xAxis.min <= xAxis.dataMin) || + xAxis.min === xAxis.dataMin) { + xAxis.min = Math.min(groupedXData[0], xAxis.min); + } + xAxis.dataMin = Math.min(groupedXData[0], xAxis.dataMin); + } + // We calculated all group positions but we should render + // only the ones within the visible range + if (dataGroupingOptions.groupAll) { + croppedData = series.cropData(groupedXData, groupedYData, xAxis.min, xAxis.max, 1 // Ordinal xAxis will remove left-most points otherwise + ); + groupedXData = croppedData.xData; + groupedYData = croppedData.yData; + } + // Set series props + series.processedXData = groupedXData; + series.processedYData = groupedYData; + } + else { + series.groupMap = null; + } + series.hasGroupedData = hasGroupedData; + series.currentDataGrouping = currentDataGrouping; + series.preventGraphAnimation = + (lastDataGrouping && lastDataGrouping.totalRange) !== + (currentDataGrouping && currentDataGrouping.totalRange); + } + }; + // Destroy the grouped data points. #622, #740 + seriesProto.destroyGroupedData = function () { + // Clear previous groups + if (this.groupedData) { + this.groupedData.forEach(function (point, i) { + if (point) { + this.groupedData[i] = point.destroy ? + point.destroy() : null; + } + }, this); + // Clears all: + // - `this.groupedData` + // - `this.points` + // - `preserve` object in series.update() + this.groupedData.length = 0; + } + }; + // Override the generatePoints method by adding a reference to grouped data + seriesProto.generatePoints = function () { + baseGeneratePoints.apply(this); + // Record grouped data in order to let it be destroyed the next time + // processData runs + this.destroyGroupedData(); // #622 + this.groupedData = this.hasGroupedData ? this.points : null; + }; + // Override point prototype to throw a warning when trying to update grouped + // points. + addEvent(Point, 'update', function () { + if (this.dataGroup) { + error(24, false, this.series.chart); + return false; + } + }); + // Extend the original method, make the tooltip's header reflect the grouped + // range. + addEvent(Tooltip, 'headerFormatter', function (e) { + var tooltip = this, + chart = this.chart, + time = chart.time, + labelConfig = e.labelConfig, + series = labelConfig.series, + options = series.options, + tooltipOptions = series.tooltipOptions, + dataGroupingOptions = options.dataGrouping, + xDateFormat = tooltipOptions.xDateFormat, + xDateFormatEnd, + xAxis = series.xAxis, + currentDataGrouping, + dateTimeLabelFormats, + labelFormats, + formattedKey, + formatString = tooltipOptions[(e.isFooter ? 'footer' : 'header') + 'Format']; + // apply only to grouped series + if (xAxis && + xAxis.options.type === 'datetime' && + dataGroupingOptions && + isNumber(labelConfig.key)) { + // set variables + currentDataGrouping = series.currentDataGrouping; + dateTimeLabelFormats = dataGroupingOptions.dateTimeLabelFormats || + // Fallback to commonOptions (#9693) + commonOptions.dateTimeLabelFormats; + // if we have grouped data, use the grouping information to get the + // right format + if (currentDataGrouping) { + labelFormats = + dateTimeLabelFormats[currentDataGrouping.unitName]; + if (currentDataGrouping.count === 1) { + xDateFormat = labelFormats[0]; + } + else { + xDateFormat = labelFormats[1]; + xDateFormatEnd = labelFormats[2]; + } + // if not grouped, and we don't have set the xDateFormat option, get the + // best fit, so if the least distance between points is one minute, show + // it, but if the least distance is one day, skip hours and minutes etc. + } + else if (!xDateFormat && dateTimeLabelFormats) { + xDateFormat = tooltip.getXDateFormat(labelConfig, tooltipOptions, xAxis); + } + // now format the key + formattedKey = time.dateFormat(xDateFormat, labelConfig.key); + if (xDateFormatEnd) { + formattedKey += time.dateFormat(xDateFormatEnd, labelConfig.key + currentDataGrouping.totalRange - 1); + } + // Replace default header style with class name + if (series.chart.styledMode) { + formatString = this.styledModeFormat(formatString); + } + // return the replaced format + e.text = format(formatString, { + point: extend(labelConfig.point, { key: formattedKey }), + series: series + }, chart); + e.preventDefault(); + } + }); + // Destroy grouped data on series destroy + addEvent(Series, 'destroy', seriesProto.destroyGroupedData); + // Handle default options for data grouping. This must be set at runtime because + // some series types are defined after this. + addEvent(Series, 'afterSetOptions', function (e) { + var options = e.options, + type = this.type, + plotOptions = this.chart.options.plotOptions, + defaultOptions = O.defaultOptions.plotOptions[type].dataGrouping, + // External series, for example technical indicators should also + // inherit commonOptions which are not available outside this module + baseOptions = this.useCommonDataGrouping && commonOptions; + if (specificOptions[type] || baseOptions) { // #1284 + if (!defaultOptions) { + defaultOptions = merge(commonOptions, specificOptions[type]); + } + options.dataGrouping = merge(baseOptions, defaultOptions, plotOptions.series && plotOptions.series.dataGrouping, // #1228 + // Set by the StockChart constructor: + plotOptions[type].dataGrouping, this.userOptions.dataGrouping); + } + }); + // When resetting the scale reset the hasProccessed flag to avoid taking + // previous data grouping of neighbour series into accound when determining + // group pixel width (#2692). + addEvent(Axis, 'afterSetScale', function () { + this.series.forEach(function (series) { + series.hasProcessed = false; + }); + }); + // Get the data grouping pixel width based on the greatest defined individual + // width of the axis' series, and if whether one of the axes need grouping. + Axis.prototype.getGroupPixelWidth = function () { + var series = this.series, + len = series.length, + i, + groupPixelWidth = 0, + doGrouping = false, + dataLength, + dgOptions; + // If multiple series are compared on the same x axis, give them the same + // group pixel width (#334) + i = len; + while (i--) { + dgOptions = series[i].options.dataGrouping; + if (dgOptions) { + groupPixelWidth = Math.max(groupPixelWidth, + // Fallback to commonOptions (#9693) + pick(dgOptions.groupPixelWidth, commonOptions.groupPixelWidth)); + } + } + // If one of the series needs grouping, apply it to all (#1634) + i = len; + while (i--) { + dgOptions = series[i].options.dataGrouping; + if (dgOptions && series[i].hasProcessed) { // #2692 + dataLength = (series[i].processedXData || series[i].data).length; + // Execute grouping if the amount of points is greater than the + // limit defined in groupPixelWidth + if (series[i].groupPixelWidth || + dataLength > + (this.chart.plotSizeX / groupPixelWidth) || + (dataLength && dgOptions.forced)) { + doGrouping = true; + } + } + } + return doGrouping ? groupPixelWidth : 0; + }; + /** + * Highstock only. Force data grouping on all the axis' series. + * + * @product highstock + * + * @function Highcharts.Axis#setDataGrouping + * + * @param {boolean|Highcharts.DataGroupingOptionsObject} [dataGrouping] + * A `dataGrouping` configuration. Use `false` to disable data grouping + * dynamically. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for a later call to + * {@link Chart#redraw}. + * + * @return {void} + */ + Axis.prototype.setDataGrouping = function (dataGrouping, redraw) { + var axis = this; + var i; + redraw = pick(redraw, true); + if (!dataGrouping) { + dataGrouping = { + forced: false, + units: null + }; + } + // Axis is instantiated, update all series + if (this instanceof Axis) { + i = this.series.length; + while (i--) { + this.series[i].update({ + dataGrouping: dataGrouping + }, false); + } + // Axis not yet instanciated, alter series options + } + else { + this.chart.options.series.forEach(function (seriesOptions) { + seriesOptions.dataGrouping = dataGrouping; + }, false); + } + // Clear ordinal slope, so we won't accidentaly use the old one (#7827) + if (axis.ordinal) { + axis.ordinal.slope = void 0; + } + if (redraw) { + this.chart.redraw(); + } + }; + H.dataGrouping = dataGrouping; + /* eslint-enable no-invalid-this, valid-jsdoc */ + /** + * Data grouping is the concept of sampling the data values into larger + * blocks in order to ease readability and increase performance of the + * JavaScript charts. Highstock by default applies data grouping when + * the points become closer than a certain pixel value, determined by + * the `groupPixelWidth` option. + * + * If data grouping is applied, the grouping information of grouped + * points can be read from the [Point.dataGroup]( + * /class-reference/Highcharts.Point#dataGroup). If point options other than + * the data itself are set, for example `name` or `color` or custom properties, + * the grouping logic doesn't know how to group it. In this case the options of + * the first point instance are copied over to the group point. This can be + * altered through a custom `approximation` callback function. + * + * @declare Highcharts.DataGroupingOptionsObject + * @product highstock + * @requires product:highstock + * @requires module:modules/datagrouping + * @apioption plotOptions.series.dataGrouping + */ + /** + * The method of approximation inside a group. When for example 30 days + * are grouped into one month, this determines what value should represent + * the group. Possible values are "average", "averages", "open", "high", + * "low", "close" and "sum". For OHLC and candlestick series the approximation + * is "ohlc" by default, which finds the open, high, low and close values + * within all the grouped data. For ranges, the approximation is "range", + * which finds the low and high values. For multi-dimensional data, + * like ranges and OHLC, "averages" will compute the average for each + * dimension. + * + * Custom aggregate methods can be added by assigning a callback function + * as the approximation. This function takes a numeric array as the + * argument and should return a single numeric value or `null`. Note + * that the numeric array will never contain null values, only true + * numbers. Instead, if null values are present in the raw data, the + * numeric array will have an `.hasNulls` property set to `true`. For + * single-value data sets the data is available in the first argument + * of the callback function. For OHLC data sets, all the open values + * are in the first argument, all high values in the second etc. + * + * Since v4.2.7, grouping meta data is available in the approximation + * callback from `this.dataGroupInfo`. It can be used to extract information + * from the raw data. + * + * Defaults to `average` for line-type series, `sum` for columns, `range` + * for range series and `ohlc` for OHLC and candlestick. + * + * @sample {highstock} stock/plotoptions/series-datagrouping-approximation + * Approximation callback with custom data + * + * @type {Highcharts.DataGroupingApproximationValue|Function} + * @apioption plotOptions.series.dataGrouping.approximation + */ + /** + * Datetime formats for the header of the tooltip in a stock chart. + * The format can vary within a chart depending on the currently selected + * time range and the current data grouping. + * + * The default formats are: + * ```js + * { + * millisecond: [ + * '%A, %b %e, %H:%M:%S.%L', '%A, %b %e, %H:%M:%S.%L', '-%H:%M:%S.%L' + * ], + * second: ['%A, %b %e, %H:%M:%S', '%A, %b %e, %H:%M:%S', '-%H:%M:%S'], + * minute: ['%A, %b %e, %H:%M', '%A, %b %e, %H:%M', '-%H:%M'], + * hour: ['%A, %b %e, %H:%M', '%A, %b %e, %H:%M', '-%H:%M'], + * day: ['%A, %b %e, %Y', '%A, %b %e', '-%A, %b %e, %Y'], + * week: ['Week from %A, %b %e, %Y', '%A, %b %e', '-%A, %b %e, %Y'], + * month: ['%B %Y', '%B', '-%B %Y'], + * year: ['%Y', '%Y', '-%Y'] + * } + * ``` + * + * For each of these array definitions, the first item is the format + * used when the active time span is one unit. For instance, if the + * current data applies to one week, the first item of the week array + * is used. The second and third items are used when the active time + * span is more than two units. For instance, if the current data applies + * to two weeks, the second and third item of the week array are used, + * and applied to the start and end date of the time span. + * + * @type {object} + * @apioption plotOptions.series.dataGrouping.dateTimeLabelFormats + */ + /** + * Enable or disable data grouping. + * + * @type {boolean} + * @default true + * @apioption plotOptions.series.dataGrouping.enabled + */ + /** + * When data grouping is forced, it runs no matter how small the intervals + * are. This can be handy for example when the sum should be calculated + * for values appearing at random times within each hour. + * + * @type {boolean} + * @default false + * @apioption plotOptions.series.dataGrouping.forced + */ + /** + * The approximate pixel width of each group. If for example a series + * with 30 points is displayed over a 600 pixel wide plot area, no grouping + * is performed. If however the series contains so many points that + * the spacing is less than the groupPixelWidth, Highcharts will try + * to group it into appropriate groups so that each is more or less + * two pixels wide. If multiple series with different group pixel widths + * are drawn on the same x axis, all series will take the greatest width. + * For example, line series have 2px default group width, while column + * series have 10px. If combined, both the line and the column will + * have 10px by default. + * + * @type {number} + * @default 2 + * @apioption plotOptions.series.dataGrouping.groupPixelWidth + */ + /** + * By default only points within the visible range are grouped. Enabling this + * option will force data grouping to calculate all grouped points for a given + * dataset. That option prevents for example a column series from calculating + * a grouped point partially. The effect is similar to + * [Series.getExtremesFromAll](#plotOptions.series.getExtremesFromAll) but does + * not affect yAxis extremes. + * + * @sample {highstock} stock/plotoptions/series-datagrouping-groupall/ + * Two series with the same data but different groupAll setting + * + * @type {boolean} + * @default false + * @since 6.1.0 + * @apioption plotOptions.series.dataGrouping.groupAll + */ + /** + * Normally, a group is indexed by the start of that group, so for example + * when 30 daily values are grouped into one month, that month's x value + * will be the 1st of the month. This apparently shifts the data to + * the left. When the smoothed option is true, this is compensated for. + * The data is shifted to the middle of the group, and min and max + * values are preserved. Internally, this is used in the Navigator series. + * + * @type {boolean} + * @default false + * @apioption plotOptions.series.dataGrouping.smoothed + */ + /** + * An array determining what time intervals the data is allowed to be + * grouped to. Each array item is an array where the first value is + * the time unit and the second value another array of allowed multiples. + * + * Defaults to: + * ```js + * units: [[ + * 'millisecond', // unit name + * [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples + * ], [ + * 'second', + * [1, 2, 5, 10, 15, 30] + * ], [ + * 'minute', + * [1, 2, 5, 10, 15, 30] + * ], [ + * 'hour', + * [1, 2, 3, 4, 6, 8, 12] + * ], [ + * 'day', + * [1] + * ], [ + * 'week', + * [1] + * ], [ + * 'month', + * [1, 3, 6] + * ], [ + * 'year', + * null + * ]] + * ``` + * + * @type {Array|null)>>} + * @apioption plotOptions.series.dataGrouping.units + */ + /** + * The approximate pixel width of each group. If for example a series + * with 30 points is displayed over a 600 pixel wide plot area, no grouping + * is performed. If however the series contains so many points that + * the spacing is less than the groupPixelWidth, Highcharts will try + * to group it into appropriate groups so that each is more or less + * two pixels wide. Defaults to `10`. + * + * @sample {highstock} stock/plotoptions/series-datagrouping-grouppixelwidth/ + * Two series with the same data density but different groupPixelWidth + * + * @type {number} + * @default 10 + * @apioption plotOptions.column.dataGrouping.groupPixelWidth + */ + ''; // required by JSDoc parsing + + return dataGrouping; + }); + _registerModule(_modules, 'masters/modules/datagrouping.src.js', [_modules['Extensions/DataGrouping.js']], function (dataGrouping) { + + + return dataGrouping; + }); +})); \ No newline at end of file diff --git a/highcharts/modules/debugger.js b/highcharts/modules/debugger.js new file mode 100644 index 0000000..8478d7f --- /dev/null +++ b/highcharts/modules/debugger.js @@ -0,0 +1,30 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Debugger module + + (c) 2012-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/debugger",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,c,b,f){a.hasOwnProperty(c)||(a[c]=f.apply(null,b))}a=a?a._modules:{};b(a,"error-messages.js",[a["Core/Globals.js"]],function(a){a.errorMessages={10:{title:"Can't plot zero or subzero values on a logarithmic axis", +text:'

    Can\'t plot zero or subzero values on a logarithmic axis

    This error occurs in the following situations:

    • If a zero or subzero data value is added to a logarithmic axis
    • If the minimum of a logarithimic axis is set to 0 or less
    • If the threshold is set to 0 or less

    Note: As of Highcharts 5.0.8 it\'s possible to bypass this error message by setting Axis.prototype.allowNegativeLog to true, and add custom conversion functions. View live demo. It is also possible to use a similar workaround for colorAxis. View live demo.

    ', +enduser:'

    Can\'t plot zero or subzero values on a logarithmic axis

    This error occurs in the following situations:

    • If a zero or subzero data value is added to a logarithmic axis
    • If the minimum of a logarithimic axis is set to 0 or less
    • If the threshold is set to 0 or less

    As of Highcharts 5.0.8 it\'s possible to bypass this error message by setting Axis.prototype.allowNegativeLog to true and add custom conversion functions. ">View Live Demo. It is also possible to use a similar workaround for colorAxis. View live demo.

    '}, +11:{title:"Can't link axes of different type",text:"

    Can't link axes of different type

    This error occurs when using the linkedTo option to link two axes of different types, for example a logarithmic axis to a linear axis. Highcharts can't link these because the calculation of ticks, extremes, padding etc. is different.

    "},12:{title:"Highcharts expects point configuration to be numbers or arrays in turbo mode",text:'

    Highcharts expects point configuration to be numbers or arrays in turbo mode

    This error occurs if the series.data option contains object configurations and the number of points exceeds the turboThreshold. It can be fixed by either setting turboThreshold to a higher value, or changing the point configurations to numbers or arrays.

    In boost mode, turbo mode is always on, which means only array of numbers or two dimensional arrays are allowed.

    See plotOptions.series.turboThreshold

    '}, +13:{title:"Rendering div not found",text:'

    Rendering div not found

    This error occurs if the chart.renderTo option is misconfigured so that Highcharts is unable to find the HTML element to render the chart in.

    If using a DOM ID when creating the chart, make sure a node with the same ID exists somewhere in the DOM.

    '},14:{title:"String value sent to series.data, expected Number",text:"

    String value sent to series.data, expected Number

    This happens if using a string as a data point, for example in a setup like this:

    series: [{\n    data: ["3", "5", "1", "6"]\n}]

    Highcharts expects numerical data values.

    The most common reason for this error this is that data is parsed from CSV or from a XML source, and the implementer forgot to run parseFloat on the parsed value.

    Note: For performance reasons internal type casting is not performed, and only the first value is checked (since 2.3).

    "}, +15:{title:"Highcharts expects data to be sorted",text:"

    Highcharts expects data to be sorted

    This happens when creating a line series or a stock chart where the data is not sorted in ascending X order.

    For performance reasons, Highcharts does not sort the data, instead it requires that the implementer pre-sorts the data.

    "},16:{title:"Highcharts already defined in the page",text:"

    Highcharts already defined in the page

    This error happens if the Highcharts namespace already exists when loading Highcharts or Highstock.

    This is caused by including Highcharts or Highstock more than once.

    Keep in mind that the Highcharts.Chart constructor and all features of Highcharts are included in Highstock, so if using the Chart and StockChart constructors in combination, only the highstock.js file is required.

    "}, +17:{title:"The requested series type does not exist",text:"

    The requested series type does not exist

    This error happens when setting chart.type or series.type to a series type that isn't defined in Highcharts. A typical reason may be that the module or extension where the series type is defined isn't included.

    For example in order to create an arearange series, the highcharts-more.js file must be loaded.

    "},18:{title:"The requested axis does not exist", +text:"

    The requested axis does not exist

    This error happens when setting a series' xAxis or yAxis property to point to an axis that does not exist.

    "},19:{title:"Too many ticks",text:"

    Too many ticks

    This error happens when applying too many ticks to an axis, specifically when adding more ticks than the axis pixel length.

    With default value this won't happen, but there are edge cases, for example when setting axis categories and xAxis.labels.step in combination with a long data range, when the axis is instructed to create a great number of ticks.

    "}, +20:{title:"Can't add object point configuration to a long data series",text:"

    Can't add object point configuration to a long data series

    In Highstock, when trying to add a point using the object literal configuration syntax, it will only work when the number of data points is below the series' turboThreshold. Instead of the object syntax, use the Array syntax.

    "},21:{title:"Can't find Proj4js library", +text:'

    Can\'t find Proj4js library

    Using latitude/longitude functionality in Highmaps requires the Proj4js library to be loaded.

    '},22:{title:"Map does not support latitude/longitude",text:'

    Map does not support latitude/longitude

    The loaded map does not support latitude/longitude functionality. This is only supported with maps from the official Highmaps map collection from version 1.1.0 onwards. If you are using a custom map, consider using the Proj4js library to convert between projections.

    '}, +23:{title:"Unsupported color format used for color interpolation",text:"

    Unsupported color format used for color interpolation

    Highcharts supports three color formats primarily: hex (#FFFFFF), rgb (rgba(255,255,255)) and rgba (rgba(255,255,255,1)). If any other format, like 3-digit colors (#FFF), named colors (white) or gradient structures are used in for example a heatmap, Highcharts will fail to interpolate and will instead use the end-color with no interpolation applied.

    We've chosen to preserve this limitation in order to keep the weight of the implementation at a minimum.

    "}, +24:{title:"Cannot run Point.update on a grouped point",text:"

    Cannot run Point.update on a grouped point

    Running Point.update in Highstock when a point is grouped by data grouping is not supported.

    This is not supported because when data grouping is enabled, there won't be any references to the raw points, which is required by the Point.update function.

    "},25:{title:"Can't find Moment.js library",text:'

    Can\'t find Moment.js library

    Using the global.timezone option requires the Moment.js library to be loaded.

    '}, +26:{title:"WebGL not supported, and no fallback module included",text:"

    WebGL not supported, and no fallback module included

    This happens when the browser doesn't support WebGL,and the canvas fallback module (boost-canvas.js) hasn't been included OR if the fallback module was includedafter the boost module.

    If a fallback is required, make sure to include boost-canvas.js, and that it's included before boost.js.

    Please note that the fallback module is not intended as a fully-featured one. Rather, it's a minimal implementation of the WebGL counterpart.

    "}, +27:{title:"This browser does not support SVG",text:"

    This browser does not support SVG

    This happens in old IE when the oldie.js module isn't loaded.

    If compatibility with IE versions 6, 7 and 8 is required, add the module after loading highcharts.js. In a website context, it's a good idea to load it in a conditional comment to avoid traffic overhead and dead code in modern browsers:

    <!--[if lt IE 9]>\n    <script src='https://code.highcharts.com/modules/oldie.js'></script>\n<![endif]-->
    "}, +28:{title:"Fallback to export server disabled",text:'

    Fallback to export server disabled

    This happens when the offline export module encounters a chart that it can\'t export successfully, and the fallback to the online export server is disabled. The offline exporting module will fail for certain browsers, and certain features (e.g. exporting.allowHTML ), depending on the type of image exporting to. For a compatibility overview, see Client Side Export.

    For very complex charts, it\'s possible that exporting fail in browsers that don\'t support Blob objects, due to data URL length limits. It\'s always recommended to define the exporting.error callback when disabling the fallback, so that details can be provided to the end-user if offline export isn\'t working for them.

    '}, +29:{title:"Browser does not support WebAudio",text:"

    Browser does not support WebAudio

    This happens when you attempt to use the sonification module on a chart in a browser or environment that does not support the WebAudio API. This API is supported on all modern browsers, including Microsoft Edge, Google Chrome and Mozilla Firefox.

    "},30:{title:"Invalid instrument",text:"

    Invalid instrument

    This happens when you try to use a sonification instrument that is not valid. If you are using a predefined instrument, make sure your spelling is correct.

    "}, +31:{title:"Non-unique point or node id",text:"

    Non-unique point or node id

    This error occurs when using the same id for two or more points or nodes.

    "},32:{title:"Deprecated function or property",text:'

    Deprecated function or property

    This error occurs when using a deprecated function or property. Consult the API documentation for alternatives, if no replacement is mentioned by the error itself.

    '},meta:{files:"errors/10/readme.md errors/10/enduser.md errors/11/readme.md errors/12/readme.md errors/13/readme.md errors/14/readme.md errors/15/readme.md errors/16/readme.md errors/17/readme.md errors/18/readme.md errors/19/readme.md errors/20/readme.md errors/21/readme.md errors/22/readme.md errors/23/readme.md errors/24/readme.md errors/25/readme.md errors/26/readme.md errors/27/readme.md errors/28/readme.md errors/29/readme.md errors/30/readme.md errors/31/readme.md errors/32/readme.md".split(" ")}}}); +b(a,"Extensions/Debugger.js",[a["Core/Globals.js"],a["Core/Utilities.js"]],function(a,b){var c=b.addEvent,f=b.isNumber;b=b.setOptions;b({chart:{displayErrors:!0}});c(a.Chart,"displayError",function(b){var d=b.code,e=this.options.chart;b=this.renderer;this.errorElements&&this.errorElements.forEach(function(a){a&&a.destroy()});if(e&&e.displayErrors&&b){this.errorElements=[];d=f(d)?"Highcharts error #"+d+": "+a.errorMessages[d].text:d;e=this.chartWidth;var c=this.chartHeight;d=d.replace(/

    (.*)<\/h1>/g, +'
    $1
    ').replace(/<\/p>/g,"


    ");this.errorElements[0]=b.rect(2,2,e-4,c-4).attr({"stroke-width":4,stroke:"#ff0000",zIndex:3}).add();this.errorElements[1]=b.label(d,0,0,"rect",void 0,void 0,void 0,void 0,"debugger").css({color:"#ffffff",width:e-16+"px",padding:0}).attr({fill:"rgba(255, 0, 0, 0.9)",width:e,padding:8,zIndex:10}).add();this.errorElements[1].attr({y:c-this.errorElements[1].getBBox().height})}});c(a.Chart,"beforeRedraw",function(){var a=this.errorElements; +a&&a.length&&a.forEach(function(a){a.destroy()});this.errorElements=null})});b(a,"masters/modules/debugger.src.js",[],function(){})}); +//# sourceMappingURL=debugger.js.map \ No newline at end of file diff --git a/highcharts/modules/debugger.js.map b/highcharts/modules/debugger.js.map new file mode 100644 index 0000000..831e300 --- /dev/null +++ b/highcharts/modules/debugger.js.map @@ -0,0 +1 @@ +{"version":3,"file":"debugger.js.map","lineCount":29,"mappings":"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","sources":["debugger.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","errorMessages","U","addEvent","isNumber","setOptions","chart","displayErrors","Chart","e","code","options","renderer","errorElements","forEach","el","destroy","msg","text","chartWidth","chartHeight","replace","rect","attr","stroke","zIndex","add","label","css","color","width","padding","fill","y","getBBox","height","length"]} \ No newline at end of file diff --git a/highcharts/modules/debugger.src.js b/highcharts/modules/debugger.src.js new file mode 100644 index 0000000..50f54e3 --- /dev/null +++ b/highcharts/modules/debugger.src.js @@ -0,0 +1,268 @@ +/** + * @license Highcharts JS v8.2.0 (2020-08-20) + * + * Debugger module + * + * (c) 2012-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/debugger', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'error-messages.js', [_modules['Core/Globals.js']], function (H) { + /* eslint-disable */ + /* * + * Error information for the debugger module + * (c) 2010-2019 Torstein Honsi + * License: www.highcharts.com/license + */ + + // DO NOT EDIT! + // Automatically generated by ./tools/error-messages.js + // Sources can be found in ./errors/*/*.md + + + + H.errorMessages = { + "10": { + "title": "Can't plot zero or subzero values on a logarithmic axis", + "text": "

    Can't plot zero or subzero values on a logarithmic axis

    This error occurs in the following situations:

    • If a zero or subzero data value is added to a logarithmic axis
    • If the minimum of a logarithimic axis is set to 0 or less
    • If the threshold is set to 0 or less

    Note: As of Highcharts 5.0.8 it's possible to bypass this error message by setting Axis.prototype.allowNegativeLog to true, and add custom conversion functions. View live demo. It is also possible to use a similar workaround for colorAxis. View live demo.

    ", + "enduser": "

    Can't plot zero or subzero values on a logarithmic axis

    This error occurs in the following situations:

    • If a zero or subzero data value is added to a logarithmic axis
    • If the minimum of a logarithimic axis is set to 0 or less
    • If the threshold is set to 0 or less

    As of Highcharts 5.0.8 it's possible to bypass this error message by setting Axis.prototype.allowNegativeLog to true and add custom conversion functions. \">View Live Demo. It is also possible to use a similar workaround for colorAxis. View live demo.

    " + }, + "11": { + "title": "Can't link axes of different type", + "text": "

    Can't link axes of different type

    This error occurs when using the linkedTo option to link two axes of different types, for example a logarithmic axis to a linear axis. Highcharts can't link these because the calculation of ticks, extremes, padding etc. is different.

    " + }, + "12": { + "title": "Highcharts expects point configuration to be numbers or arrays in turbo mode", + "text": "

    Highcharts expects point configuration to be numbers or arrays in turbo mode

    This error occurs if the series.data option contains object configurations and the number of points exceeds the turboThreshold. It can be fixed by either setting turboThreshold to a higher value, or changing the point configurations to numbers or arrays.

    In boost mode, turbo mode is always on, which means only array of numbers or two dimensional arrays are allowed.

    See plotOptions.series.turboThreshold

    " + }, + "13": { + "title": "Rendering div not found", + "text": "

    Rendering div not found

    This error occurs if the chart.renderTo option is misconfigured so that Highcharts is unable to find the HTML element to render the chart in.

    If using a DOM ID when creating the chart, make sure a node with the same ID exists somewhere in the DOM.

    " + }, + "14": { + "title": "String value sent to series.data, expected Number", + "text": "

    String value sent to series.data, expected Number

    This happens if using a string as a data point, for example in a setup like this:

    series: [{\n    data: ["3", "5", "1", "6"]\n}]

    Highcharts expects numerical data values.

    The most common reason for this error this is that data is parsed from CSV or from a XML source, and the implementer forgot to run parseFloat on the parsed value.

    Note: For performance reasons internal type casting is not performed, and only the first value is checked (since 2.3).

    " + }, + "15": { + "title": "Highcharts expects data to be sorted", + "text": "

    Highcharts expects data to be sorted

    This happens when creating a line series or a stock chart where the data is not sorted in ascending X order.

    For performance reasons, Highcharts does not sort the data, instead it requires that the implementer pre-sorts the data.

    " + }, + "16": { + "title": "Highcharts already defined in the page", + "text": "

    Highcharts already defined in the page

    This error happens if the Highcharts namespace already exists when loading Highcharts or Highstock.

    This is caused by including Highcharts or Highstock more than once.

    Keep in mind that the Highcharts.Chart constructor and all features of Highcharts are included in Highstock, so if using the Chart and StockChart constructors in combination, only the highstock.js file is required.

    " + }, + "17": { + "title": "The requested series type does not exist", + "text": "

    The requested series type does not exist

    This error happens when setting chart.type or series.type to a series type that isn't defined in Highcharts. A typical reason may be that the module or extension where the series type is defined isn't included.

    For example in order to create an arearange series, the highcharts-more.js file must be loaded.

    " + }, + "18": { + "title": "The requested axis does not exist", + "text": "

    The requested axis does not exist

    This error happens when setting a series' xAxis or yAxis property to point to an axis that does not exist.

    " + }, + "19": { + "title": "Too many ticks", + "text": "

    Too many ticks

    This error happens when applying too many ticks to an axis, specifically when adding more ticks than the axis pixel length.

    With default value this won't happen, but there are edge cases, for example when setting axis categories and xAxis.labels.step in combination with a long data range, when the axis is instructed to create a great number of ticks.

    " + }, + "20": { + "title": "Can't add object point configuration to a long data series", + "text": "

    Can't add object point configuration to a long data series

    In Highstock, when trying to add a point using the object literal configuration syntax, it will only work when the number of data points is below the series' turboThreshold. Instead of the object syntax, use the Array syntax.

    " + }, + "21": { + "title": "Can't find Proj4js library", + "text": "

    Can't find Proj4js library

    Using latitude/longitude functionality in Highmaps requires the Proj4js library to be loaded.

    " + }, + "22": { + "title": "Map does not support latitude/longitude", + "text": "

    Map does not support latitude/longitude

    The loaded map does not support latitude/longitude functionality. This is only supported with maps from the official Highmaps map collection from version 1.1.0 onwards. If you are using a custom map, consider using the Proj4js library to convert between projections.

    " + }, + "23": { + "title": "Unsupported color format used for color interpolation", + "text": "

    Unsupported color format used for color interpolation

    Highcharts supports three color formats primarily: hex (#FFFFFF), rgb (rgba(255,255,255)) and rgba (rgba(255,255,255,1)). If any other format, like 3-digit colors (#FFF), named colors (white) or gradient structures are used in for example a heatmap, Highcharts will fail to interpolate and will instead use the end-color with no interpolation applied.

    We've chosen to preserve this limitation in order to keep the weight of the implementation at a minimum.

    " + }, + "24": { + "title": "Cannot run Point.update on a grouped point", + "text": "

    Cannot run Point.update on a grouped point

    Running Point.update in Highstock when a point is grouped by data grouping is not supported.

    This is not supported because when data grouping is enabled, there won't be any references to the raw points, which is required by the Point.update function.

    " + }, + "25": { + "title": "Can't find Moment.js library", + "text": "

    Can't find Moment.js library

    Using the global.timezone option requires the Moment.js library to be loaded.

    " + }, + "26": { + "title": "WebGL not supported, and no fallback module included", + "text": "

    WebGL not supported, and no fallback module included

    This happens when the browser doesn't support WebGL,and the canvas fallback module (boost-canvas.js) hasn't been included OR if the fallback module was includedafter the boost module.

    If a fallback is required, make sure to include boost-canvas.js, and that it's included before boost.js.

    Please note that the fallback module is not intended as a fully-featured one. Rather, it's a minimal implementation of the WebGL counterpart.

    " + }, + "27": { + "title": "This browser does not support SVG", + "text": "

    This browser does not support SVG

    This happens in old IE when the oldie.js module isn't loaded.

    If compatibility with IE versions 6, 7 and 8 is required, add the module after loading highcharts.js. In a website context, it's a good idea to load it in a conditional comment to avoid traffic overhead and dead code in modern browsers:

    <!--[if lt IE 9]>\n    <script src='https://code.highcharts.com/modules/oldie.js'></script>\n<![endif]-->
    " + }, + "28": { + "title": "Fallback to export server disabled", + "text": "

    Fallback to export server disabled

    This happens when the offline export module encounters a chart that it can't export successfully, and the fallback to the online export server is disabled. The offline exporting module will fail for certain browsers, and certain features (e.g. exporting.allowHTML ), depending on the type of image exporting to. For a compatibility overview, see Client Side Export.

    For very complex charts, it's possible that exporting fail in browsers that don't support Blob objects, due to data URL length limits. It's always recommended to define the exporting.error callback when disabling the fallback, so that details can be provided to the end-user if offline export isn't working for them.

    " + }, + "29": { + "title": "Browser does not support WebAudio", + "text": "

    Browser does not support WebAudio

    This happens when you attempt to use the sonification module on a chart in a browser or environment that does not support the WebAudio API. This API is supported on all modern browsers, including Microsoft Edge, Google Chrome and Mozilla Firefox.

    " + }, + "30": { + "title": "Invalid instrument", + "text": "

    Invalid instrument

    This happens when you try to use a sonification instrument that is not valid. If you are using a predefined instrument, make sure your spelling is correct.

    " + }, + "31": { + "title": "Non-unique point or node id", + "text": "

    Non-unique point or node id

    This error occurs when using the same id for two or more points or nodes.

    " + }, + "32": { + "title": "Deprecated function or property", + "text": "

    Deprecated function or property

    This error occurs when using a deprecated function or property. Consult the API documentation for alternatives, if no replacement is mentioned by the error itself.

    " + }, + "meta": { + "files": [ + "errors/10/readme.md", + "errors/10/enduser.md", + "errors/11/readme.md", + "errors/12/readme.md", + "errors/13/readme.md", + "errors/14/readme.md", + "errors/15/readme.md", + "errors/16/readme.md", + "errors/17/readme.md", + "errors/18/readme.md", + "errors/19/readme.md", + "errors/20/readme.md", + "errors/21/readme.md", + "errors/22/readme.md", + "errors/23/readme.md", + "errors/24/readme.md", + "errors/25/readme.md", + "errors/26/readme.md", + "errors/27/readme.md", + "errors/28/readme.md", + "errors/29/readme.md", + "errors/30/readme.md", + "errors/31/readme.md", + "errors/32/readme.md" + ] + } + }; + + }); + _registerModule(_modules, 'Extensions/Debugger.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + isNumber = U.isNumber, + setOptions = U.setOptions; + setOptions({ + /** + * @optionparent chart + */ + chart: { + /** + * Whether to display errors on the chart. When `false`, the errors will + * be shown only in the console. + * + * @sample highcharts/chart/display-errors/ + * Show errors on chart + * + * @since 7.0.0 + * @requires modules/debugger + */ + displayErrors: true + } + }); + /* eslint-disable no-invalid-this */ + addEvent(H.Chart, 'displayError', function (e) { + var chart = this, + code = e.code, + msg, + options = chart.options.chart, + renderer = chart.renderer, + chartWidth, + chartHeight; + if (chart.errorElements) { + (chart.errorElements).forEach(function (el) { + if (el) { + el.destroy(); + } + }); + } + if (options && options.displayErrors && renderer) { + chart.errorElements = []; + msg = isNumber(code) ? + ('Highcharts error #' + code + ': ' + + H.errorMessages[code].text) : + code; + chartWidth = chart.chartWidth; + chartHeight = chart.chartHeight; + // Format msg so SVGRenderer can handle it + msg = msg + .replace(/

    (.*)<\/h1>/g, '
    $1
    ') + .replace(/<\/p>/g, '


    '); + // Render red chart frame. + chart.errorElements[0] = renderer.rect(2, 2, chartWidth - 4, chartHeight - 4).attr({ + 'stroke-width': 4, + stroke: '#ff0000', + zIndex: 3 + }).add(); + // Render error message + chart.errorElements[1] = renderer.label(msg, 0, 0, 'rect', void 0, void 0, void 0, void 0, 'debugger').css({ + color: '#ffffff', + width: (chartWidth - 16) + 'px', + padding: 0 + }).attr({ + fill: 'rgba(255, 0, 0, 0.9)', + width: chartWidth, + padding: 8, + zIndex: 10 + }).add(); + chart.errorElements[1].attr({ + y: chartHeight - this.errorElements[1].getBBox().height + }); + } + }); + addEvent(H.Chart, 'beforeRedraw', function () { + var errorElements = this.errorElements; + if (errorElements && errorElements.length) { + errorElements.forEach(function (el) { + el.destroy(); + }); + } + this.errorElements = null; + }); + + }); + _registerModule(_modules, 'masters/modules/debugger.src.js', [], function () { + + + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/dependency-wheel.js b/highcharts/modules/dependency-wheel.js new file mode 100644 index 0000000..2c13d6e --- /dev/null +++ b/highcharts/modules/dependency-wheel.js @@ -0,0 +1,17 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Dependency wheel module + + (c) 2010-2018 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/dependency-wheel",["highcharts","highcharts/modules/sankey"],function(d){a(d);a.Highcharts=d;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function d(a,f,d,m){a.hasOwnProperty(f)||(a[f]=m.apply(null,d))}a=a?a._modules:{};d(a,"Series/DependencyWheelSeries.js",[a["Core/Globals.js"],a["Core/Utilities.js"],a["Mixins/Nodes.js"]], +function(a,d,q){var m=d.animObject;d=d.seriesType;var f=a.seriesTypes.sankey.prototype;d("dependencywheel","sankey",{center:[null,null],curveFactor:.6,startAngle:0},{orderNodes:!1,getCenter:a.seriesTypes.pie.prototype.getCenter,createNodeColumns:function(){var a=[this.createNodeColumn()];this.nodes.forEach(function(c){c.column=0;a[0].push(c)});return a},getNodePadding:function(){return this.options.nodePadding/Math.PI},createNode:function(a){var c=f.createNode.call(this,a);c.index=this.nodes.length- +1;c.getSum=function(){return c.linksFrom.concat(c.linksTo).reduce(function(a,c){return a+c.weight},0)};c.offset=function(a){function h(a){return a.fromNode===c?a.toNode:a.fromNode}var p=0,b,g=c.linksFrom.concat(c.linksTo);g.sort(function(a,c){return h(a).index-h(c).index});for(b=0;bc.index){g=g.slice(0,b).reverse().concat(g.slice(b).reverse());var n=!0;break}n||g.reverse();for(b=0;bMath.PI&&(b=2*Math.PI-b);b*=k;bthis.angle||this.angle>Math.PI,f=d.start,b=d.end;this.dataLabelPath||(this.dataLabelPath=c.arc({open:!0}).add(a)); +this.dataLabelPath.attr({x:d.x,y:d.y,r:d.r+(this.dataLabel.options.distance||0),start:h?f:b,end:h?b:f,clockwise:+h});return this.dataLabelPath},isValid:function(){return!0}});""});d(a,"masters/modules/dependency-wheel.src.js",[],function(){})}); +//# sourceMappingURL=dependency-wheel.js.map \ No newline at end of file diff --git a/highcharts/modules/dependency-wheel.js.map b/highcharts/modules/dependency-wheel.js.map new file mode 100644 index 0000000..77e57f5 --- /dev/null +++ b/highcharts/modules/dependency-wheel.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dependency-wheel.js.map","lineCount":16,"mappings":"A;;;;;;;;;AAUC,SAAS,CAACA,CAAD,CAAU,CACM,QAAtB,GAAI,MAAOC,OAAX,EAAkCA,MAAAC,QAAlC,EACIF,CAAA,CAAQ,SAAR,CACA,CADqBA,CACrB,CAAAC,MAAAC,QAAA,CAAiBF,CAFrB,EAG6B,UAAtB,GAAI,MAAOG,OAAX,EAAoCA,MAAAC,IAApC,CACHD,MAAA,CAAO,qCAAP,CAA8C,CAAC,YAAD,CAAe,2BAAf,CAA9C,CAA2F,QAAS,CAACE,CAAD,CAAa,CAC7GL,CAAA,CAAQK,CAAR,CACAL,EAAAK,WAAA,CAAqBA,CACrB,OAAOL,EAHsG,CAAjH,CADG,CAOHA,CAAA,CAA8B,WAAtB,GAAA,MAAOK,WAAP,CAAoCA,UAApC,CAAiDC,IAAAA,EAAzD,CAXY,CAAnB,CAAA,CAaC,QAAS,CAACD,CAAD,CAAa,CAEpBE,QAASA,EAAe,CAACC,CAAD,CAAMC,CAAN,CAAYC,CAAZ,CAAkBC,CAAlB,CAAsB,CACrCH,CAAAI,eAAA,CAAmBH,CAAnB,CAAL,GACID,CAAA,CAAIC,CAAJ,CADJ,CACgBE,CAAAE,MAAA,CAAS,IAAT,CAAeH,CAAf,CADhB,CAD0C,CAD1CI,CAAAA,CAAWT,CAAA,CAAaA,CAAAS,SAAb,CAAmC,EAMlDP,EAAA,CAAgBO,CAAhB,CAA0B,iCAA1B,CAA6D,CAACA,CAAA,CAAS,iBAAT,CAAD,CAA8BA,CAAA,CAAS,mBAAT,CAA9B,CAA6DA,CAAA,CAAS,iBAAT,CAA7D,CAA7D;AAAwJ,QAAS,CAACC,CAAD,CAAIC,CAAJ,CAAOC,CAAP,CAAmB,CAAA,IAY5KC,EAAaF,CAAAE,WACbC,EAAAA,CAAaH,CAAAG,WACjB,KAAIC,EAAOL,CAAAM,YAAAC,OAAAC,UAQXJ,EAAA,CAAW,iBAAX,CAA8B,QAA9B,CAeA,CAUIK,OAAQ,CAAC,IAAD,CAAO,IAAP,CAVZ,CAWIC,YAAa,EAXjB,CAeIC,WAAY,CAfhB,CAfA,CA+BG,CACCC,WAAY,CAAA,CADb,CAECC,UAAWb,CAAAM,YAAAQ,IAAAN,UAAAK,UAFZ,CAQCE,kBAAmBA,QAAS,EAAG,CAC3B,IAAIC,EAAU,CAAC,IAAAC,iBAAA,EAAD,CACd,KAAAC,MAAAC,QAAA,CAAmB,QAAS,CAACC,CAAD,CAAO,CAC/BA,CAAAC,OAAA,CAAc,CACdL,EAAA,CAAQ,CAAR,CAAAM,KAAA,CAAgBF,CAAhB,CAF+B,CAAnC,CAIA,OAAOJ,EANoB,CARhC,CAoBCO,eAAgBA,QAAS,EAAG,CACxB,MAAO,KAAAC,QAAAC,YAAP,CAAkCC,IAAAC,GADV,CApB7B,CAuBCC,WAAYA,QAAS,CAACC,CAAD,CAAK,CACtB,IAAIT,EAAOf,CAAAuB,WAAAE,KAAA,CAAqB,IAArB,CACPD,CADO,CAEXT,EAAAW,MAAA,CAAa,IAAAb,MAAAc,OAAb;AAAiC,CAKjCZ,EAAAa,OAAA,CAAcC,QAAS,EAAG,CACtB,MAAOd,EAAAe,UAAAC,OAAA,CACKhB,CAAAiB,QADL,CAAAC,OAAA,CAEK,QAAS,CAACC,CAAD,CAAMC,CAAN,CAAY,CAC7B,MAAOD,EAAP,CAAaC,CAAAC,OADgB,CAF1B,CAIJ,CAJI,CADe,CAW1BrB,EAAAsB,OAAA,CAAcC,QAAS,CAACC,CAAD,CAAQ,CAQ3BC,QAASA,EAAS,CAACL,CAAD,CAAO,CACrB,MAAIA,EAAAM,SAAJ,GAAsB1B,CAAtB,CACWoB,CAAAO,OADX,CAGOP,CAAAM,SAJc,CARE,IACvBJ,EAAS,CADc,CAEvBM,CAFuB,CAGvBC,EAAQ7B,CAAAe,UAAAC,OAAA,CAAsBhB,CAAAiB,QAAtB,CAaZY,EAAAC,KAAA,CAAW,QAAS,CAACC,CAAD,CAAIC,CAAJ,CAAO,CACvB,MAAOP,EAAA,CAAUM,CAAV,CAAApB,MAAP,CAA4Bc,CAAA,CAAUO,CAAV,CAAArB,MADL,CAA3B,CAGA,KAAKiB,CAAL,CAAS,CAAT,CAAYA,CAAZ,CAAgBC,CAAAjB,OAAhB,CAA8BgB,CAAA,EAA9B,CACI,GAAIH,CAAA,CAAUI,CAAA,CAAMD,CAAN,CAAV,CAAAjB,MAAJ,CAAgCX,CAAAW,MAAhC,CAA4C,CACxCkB,CAAA,CAAQA,CAAAI,MAAA,CAAY,CAAZ,CAAeL,CAAf,CAAAM,QAAA,EAAAlB,OAAA,CAAmCa,CAAAI,MAAA,CAAYL,CAAZ,CAAAM,QAAA,EAAnC,CACR,KAAAC,EAAS,CAAA,CACT,MAHwC,CAM3CA,CAAL,EACIN,CAAAK,QAAA,EAEJ,KAAKN,CAAL,CAAS,CAAT,CAAYA,CAAZ,CAAgBC,CAAAjB,OAAhB,CAA8BgB,CAAA,EAA9B,CAAmC,CAC/B,GAAIC,CAAA,CAAMD,CAAN,CAAJ,GAAiBJ,CAAjB,CACI,MAAOF,EAEXA,EAAA,EAAUO,CAAA,CAAMD,CAAN,CAAAP,OAJqB,CA7BR,CAoC/B,OAAOrB,EAvDe,CAvB3B,CAqFCoC,UAAWA,QAAS,EAAG,CAAA,IACfhC;AAAU,IAAAA,QADK,CAEfiC,EAAS,CAATA,CAAa/B,IAAAC,GAAb8B,EACK,IAAAC,MAAAC,WADLF,CAC6B,IAAAlC,eAAA,EAD7BkC,CAFe,CAIfhD,EAAS,IAAAI,UAAA,EAJM,CAKfF,GAAca,CAAAb,WAAdA,CAAmC,EAAnCA,EAAyCX,CAAA4D,QAC7CvD,EAAAmD,UAAA1B,KAAA,CAAoB,IAApB,CACA,KAAA+B,YAAA,CAAiB,CAAjB,CAAA1C,QAAA,CAA4B,QAAS,CAACC,CAAD,CAAO,CAExC,GAAIA,CAAA0C,IAAJ,CAAc,CAAA,IACNC,EAAY3C,CAAA2C,UADN,CAENC,EAAUvD,CAAA,CAAO,CAAP,CAFJ,CAGNwD,EAAUxD,CAAA,CAAO,CAAP,CAHJ,CAINyD,EAAIzD,CAAA,CAAO,CAAP,CAAJyD,CAAgB,CAJV,CAKNC,EAASD,CAATC,CAAa3C,CAAA4C,UALP,CAMNC,EAAQ1D,CAAR0D,CAAqBZ,CAArBY,CAA8BN,CAAAO,EAC9BC,EAAAA,CAAM5D,CAAN4D,CACId,CADJc,EACcR,CAAAO,EADdC,CAC4BR,CAAAS,OAD5BD,CAGJnD,EAAAqD,MAAA,CAAaJ,CAAb,EAAsBE,CAAtB,CAA4BF,CAA5B,EAAqC,CACrCjD,EAAAsD,UAAA,CAAiB,KACjBtD,EAAA2C,UAAA,CAAiB,CACbY,EAAGX,CADU,CAEbM,EAAGL,CAFU,CAGbC,EAAGA,CAHU,CAIbC,OAAQA,CAJK,CAKbE,MAAOA,CALM,CAMbE,IAAKA,CANQ,CAQjBnD,EAAAwD,MAAA,CAAa,CACTD,EAAGX,CAAHW,CAAajD,IAAAmD,IAAA,EAAUR,CAAV,CAAkBE,CAAlB,EAAyB,CAAzB,CAAbI,EAA4CT,CAA5CS,CAAgDR,CAAhDQ,EAA0D,CADjD,CAETL,EAAGL,CAAHK,CAAa5C,IAAAoD,IAAA,EAAUT,CAAV,CAAkBE,CAAlB,EAAyB,CAAzB,CAAbD,EAA4CJ,CAA5CI,CAAgDH,CAAhDG,EAA0D,CAFjD,CAGTS,MAAO,CAHE,CAITP,OAAQ,CAJC,CAObpD,EAAAe,UAAAhB,QAAA,CAAuB,QAAS,CAACyB,CAAD,CAAQ,CACpC,GAAIA,CAAAoC,SAAJ,CAAoB,CAChB,IAAIC,CAAJ;AACIC,EAAUtC,CAAAoC,SAAAG,IAAA,CAAmB,QAAS,CAACC,CAAD,CACtCpC,CADsC,CACnC,CACKyB,CAAAA,EAAQhB,CADb,KAEHkB,EAAIjD,IAAAmD,IAAA,CAASlE,CAAT,CAAsB8D,CAAtB,CAAJE,EAAoCR,CAApCQ,CAA6C,CAA7CA,CAFG,CAGHL,EAAI5C,IAAAoD,IAAA,CAASnE,CAAT,CAAsB8D,CAAtB,CAAJH,EAAoCH,CAApCG,CAA6C,CAA7CA,CAHG,CAIH5D,EAAcc,CAAAd,YAKduE,EAAA,CAAWvD,IAAA2D,IAAA,CAASzC,CAAAoC,SAAA,CAAe,CAAf,CAAmBhC,CAAnB,CAAT,CAAiCS,CAAjC,CAA0CgB,CAA1C,CACPQ,EAAJ,CAAevD,IAAAC,GAAf,GACIsD,CADJ,CACe,CADf,CACmBvD,IAAAC,GADnB,CAC6BsD,CAD7B,CAGWA,EAAX,EAAsBd,CAClBc,EAAJ,CAAed,CAAf,GACIzD,CADJ,EACoBuE,CADpB,CAC+Bd,CAD/B,CAGA,OAAO,CACHQ,EAAGX,CAAHW,CAAaA,CADV,CAEHL,EAAGL,CAAHK,CAAaA,CAFV,CAGHgB,IAAKtB,CAALsB,EAAgB,CAAhBA,CAAoB5E,CAApB4E,EAAmCX,CAHhC,CAIHY,IAAKtB,CAALsB,EAAgB,CAAhBA,CAAoB7E,CAApB6E,EAAmCjB,CAJhC,CAjBJ,CADO,CAyBd1B,EAAAmB,UAAA,CAAkB,CACdyB,EAAG,CAAC,CACI,GADJ,CAEIN,CAAA,CAAQ,CAAR,CAAAP,EAFJ,CAEkBO,CAAA,CAAQ,CAAR,CAAAZ,EAFlB,CAAD,CAGI,CACC,GADD,CAECH,CAFD,CAESA,CAFT,CAGC,CAHD,CAIC,CAJD,CAKC,CALD,CAMCe,CAAA,CAAQ,CAAR,CAAAP,EAND,CAMeO,CAAA,CAAQ,CAAR,CAAAZ,EANf,CAHJ,CAUI,CACC,GADD,CAECY,CAAA,CAAQ,CAAR,CAAAI,IAFD,CAEiBJ,CAAA,CAAQ,CAAR,CAAAK,IAFjB,CAGCL,CAAA,CAAQ,CAAR,CAAAI,IAHD,CAGiBJ,CAAA,CAAQ,CAAR,CAAAK,IAHjB,CAICL,CAAA,CAAQ,CAAR,CAAAP,EAJD,CAIeO,CAAA,CAAQ,CAAR,CAAAZ,EAJf,CAVJ,CAeI,CACC,GADD,CAECH,CAFD,CAESA,CAFT,CAGC,CAHD,CAIC,CAJD,CAKC,CALD,CAMCe,CAAA,CAAQ,CAAR,CAAAP,EAND,CAMeO,CAAA,CAAQ,CAAR,CAAAZ,EANf,CAfJ,CAsBI,CACC,GADD,CAECY,CAAA,CAAQ,CAAR,CAAAI,IAFD,CAEiBJ,CAAA,CAAQ,CAAR,CAAAK,IAFjB,CAGCL,CAAA,CAAQ,CAAR,CAAAI,IAHD,CAGiBJ,CAAA,CAAQ,CAAR,CAAAK,IAHjB,CAICL,CAAA,CAAQ,CAAR,CAAAP,EAJD,CAIeO,CAAA,CAAQ,CAAR,CAAAZ,EAJf,CAtBJ,CADW,CA3BF,CADgB,CAAxC,CA3BU,CAF0B,CAA5C,CAPmB,CArFxB,CAwLCmB,QAASA,QAAS,CAACC,CAAD,CAAO,CACrB,GAAI,CAACA,CAAL,CAAW,CACP,IACIC,EADWxF,CAAA,CAAW,IAAAqB,QAAAoE,UAAX,CAAAC,SACXF;AAAmB,CAAnBA,CAAwB,IAAAzE,MAAAc,OAC5B,KAAAd,MAAAC,QAAA,CAAmB,QAAS,CAACyB,CAAD,CAAQI,CAAR,CAAW,CACnC,IAAI8C,EAAUlD,CAAAkD,QACVA,EAAJ,GACIA,CAAAC,KAAA,CAAa,CAAEC,QAAS,CAAX,CAAb,CACA,CAAAC,UAAA,CAAW,QAAS,EAAG,CACnBH,CAAAL,QAAA,CAAgB,CAAEO,QAAS,CAAX,CAAhB,CAAgC,CAAEH,SAAUF,CAAZ,CAAhC,CADmB,CAAvB,CAEGA,CAFH,CAEU3C,CAFV,CAFJ,CAFmC,CAAvC,CAQG,IARH,CASA,KAAAkD,OAAA/E,QAAA,CAAoB,QAAS,CAACyB,CAAD,CAAQ,CACjC,IAAIkD,EAAUlD,CAAAkD,QACV,EAAClD,CAAAuD,OAAL,EAAqBL,CAArB,EACIA,CAAAC,KAAA,CAAa,CAAEC,QAAS,CAAX,CAAb,CAAAP,QAAA,CACa,CACTO,QAAS,CADA,CADb,CAGG,IAAAxE,QAAAoE,UAHH,CAH6B,CAArC,CAQG,IARH,CAZO,CADU,CAxL1B,CA/BH,CAkPA,CACIQ,SAAUlG,CAAAmG,aADd,CAOIC,iBAAkBA,QAAS,CAACC,CAAD,CAAQ,CAAA,IAC3BC,EAAW,IAAAC,OAAA/C,MAAA8C,SADgB,CAE3BzC,EAAY,IAAAA,UAFe,CAG3B2C,EAAyB,CAAzBA,CAAY,IAAAjC,MAAZiC,EAA8B,IAAAjC,MAA9BiC,CAA2ChF,IAAAC,GAHhB,CAI3B0C,EAAQN,CAAAM,MAJmB,CAK3BE,EAAMR,CAAAQ,IACL,KAAAoC,cAAL,GACI,IAAAA,cADJ,CACyBH,CAAAI,IAAA,CACZ,CAAEC,KAAM,CAAA,CAAR,CADY,CAAAC,IAAA,CAIZP,CAJY,CADzB,CAOA;IAAAI,cAAAZ,KAAA,CAAwB,CACpBpB,EAAGZ,CAAAY,EADiB,CAEpBL,EAAGP,CAAAO,EAFiB,CAGpBJ,EAAIH,CAAAG,EAAJA,EACK,IAAA6C,UAAAvF,QAAAyD,SADLf,EACwC,CADxCA,CAHoB,CAKpBG,MAAQqC,CAAA,CAAYrC,CAAZ,CAAoBE,CALR,CAMpBA,IAAMmC,CAAA,CAAYnC,CAAZ,CAAkBF,CANJ,CAOpB2C,UAAW,CAACN,CAPQ,CAAxB,CASA,OAAO,KAAAC,cAtBwB,CAPvC,CA+BIM,QAASA,QAAS,EAAG,CAEjB,MAAO,CAAA,CAFU,CA/BzB,CAlPA,CA6UA,GAnWgL,CAApL,CAsWAzH,EAAA,CAAgBO,CAAhB,CAA0B,yCAA1B,CAAqE,EAArE,CAAyE,QAAS,EAAG,EAArF,CA7WoB,CAbvB;","sources":["dependency-wheel.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","NodesMixin","animObject","seriesType","base","seriesTypes","sankey","prototype","center","curveFactor","startAngle","orderNodes","getCenter","pie","createNodeColumns","columns","createNodeColumn","nodes","forEach","node","column","push","getNodePadding","options","nodePadding","Math","PI","createNode","id","call","index","length","getSum","node.getSum","linksFrom","concat","linksTo","reduce","acc","link","weight","offset","node.offset","point","otherNode","fromNode","toNode","i","links","sort","a","b","slice","reverse","sliced","translate","factor","chart","plotHeight","deg2rad","nodeColumns","sum","shapeArgs","centerX","centerY","r","innerR","nodeWidth","start","y","end","height","angle","shapeType","x","dlBox","cos","sin","width","linkBase","distance","corners","map","top","abs","cpX","cpY","d","animate","init","step","animation","duration","graphic","attr","opacity","setTimeout","points","isNode","setState","setNodeState","getDataLabelPath","label","renderer","series","upperHalf","dataLabelPath","arc","open","add","dataLabel","clockwise","isValid"]} \ No newline at end of file diff --git a/highcharts/modules/dependency-wheel.src.js b/highcharts/modules/dependency-wheel.src.js new file mode 100644 index 0000000..316ffbd --- /dev/null +++ b/highcharts/modules/dependency-wheel.src.js @@ -0,0 +1,393 @@ +/** + * @license Highcharts JS v8.2.0 (2020-08-20) + * + * Dependency wheel module + * + * (c) 2010-2018 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/dependency-wheel', ['highcharts', 'highcharts/modules/sankey'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'Series/DependencyWheelSeries.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js'], _modules['Mixins/Nodes.js']], function (H, U, NodesMixin) { + /* * + * + * Dependency wheel module + * + * (c) 2018-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var animObject = U.animObject, + seriesType = U.seriesType; + var base = H.seriesTypes.sankey.prototype; + /** + * @private + * @class + * @name Highcharts.seriesTypes.dependencywheel + * + * @augments Highcharts.seriesTypes.sankey + */ + seriesType('dependencywheel', 'sankey', + /** + * A dependency wheel chart is a type of flow diagram, where all nodes are + * laid out in a circle, and the flow between the are drawn as link bands. + * + * @sample highcharts/demo/dependency-wheel/ + * Dependency wheel + * + * @extends plotOptions.sankey + * @exclude dataSorting + * @since 7.1.0 + * @product highcharts + * @requires modules/dependencywheel + * @optionparent plotOptions.dependencywheel + */ + { + /** + * The center of the wheel relative to the plot area. Can be + * percentages or pixel values. The default behaviour is to + * center the wheel inside the plot area. + * + * @type {Array} + * @default [null, null] + * @product highcharts + */ + center: [null, null], + curveFactor: 0.6, + /** + * The start angle of the dependency wheel, in degrees where 0 is up. + */ + startAngle: 0 + }, { + orderNodes: false, + getCenter: H.seriesTypes.pie.prototype.getCenter, + /* eslint-disable valid-jsdoc */ + /** + * Dependency wheel has only one column, it runs along the perimeter. + * @private + */ + createNodeColumns: function () { + var columns = [this.createNodeColumn()]; + this.nodes.forEach(function (node) { + node.column = 0; + columns[0].push(node); + }); + return columns; + }, + /** + * Translate from vertical pixels to perimeter. + * @private + */ + getNodePadding: function () { + return this.options.nodePadding / Math.PI; + }, + createNode: function (id) { + var node = base.createNode.call(this, + id); + node.index = this.nodes.length - 1; + /** + * Return the sum of incoming and outgoing links. + * @private + */ + node.getSum = function () { + return node.linksFrom + .concat(node.linksTo) + .reduce(function (acc, link) { + return acc + link.weight; + }, 0); + }; + /** + * Get the offset in weight values of a point/link. + * @private + */ + node.offset = function (point) { + var offset = 0, + i, + links = node.linksFrom.concat(node.linksTo), + sliced; + /** + * @private + */ + function otherNode(link) { + if (link.fromNode === node) { + return link.toNode; + } + return link.fromNode; + } + // Sort and slice the links to avoid links going out of each + // node crossing each other. + links.sort(function (a, b) { + return otherNode(a).index - otherNode(b).index; + }); + for (i = 0; i < links.length; i++) { + if (otherNode(links[i]).index > node.index) { + links = links.slice(0, i).reverse().concat(links.slice(i).reverse()); + sliced = true; + break; + } + } + if (!sliced) { + links.reverse(); + } + for (i = 0; i < links.length; i++) { + if (links[i] === point) { + return offset; + } + offset += links[i].weight; + } + }; + return node; + }, + /** + * @private + * @todo Override the refactored sankey translateLink and translateNode + * functions instead of the whole translate function. + */ + translate: function () { + var options = this.options, + factor = 2 * Math.PI / + (this.chart.plotHeight + this.getNodePadding()), + center = this.getCenter(), + startAngle = (options.startAngle - 90) * H.deg2rad; + base.translate.call(this); + this.nodeColumns[0].forEach(function (node) { + // Don't render the nodes if sum is 0 #12453 + if (node.sum) { + var shapeArgs = node.shapeArgs, + centerX = center[0], + centerY = center[1], + r = center[2] / 2, + innerR = r - options.nodeWidth, + start = startAngle + factor * shapeArgs.y, + end = startAngle + + factor * (shapeArgs.y + shapeArgs.height); + // Middle angle + node.angle = start + (end - start) / 2; + node.shapeType = 'arc'; + node.shapeArgs = { + x: centerX, + y: centerY, + r: r, + innerR: innerR, + start: start, + end: end + }; + node.dlBox = { + x: centerX + Math.cos((start + end) / 2) * (r + innerR) / 2, + y: centerY + Math.sin((start + end) / 2) * (r + innerR) / 2, + width: 1, + height: 1 + }; + // Draw the links from this node + node.linksFrom.forEach(function (point) { + if (point.linkBase) { + var distance; + var corners = point.linkBase.map(function (top, + i) { + var angle = factor * top, + x = Math.cos(startAngle + angle) * (innerR + 1), + y = Math.sin(startAngle + angle) * (innerR + 1), + curveFactor = options.curveFactor; + // The distance between the from and to node + // along the perimeter. This affect how curved + // the link is, so that links between neighbours + // don't extend too far towards the center. + distance = Math.abs(point.linkBase[3 - i] * factor - angle); + if (distance > Math.PI) { + distance = 2 * Math.PI - distance; + } + distance = distance * innerR; + if (distance < innerR) { + curveFactor *= (distance / innerR); + } + return { + x: centerX + x, + y: centerY + y, + cpX: centerX + (1 - curveFactor) * x, + cpY: centerY + (1 - curveFactor) * y + }; + }); + point.shapeArgs = { + d: [[ + 'M', + corners[0].x, corners[0].y + ], [ + 'A', + innerR, innerR, + 0, + 0, + 1, + corners[1].x, corners[1].y + ], [ + 'C', + corners[1].cpX, corners[1].cpY, + corners[2].cpX, corners[2].cpY, + corners[2].x, corners[2].y + ], [ + 'A', + innerR, innerR, + 0, + 0, + 1, + corners[3].x, corners[3].y + ], [ + 'C', + corners[3].cpX, corners[3].cpY, + corners[0].cpX, corners[0].cpY, + corners[0].x, corners[0].y + ]] + }; + } + }); + } + }); + }, + animate: function (init) { + if (!init) { + var duration = animObject(this.options.animation).duration, + step = (duration / 2) / this.nodes.length; + this.nodes.forEach(function (point, i) { + var graphic = point.graphic; + if (graphic) { + graphic.attr({ opacity: 0 }); + setTimeout(function () { + graphic.animate({ opacity: 1 }, { duration: step }); + }, step * i); + } + }, this); + this.points.forEach(function (point) { + var graphic = point.graphic; + if (!point.isNode && graphic) { + graphic.attr({ opacity: 0 }) + .animate({ + opacity: 1 + }, this.options.animation); + } + }, this); + } + } + /* eslint-enable valid-jsdoc */ + }, + // Point class + { + setState: NodesMixin.setNodeState, + /* eslint-disable valid-jsdoc */ + /** + * Return a text path that the data label uses. + * @private + */ + getDataLabelPath: function (label) { + var renderer = this.series.chart.renderer, + shapeArgs = this.shapeArgs, + upperHalf = this.angle < 0 || this.angle > Math.PI, + start = shapeArgs.start, + end = shapeArgs.end; + if (!this.dataLabelPath) { + this.dataLabelPath = renderer + .arc({ open: true }) + // Add it inside the data label group so it gets destroyed + // with the label + .add(label); + } + this.dataLabelPath.attr({ + x: shapeArgs.x, + y: shapeArgs.y, + r: (shapeArgs.r + + (this.dataLabel.options.distance || 0)), + start: (upperHalf ? start : end), + end: (upperHalf ? end : start), + clockwise: +upperHalf + }); + return this.dataLabelPath; + }, + isValid: function () { + // No null points here + return true; + } + /* eslint-enable valid-jsdoc */ + }); + /** + * A `dependencywheel` series. If the [type](#series.dependencywheel.type) + * option is not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.dependencywheel + * @exclude dataSorting + * @product highcharts + * @requires modules/dependencywheel + * @apioption series.dependencywheel + */ + /** + * A collection of options for the individual nodes. The nodes in a dependency + * diagram are auto-generated instances of `Highcharts.Point`, but options can + * be applied here and linked by the `id`. + * + * @extends series.sankey.nodes + * @type {Array<*>} + * @product highcharts + * @excluding offset + * @apioption series.dependencywheel.nodes + */ + /** + * An array of data points for the series. For the `dependencywheel` series + * type, points can be given in the following way: + * + * An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' [turboThreshold](#series.area.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * from: 'Category1', + * to: 'Category2', + * weight: 2 + * }, { + * from: 'Category1', + * to: 'Category3', + * weight: 5 + * }] + * ``` + * + * @type {Array<*>} + * @extends series.sankey.data + * @product highcharts + * @excluding outgoing, dataLabels + * @apioption series.dependencywheel.data + */ + /** + * Individual data label for each node. The options are the same as + * the ones for [series.dependencywheel.dataLabels](#series.dependencywheel.dataLabels). + * + * @apioption series.dependencywheel.nodes.dataLabels + */ + ''; // adds doclets above to the transpiled file + + }); + _registerModule(_modules, 'masters/modules/dependency-wheel.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/dotplot.js b/highcharts/modules/dotplot.js new file mode 100644 index 0000000..d1b487e --- /dev/null +++ b/highcharts/modules/dotplot.js @@ -0,0 +1,14 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Dot plot series type for Highcharts + + (c) 2010-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/dotplot",["highcharts"],function(d){a(d);a.Highcharts=d;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function d(a,c,d,p){a.hasOwnProperty(c)||(a[c]=p.apply(null,d))}a=a?a._modules:{};d(a,"Series/DotplotSeries.js",[a["Core/Renderer/SVG/SVGRenderer.js"],a["Core/Utilities.js"]],function(a,c){var d=c.extend,p=c.objectEach, +t=c.pick;c=c.seriesType;c("dotplot","column",{itemPadding:.2,marker:{symbol:"circle",states:{hover:{},select:{}}}},{markerAttribs:void 0,drawPoints:function(){var a=this,c=a.chart.renderer,k=this.options.marker,l=this.yAxis.transA*a.options.itemPadding,m=this.borderWidth%2?.5:1;this.points.forEach(function(b){var e;var f=b.marker||{};var u=f.symbol||k.symbol,x=t(f.radius,k.radius),v="rect"!==u;b.graphics=e=b.graphics||{};var n=b.pointAttr?b.pointAttr[b.selected?"selected":""]||a.pointAttr[""]:a.pointAttribs(b, +b.selected&&"select");delete n.r;a.chart.styledMode&&(delete n.stroke,delete n["stroke-width"]);if(null!==b.y){b.graphic||(b.graphic=c.g("point").add(a.group));var h=b.y;var w=t(b.stackY,b.y);var q=Math.min(b.pointWidth,a.yAxis.transA-l);for(f=w;f>w-b.y;f--){var g=b.barX+(v?b.pointWidth/2-q/2:0);var r=a.yAxis.toPixels(f,!0)+l/2;a.options.crisp&&(g=Math.round(g)-m,r=Math.round(r)+m);g={x:g,y:r,width:Math.round(v?q:b.pointWidth),height:Math.round(q),r:x};e[h]?e[h].animate(g):e[h]=c.symbol(u).attr(d(g, +n)).add(b.graphic);e[h].isActive=!0;h--}}p(e,function(a,b){a.isActive?a.isActive=!1:(a.destroy(),delete a[b])})})}});a.prototype.symbols.rect=function(c,d,k,l,m){return a.prototype.symbols.callout(c,d,k,l,m)}});d(a,"masters/modules/dotplot.src.js",[],function(){})}); +//# sourceMappingURL=dotplot.js.map \ No newline at end of file diff --git a/highcharts/modules/dotplot.js.map b/highcharts/modules/dotplot.js.map new file mode 100644 index 0000000..1c605e3 --- /dev/null +++ b/highcharts/modules/dotplot.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dotplot.js.map","lineCount":13,"mappings":"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","sources":["dotplot.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","SVGRenderer","U","extend","objectEach","pick","seriesType","itemPadding","marker","symbol","states","hover","select","markerAttribs","drawPoints","series","renderer","chart","seriesMarkerOptions","options","itemPaddingTranslated","yAxis","transA","crisp","borderWidth","points","forEach","point","graphics","pointMarkerOptions","radius","isSquare","pointAttr","selected","pointAttribs","r","styledMode","stroke","y","graphic","g","add","group","itemY","yTop","stackY","size","Math","min","pointWidth","yPos","x","barX","toPixels","round","attr","width","height","animate","isActive","key","destroy","prototype","symbols","rect","SVGRenderer.prototype.symbols.rect","w","h","callout"]} \ No newline at end of file diff --git a/highcharts/modules/dotplot.src.js b/highcharts/modules/dotplot.src.js new file mode 100644 index 0000000..042f02e --- /dev/null +++ b/highcharts/modules/dotplot.src.js @@ -0,0 +1,163 @@ +/** + * @license Highcharts JS v8.2.0 (2020-08-20) + * + * Dot plot series type for Highcharts + * + * (c) 2010-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/dotplot', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'Series/DotplotSeries.js', [_modules['Core/Renderer/SVG/SVGRenderer.js'], _modules['Core/Utilities.js']], function (SVGRenderer, U) { + /* * + * + * (c) 2009-2020 Torstein Honsi + * + * Dot plot series type for Highcharts + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * @private + * @todo + * - Check update, remove etc. + * - Custom icons like persons, carts etc. Either as images, font icons or + * Highcharts symbols. + */ + var extend = U.extend, + objectEach = U.objectEach, + pick = U.pick, + seriesType = U.seriesType; + /** + * @private + * @class + * @name Highcharts.seriesTypes.dotplot + * + * @augments Highcharts.Series + */ + seriesType('dotplot', 'column', { + itemPadding: 0.2, + marker: { + symbol: 'circle', + states: { + hover: {}, + select: {} + } + } + }, { + markerAttribs: void 0, + drawPoints: function () { + var series = this, + renderer = series.chart.renderer, + seriesMarkerOptions = this.options.marker, + itemPaddingTranslated = this.yAxis.transA * + series.options.itemPadding, + borderWidth = this.borderWidth, + crisp = borderWidth % 2 ? 0.5 : 1; + this.points.forEach(function (point) { + var yPos, + attr, + graphics, + itemY, + pointAttr, + pointMarkerOptions = point.marker || {}, + symbol = (pointMarkerOptions.symbol || + seriesMarkerOptions.symbol), + radius = pick(pointMarkerOptions.radius, + seriesMarkerOptions.radius), + size, + yTop, + isSquare = symbol !== 'rect', + x, + y; + point.graphics = graphics = point.graphics || {}; + pointAttr = point.pointAttr ? + (point.pointAttr[point.selected ? 'selected' : ''] || + series.pointAttr['']) : + series.pointAttribs(point, point.selected && 'select'); + delete pointAttr.r; + if (series.chart.styledMode) { + delete pointAttr.stroke; + delete pointAttr['stroke-width']; + } + if (point.y !== null) { + if (!point.graphic) { + point.graphic = renderer.g('point').add(series.group); + } + itemY = point.y; + yTop = pick(point.stackY, point.y); + size = Math.min(point.pointWidth, series.yAxis.transA - itemPaddingTranslated); + for (yPos = yTop; yPos > yTop - point.y; yPos--) { + x = point.barX + (isSquare ? + point.pointWidth / 2 - size / 2 : + 0); + y = series.yAxis.toPixels(yPos, true) + + itemPaddingTranslated / 2; + if (series.options.crisp) { + x = Math.round(x) - crisp; + y = Math.round(y) + crisp; + } + attr = { + x: x, + y: y, + width: Math.round(isSquare ? size : point.pointWidth), + height: Math.round(size), + r: radius + }; + if (graphics[itemY]) { + graphics[itemY].animate(attr); + } + else { + graphics[itemY] = renderer.symbol(symbol) + .attr(extend(attr, pointAttr)) + .add(point.graphic); + } + graphics[itemY].isActive = true; + itemY--; + } + } + objectEach(graphics, function (graphic, key) { + if (!graphic.isActive) { + graphic.destroy(); + delete graphic[key]; + } + else { + graphic.isActive = false; + } + }); + }); + } + }); + SVGRenderer.prototype.symbols.rect = function (x, y, w, h, options) { + return SVGRenderer.prototype.symbols.callout(x, y, w, h, options); + }; + + }); + _registerModule(_modules, 'masters/modules/dotplot.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/drag-panes.js b/highcharts/modules/drag-panes.js new file mode 100644 index 0000000..dc6cf70 --- /dev/null +++ b/highcharts/modules/drag-panes.js @@ -0,0 +1,20 @@ +/* + Highstock JS v8.2.0 (2020-08-20) + + Drag-panes module + + (c) 2010-2019 Highsoft AS + Author: Kacper Madej + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/drag-panes",["highcharts","highcharts/modules/stock"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,m,b,d){a.hasOwnProperty(m)||(a[m]=d.apply(null,b))}a=a?a._modules:{};b(a,"Extensions/DragPanes.js",[a["Core/Globals.js"],a["Core/Axis/Axis.js"],a["Core/Pointer.js"],a["Core/Utilities.js"]], +function(a,b,u,d){var m=a.hasTouch,f=d.addEvent,r=d.clamp,x=d.isNumber,y=d.merge,z=d.objectEach,v=d.relativeLength;d=d.wrap;var w=function(){function a(c){this.options=this.lastPos=this.controlLine=this.axis=void 0;this.init(c)}a.prototype.init=function(c,a){this.axis=c;this.options=c.options.resize;this.render();a||this.addMouseEvents()};a.prototype.render=function(){var c=this.axis,a=c.chart,e=this.options,b=e.x||0,d=e.y,k=r(c.top+c.height+d,a.plotTop,a.plotTop+a.plotHeight),l={};a.styledMode|| +(l={cursor:e.cursor,stroke:e.lineColor,"stroke-width":e.lineWidth,dashstyle:e.lineDashStyle});this.lastPos=k-d;this.controlLine||(this.controlLine=a.renderer.path().addClass("highcharts-axis-resizer"));this.controlLine.add(c.axisGroup);e=a.styledMode?this.controlLine.strokeWidth():e.lineWidth;l.d=a.renderer.crispLine([["M",c.left+b,k],["L",c.left+c.width+b,k]],e);this.controlLine.attr(l)};a.prototype.addMouseEvents=function(){var c=this,a=c.controlLine.element,e=c.axis.chart.container,b=[],d,k,l; +c.mouseMoveHandler=d=function(a){c.onMouseMove(a)};c.mouseUpHandler=k=function(a){c.onMouseUp(a)};c.mouseDownHandler=l=function(a){c.onMouseDown(a)};b.push(f(e,"mousemove",d),f(e.ownerDocument,"mouseup",k),f(a,"mousedown",l));m&&b.push(f(e,"touchmove",d),f(e.ownerDocument,"touchend",k),f(a,"touchstart",l));c.eventsToUnbind=b};a.prototype.onMouseMove=function(a){a.touches&&0===a.touches[0].pageX||!this.grabbed||(this.hasDragged=!0,this.updateAxes(this.axis.chart.pointer.normalize(a).chartY-this.options.y))}; +a.prototype.onMouseUp=function(a){this.hasDragged&&this.updateAxes(this.axis.chart.pointer.normalize(a).chartY-this.options.y);this.grabbed=this.hasDragged=this.axis.chart.activeResizer=null};a.prototype.onMouseDown=function(a){this.axis.chart.pointer.reset(!1,0);this.grabbed=this.axis.chart.activeResizer=!0};a.prototype.updateAxes=function(a){var c=this,e=c.axis.chart,b=c.options.controlledAxis,d=0===b.next.length?[e.yAxis.indexOf(c.axis)+1]:b.next;b=[c.axis].concat(b.prev);var k=[],l=!1,p=e.plotTop, +f=e.plotHeight,m=p+f;a=r(a,p,m);var q=a-c.lastPos;1>q*q||([b,d].forEach(function(b,d){b.forEach(function(b,h){var g=(b=x(b)?e.yAxis[b]:d||h?e.get(b):b)&&b.options;if(g&&"navigator-y-axis"!==g.id){h=b.top;var t=Math.round(v(g.minLength,f));var n=Math.round(v(g.maxLength,f));d?(q=a-c.lastPos,g=Math.round(r(b.len-q,t,n)),h=b.top+q,h+g>m&&(n=m-g-h,a+=n,h+=n),hm&&(g=f)),g===t&&(l=!0),k.push({axis:b,options:{top:100*(h-p)/f+"%",height:100*g/f+"%"}})):(g=Math.round(r(a-h,t,n)),g===n&&(l=!0), +a=h+g,k.push({axis:b,options:{height:100*g/f+"%"}}))}})}),l||(k.forEach(function(a){a.axis.update(a.options,!1)}),e.redraw(!1)))};a.prototype.destroy=function(){var a=this;delete a.axis.resizer;this.eventsToUnbind&&this.eventsToUnbind.forEach(function(a){a()});a.controlLine.destroy();z(a,function(b,c){a[c]=null})};a.resizerOptions={minLength:"10%",maxLength:"100%",resize:{controlledAxis:{next:[],prev:[]},enabled:!1,cursor:"ns-resize",lineColor:"#cccccc",lineDashStyle:"Solid",lineWidth:4,x:0,y:0}}; +return a}();b.keepProps.push("resizer");f(b,"afterRender",function(){var b=this.resizer,c=this.options.resize;c&&(c=!1!==c.enabled,b?c?b.init(this,!0):b.destroy():c&&(this.resizer=new a.AxisResizer(this)))});f(b,"destroy",function(a){!a.keepEvents&&this.resizer&&this.resizer.destroy()});d(u.prototype,"runPointActions",function(a){this.chart.activeResizer||a.apply(this,Array.prototype.slice.call(arguments,1))});d(u.prototype,"drag",function(a){this.chart.activeResizer||a.apply(this,Array.prototype.slice.call(arguments, +1))});y(!0,b.defaultYAxisOptions,w.resizerOptions);a.AxisResizer=w;return a.AxisResizer});b(a,"masters/modules/drag-panes.src.js",[],function(){})}); +//# sourceMappingURL=drag-panes.js.map \ No newline at end of file diff --git a/highcharts/modules/drag-panes.js.map b/highcharts/modules/drag-panes.js.map new file mode 100644 index 0000000..6f3868d --- /dev/null +++ b/highcharts/modules/drag-panes.js.map @@ -0,0 +1 @@ +{"version":3,"file":"drag-panes.js.map","lineCount":19,"mappings":"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","sources":["drag-panes.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","Axis","Pointer","U","hasTouch","addEvent","clamp","isNumber","merge","objectEach","relativeLength","wrap","AxisResizer","axis","options","lastPos","controlLine","init","prototype","AxisResizer.prototype.init","update","resize","render","addMouseEvents","AxisResizer.prototype.render","resizer","chart","x","y","pos","top","height","plotTop","plotHeight","attr","styledMode","cursor","stroke","lineColor","lineWidth","dashstyle","lineDashStyle","renderer","addClass","add","axisGroup","strokeWidth","d","crispLine","left","width","AxisResizer.prototype.addMouseEvents","ctrlLineElem","element","container","eventsToUnbind","mouseMoveHandler","mouseUpHandler","mouseDownHandler","e","onMouseMove","onMouseUp","onMouseDown","push","ownerDocument","AxisResizer.prototype.onMouseMove","touches","pageX","grabbed","hasDragged","updateAxes","pointer","normalize","chartY","AxisResizer.prototype.onMouseUp","activeResizer","AxisResizer.prototype.onMouseDown","reset","AxisResizer.prototype.updateAxes","axes","controlledAxis","nextAxes","next","length","yAxis","indexOf","prevAxes","concat","prev","axesConfigs","stopDrag","plotBottom","yDelta","forEach","axesGroup","isNext","axisInfo","i","axisOptions","get","id","minLength","Math","round","maxLength","len","hDelta","config","redraw","destroy","AxisResizer.prototype.destroy","unbind","val","key","resizerOptions","enabled","keepProps","keepEvents","proceed","Array","slice","call","arguments","defaultYAxisOptions"]} \ No newline at end of file diff --git a/highcharts/modules/drag-panes.src.js b/highcharts/modules/drag-panes.src.js new file mode 100644 index 0000000..2cecc85 --- /dev/null +++ b/highcharts/modules/drag-panes.src.js @@ -0,0 +1,581 @@ +/** + * @license Highstock JS v8.2.0 (2020-08-20) + * + * Drag-panes module + * + * (c) 2010-2019 Highsoft AS + * Author: Kacper Madej + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/drag-panes', ['highcharts', 'highcharts/modules/stock'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'Extensions/DragPanes.js', [_modules['Core/Globals.js'], _modules['Core/Axis/Axis.js'], _modules['Core/Pointer.js'], _modules['Core/Utilities.js']], function (H, Axis, Pointer, U) { + /* * + * + * Plugin for resizing axes / panes in a chart. + * + * (c) 2010-2017 Highsoft AS + * + * Author: Kacper Madej + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var hasTouch = H.hasTouch; + var addEvent = U.addEvent, + clamp = U.clamp, + isNumber = U.isNumber, + merge = U.merge, + objectEach = U.objectEach, + relativeLength = U.relativeLength, + wrap = U.wrap; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The AxisResizer class. + * + * @private + * @class + * @name Highcharts.AxisResizer + * + * @param {Highcharts.Axis} axis + * Main axis for the AxisResizer. + */ + var AxisResizer = /** @class */ (function () { + function AxisResizer(axis) { + /* eslint-enable no-invalid-this */ + this.axis = void 0; + this.controlLine = void 0; + this.lastPos = void 0; + this.options = void 0; + this.init(axis); + } + /** + * Initialize the AxisResizer object. + * + * @function Highcharts.AxisResizer#init + * + * @param {Highcharts.Axis} axis + * Main axis for the AxisResizer. + */ + AxisResizer.prototype.init = function (axis, update) { + this.axis = axis; + this.options = axis.options.resize; + this.render(); + if (!update) { + // Add mouse events. + this.addMouseEvents(); + } + }; + /** + * Render the AxisResizer + * + * @function Highcharts.AxisResizer#render + */ + AxisResizer.prototype.render = function () { + var resizer = this, + axis = resizer.axis, + chart = axis.chart, + options = resizer.options, + x = options.x || 0, + y = options.y, + // Normalize control line position according to the plot area + pos = clamp(axis.top + axis.height + y, + chart.plotTop, + chart.plotTop + chart.plotHeight), + attr = {}, + lineWidth; + if (!chart.styledMode) { + attr = { + cursor: options.cursor, + stroke: options.lineColor, + 'stroke-width': options.lineWidth, + dashstyle: options.lineDashStyle + }; + } + // Register current position for future reference. + resizer.lastPos = pos - y; + if (!resizer.controlLine) { + resizer.controlLine = chart.renderer.path() + .addClass('highcharts-axis-resizer'); + } + // Add to axisGroup after axis update, because the group is recreated + // Do .add() before path is calculated because strokeWidth() needs it. + resizer.controlLine.add(axis.axisGroup); + lineWidth = chart.styledMode ? + resizer.controlLine.strokeWidth() : + options.lineWidth; + attr.d = chart.renderer.crispLine([ + ['M', axis.left + x, pos], + ['L', axis.left + axis.width + x, pos] + ], lineWidth); + resizer.controlLine.attr(attr); + }; + /** + * Set up the mouse and touch events for the control line. + * + * @function Highcharts.AxisResizer#addMouseEvents + */ + AxisResizer.prototype.addMouseEvents = function () { + var resizer = this, + ctrlLineElem = resizer.controlLine.element, + container = resizer.axis.chart.container, + eventsToUnbind = [], + mouseMoveHandler, + mouseUpHandler, + mouseDownHandler; + // Create mouse events' handlers. + // Make them as separate functions to enable wrapping them: + resizer.mouseMoveHandler = mouseMoveHandler = function (e) { + resizer.onMouseMove(e); + }; + resizer.mouseUpHandler = mouseUpHandler = function (e) { + resizer.onMouseUp(e); + }; + resizer.mouseDownHandler = mouseDownHandler = function (e) { + resizer.onMouseDown(e); + }; + // Add mouse move and mouseup events. These are bind to doc/container, + // because resizer.grabbed flag is stored in mousedown events. + eventsToUnbind.push(addEvent(container, 'mousemove', mouseMoveHandler), addEvent(container.ownerDocument, 'mouseup', mouseUpHandler), addEvent(ctrlLineElem, 'mousedown', mouseDownHandler)); + // Touch events. + if (hasTouch) { + eventsToUnbind.push(addEvent(container, 'touchmove', mouseMoveHandler), addEvent(container.ownerDocument, 'touchend', mouseUpHandler), addEvent(ctrlLineElem, 'touchstart', mouseDownHandler)); + } + resizer.eventsToUnbind = eventsToUnbind; + }; + /** + * Mouse move event based on x/y mouse position. + * + * @function Highcharts.AxisResizer#onMouseMove + * + * @param {Highcharts.PointerEventObject} e + * Mouse event. + */ + AxisResizer.prototype.onMouseMove = function (e) { + /* + * In iOS, a mousemove event with e.pageX === 0 is fired when holding + * the finger down in the center of the scrollbar. This should + * be ignored. Borrowed from Navigator. + */ + if (!e.touches || e.touches[0].pageX !== 0) { + // Drag the control line + if (this.grabbed) { + this.hasDragged = true; + this.updateAxes(this.axis.chart.pointer.normalize(e).chartY - + this.options.y); + } + } + }; + /** + * Mouse up event based on x/y mouse position. + * + * @function Highcharts.AxisResizer#onMouseUp + * + * @param {Highcharts.PointerEventObject} e + * Mouse event. + */ + AxisResizer.prototype.onMouseUp = function (e) { + if (this.hasDragged) { + this.updateAxes(this.axis.chart.pointer.normalize(e).chartY - + this.options.y); + } + // Restore runPointActions. + this.grabbed = this.hasDragged = this.axis.chart.activeResizer = + null; + }; + /** + * Mousedown on a control line. + * Will store necessary information for drag&drop. + * + * @function Highcharts.AxisResizer#onMouseDown + */ + AxisResizer.prototype.onMouseDown = function (e) { + // Clear all hover effects. + this.axis.chart.pointer.reset(false, 0); + // Disable runPointActions. + this.grabbed = this.axis.chart.activeResizer = true; + }; + /** + * Update all connected axes after a change of control line position + * + * @function Highcharts.AxisResizer#updateAxes + * + * @param {number} chartY + */ + AxisResizer.prototype.updateAxes = function (chartY) { + var resizer = this, + chart = resizer.axis.chart, + axes = resizer.options.controlledAxis, + nextAxes = axes.next.length === 0 ? + [chart.yAxis.indexOf(resizer.axis) + 1] : axes.next, + // Main axis is included in the prev array by default + prevAxes = [resizer.axis].concat(axes.prev), + // prev and next configs + axesConfigs = [], + stopDrag = false, + plotTop = chart.plotTop, + plotHeight = chart.plotHeight, + plotBottom = plotTop + plotHeight, + yDelta, + calculatePercent = function (value) { + return value * 100 / plotHeight + '%'; + }, normalize = function (val, min, max) { + return Math.round(clamp(val, min, max)); + }; + // Normalize chartY to plot area limits + chartY = clamp(chartY, plotTop, plotBottom); + yDelta = chartY - resizer.lastPos; + // Update on changes of at least 1 pixel in the desired direction + if (yDelta * yDelta < 1) { + return; + } + // First gather info how axes should behave + [prevAxes, nextAxes].forEach(function (axesGroup, isNext) { + axesGroup.forEach(function (axisInfo, i) { + // Axes given as array index, axis object or axis id + var axis = isNumber(axisInfo) ? + // If it's a number - it's an index + chart.yAxis[axisInfo] : + ( + // If it's first elem. in first group + (!isNext && !i) ? + // then it's an Axis object + axisInfo : + // else it should be an id + chart.get(axisInfo)), + axisOptions = axis && axis.options, + optionsToUpdate = {}, + hDelta = 0, + height, + top, + minLength, + maxLength; + // Skip if axis is not found + // or it is navigator's yAxis (#7732) + if (!axisOptions || + axisOptions.id === 'navigator-y-axis') { + return; + } + top = axis.top; + minLength = Math.round(relativeLength(axisOptions.minLength, plotHeight)); + maxLength = Math.round(relativeLength(axisOptions.maxLength, plotHeight)); + if (isNext) { + // Try to change height first. yDelta could had changed + yDelta = chartY - resizer.lastPos; + // Normalize height to option limits + height = normalize(axis.len - yDelta, minLength, maxLength); + // Adjust top, so the axis looks like shrinked from top + top = axis.top + yDelta; + // Check for plot area limits + if (top + height > plotBottom) { + hDelta = plotBottom - height - top; + chartY += hDelta; + top += hDelta; + } + // Fit to plot - when overflowing on top + if (top < plotTop) { + top = plotTop; + if (top + height > plotBottom) { + height = plotHeight; + } + } + // If next axis meets min length, stop dragging: + if (height === minLength) { + stopDrag = true; + } + axesConfigs.push({ + axis: axis, + options: { + top: calculatePercent(top - plotTop), + height: calculatePercent(height) + } + }); + } + else { + // Normalize height to option limits + height = normalize(chartY - top, minLength, maxLength); + // If prev axis meets max length, stop dragging: + if (height === maxLength) { + stopDrag = true; + } + // Check axis size limits + chartY = top + height; + axesConfigs.push({ + axis: axis, + options: { + height: calculatePercent(height) + } + }); + } + optionsToUpdate.height = height; + }); + }); + // If we hit the min/maxLength with dragging, don't do anything: + if (!stopDrag) { + // Now update axes: + axesConfigs.forEach(function (config) { + config.axis.update(config.options, false); + }); + chart.redraw(false); + } + }; + /** + * Destroy AxisResizer. Clear outside references, clear events, + * destroy elements, nullify properties. + * + * @function Highcharts.AxisResizer#destroy + */ + AxisResizer.prototype.destroy = function () { + var resizer = this, + axis = resizer.axis; + // Clear resizer in axis + delete axis.resizer; + // Clear control line events + if (this.eventsToUnbind) { + this.eventsToUnbind.forEach(function (unbind) { + unbind(); + }); + } + // Destroy AxisResizer elements + resizer.controlLine.destroy(); + // Nullify properties + objectEach(resizer, function (val, key) { + resizer[key] = null; + }); + }; + // Default options for AxisResizer. + AxisResizer.resizerOptions = { + /** + * Minimal size of a resizable axis. Could be set as a percent + * of plot area or pixel size. + * + * @sample {highstock} stock/yaxis/resize-min-max-length + * minLength and maxLength + * + * @type {number|string} + * @product highstock + * @requires modules/drag-panes + * @apioption yAxis.minLength + */ + minLength: '10%', + /** + * Maximal size of a resizable axis. Could be set as a percent + * of plot area or pixel size. + * + * @sample {highstock} stock/yaxis/resize-min-max-length + * minLength and maxLength + * + * @type {number|string} + * @product highstock + * @requires modules/drag-panes + * @apioption yAxis.maxLength + */ + maxLength: '100%', + /** + * Options for axis resizing. It adds a thick line between panes which + * the user can drag in order to resize the panes. + * + * @sample {highstock} stock/demo/candlestick-and-volume + * Axis resizing enabled + * + * @product highstock + * @requires modules/drag-panes + * @optionparent yAxis.resize + */ + resize: { + /** + * Contains two arrays of axes that are controlled by control line + * of the axis. + * + * @requires modules/drag-panes + */ + controlledAxis: { + /** + * Array of axes that should move out of the way of resizing + * being done for the current axis. If not set, the next axis + * will be used. + * + * @sample {highstock} stock/yaxis/multiple-resizers + * Three panes with resizers + * @sample {highstock} stock/yaxis/resize-multiple-axes + * One resizer controlling multiple axes + * + * @type {Array} + * @default [] + * @requires modules/drag-panes + */ + next: [], + /** + * Array of axes that should move with the current axis + * while resizing. + * + * @sample {highstock} stock/yaxis/multiple-resizers + * Three panes with resizers + * @sample {highstock} stock/yaxis/resize-multiple-axes + * One resizer controlling multiple axes + * + * @type {Array} + * @default [] + * @requires modules/drag-panes + */ + prev: [] + }, + /** + * Enable or disable resize by drag for the axis. + * + * @sample {highstock} stock/demo/candlestick-and-volume + * Enabled resizer + * + * @requires modules/drag-panes + */ + enabled: false, + /** + * Cursor style for the control line. + * + * In styled mode use class `highcharts-axis-resizer` instead. + * + * @requires modules/drag-panes + */ + cursor: 'ns-resize', + /** + * Color of the control line. + * + * In styled mode use class `highcharts-axis-resizer` instead. + * + * @sample {highstock} stock/yaxis/styled-resizer + * Styled resizer + * + * @type {Highcharts.ColorString} + * @requires modules/drag-panes + */ + lineColor: '#cccccc', + /** + * Dash style of the control line. + * + * In styled mode use class `highcharts-axis-resizer` instead. + * + * @see For supported options check [dashStyle](#plotOptions.series.dashStyle) + * + * @sample {highstock} stock/yaxis/styled-resizer + * Styled resizer + * + * @requires modules/drag-panes + */ + lineDashStyle: 'Solid', + /** + * Width of the control line. + * + * In styled mode use class `highcharts-axis-resizer` instead. + * + * @sample {highstock} stock/yaxis/styled-resizer + * Styled resizer + * + * @requires modules/drag-panes + */ + lineWidth: 4, + /** + * Horizontal offset of the control line. + * + * @sample {highstock} stock/yaxis/styled-resizer + * Styled resizer + * + * @requires modules/drag-panes + */ + x: 0, + /** + * Vertical offset of the control line. + * + * @sample {highstock} stock/yaxis/styled-resizer + * Styled resizer + * + * @requires modules/drag-panes + */ + y: 0 + } + }; + return AxisResizer; + }()); + // Keep resizer reference on axis update + Axis.keepProps.push('resizer'); + /* eslint-disable no-invalid-this */ + // Add new AxisResizer, update or remove it + addEvent(Axis, 'afterRender', function () { + var axis = this, + resizer = axis.resizer, + resizerOptions = axis.options.resize, + enabled; + if (resizerOptions) { + enabled = resizerOptions.enabled !== false; + if (resizer) { + // Resizer present and enabled + if (enabled) { + // Update options + resizer.init(axis, true); + // Resizer present, but disabled + } + else { + // Destroy the resizer + resizer.destroy(); + } + } + else { + // Resizer not present and enabled + if (enabled) { + // Add new resizer + axis.resizer = new H.AxisResizer(axis); + } + // Resizer not present and disabled, so do nothing + } + } + }); + // Clear resizer on axis remove. + addEvent(Axis, 'destroy', function (e) { + if (!e.keepEvents && this.resizer) { + this.resizer.destroy(); + } + }); + // Prevent any hover effects while dragging a control line of AxisResizer. + wrap(Pointer.prototype, 'runPointActions', function (proceed) { + if (!this.chart.activeResizer) { + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + } + }); + // Prevent default drag action detection while dragging a control line of + // AxisResizer. (#7563) + wrap(Pointer.prototype, 'drag', function (proceed) { + if (!this.chart.activeResizer) { + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + } + }); + merge(true, Axis.defaultYAxisOptions, AxisResizer.resizerOptions); + H.AxisResizer = AxisResizer; + + return H.AxisResizer; + }); + _registerModule(_modules, 'masters/modules/drag-panes.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/draggable-points.js b/highcharts/modules/draggable-points.js new file mode 100644 index 0000000..f6195e0 --- /dev/null +++ b/highcharts/modules/draggable-points.js @@ -0,0 +1,40 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + (c) 2009-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(e){"object"===typeof module&&module.exports?(e["default"]=e,module.exports=e):"function"===typeof define&&define.amd?define("highcharts/modules/draggable-points",["highcharts"],function(r){e(r);e.Highcharts=r;return e}):e("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(e){function r(e,q,l,r){e.hasOwnProperty(q)||(e[q]=r.apply(null,l))}e=e?e._modules:{};r(e,"Extensions/DraggablePoints.js",[e["Core/Globals.js"],e["Core/Series/Point.js"],e["Core/Utilities.js"]],function(e,q,l){function r(a){return{left:"right", +right:"left",top:"bottom",bottom:"top"}[a]}function K(a){var b=["draggableX","draggableY"],c;m(a.dragDropProps,function(a){a.optionName&&b.push(a.optionName)});for(c=b.length;c--;)if(a.options.dragDrop[b[c]])return!0}function L(a){var b=a.series?a.series.length:0;if(a.hasCartesianSeries&&!a.polar)for(;b--;)if(a.series[b].options.dragDrop&&K(a.series[b]))return!0}function M(a){var b=a.series,c=b.options.dragDrop||{};a=a.options&&a.options.dragDrop;var d,f;m(b.dragDropProps,function(a){"x"===a.axis&& +a.move?d=!0:"y"===a.axis&&a.move&&(f=!0)});return(c.draggableX&&d||c.draggableY&&f)&&!(a&&!1===a.draggableX&&!1===a.draggableY)&&b.yAxis&&b.xAxis}function w(a,b){return"undefined"===typeof a.chartX||"undefined"===typeof a.chartY?b.pointer.normalize(a):a}function x(a,b,c,d){var f=b.map(function(b){return t(a,b,c,d)});return function(){f.forEach(function(a){a()})}}function N(a,b,c){var d=b.dragDropData.origin;b=d.chartX;d=d.chartY;var f=a.chartX;a=a.chartY;return Math.sqrt((f-b)*(f-b)+(a-d)*(a-d))> +c}function O(a,b,c){var d={chartX:a.chartX,chartY:a.chartY,guideBox:c&&{x:c.attr("x"),y:c.attr("y"),width:c.attr("width"),height:c.attr("height")},points:{}};b.forEach(function(b){var c={};m(b.series.dragDropProps,function(d,f){d=b.series[d.axis+"Axis"];c[f]=b[f];c[f+"Offset"]=d.toPixels(b[f])-(d.horiz?a.chartX:a.chartY)});c.point=b;d.points[b.id]=c});return d}function P(a){var b=a.series,c=[],d=b.options.dragDrop.groupBy;b.isSeriesBoosting?b.options.data.forEach(function(a,d){c.push((new b.pointClass).init(b, +a));c[c.length-1].index=d}):c=b.points;return a.options[d]?c.filter(function(b){return b.options[d]===a.options[d]}):[a]}function D(a,b){var c=P(b),d=b.series,f=d.chart,n;v(d.options.dragDrop&&d.options.dragDrop.liveRedraw,!0)||(f.dragGuideBox=n=d.getGuideBox(c),f.setGuideBoxState("default",d.options.dragDrop.guideBox).add(d.group));f.dragDropData={origin:O(a,c,n),point:b,groupedPoints:c,isDragging:!0}}function Q(a,b){var c=a.point,d=p(c.series.options.dragDrop,c.options.dragDrop),f={},n=a.updateProp, +B={};m(c.series.dragDropProps,function(a,b){if(!n||n===b&&a.resize&&(!a.optionName||!1!==d[a.optionName]))if(n||a.move&&("x"===a.axis&&d.draggableX||"y"===a.axis&&d.draggableY))f[b]=a});(n?[c]:a.groupedPoints).forEach(function(c){B[c.id]={point:c,newValues:c.getDropValues(a.origin,b,f)}});return B}function E(a,b){var c=a.dragDropData.newPoints;b=!1===b?!1:p({duration:400},a.options.chart.animation);a.isDragDropAnimating=!0;m(c,function(a){a.point.update(a.newValues,!1)});a.redraw(b);setTimeout(function(){delete a.isDragDropAnimating; +a.hoverPoint&&!a.dragHandles&&a.hoverPoint.showDragHandles()},b.duration)}function F(a){var b=a.series&&a.series.chart,c=b&&b.dragDropData;!b||!b.dragHandles||c&&(c.isDragging&&c.draggedPastSensitivity||c.isHoveringHandle===a.id)||b.hideDragHandles()}function G(a){var b=0,c;for(c in a)Object.hasOwnProperty.call(a,c)&&b++;return b}function H(a){for(var b in a)if(Object.hasOwnProperty.call(a,b))return a[b]}function R(a,b){if(!b.zoomOrPanKeyPressed(a)){var c=b.dragDropData;var d=0;if(c&&c.isDragging){var f= +c.point;d=f.series.options.dragDrop;a.preventDefault();c.draggedPastSensitivity||(c.draggedPastSensitivity=N(a,b,v(f.options.dragDrop&&f.options.dragDrop.dragSensitivity,d&&d.dragSensitivity,2)));c.draggedPastSensitivity&&(c.newPoints=Q(c,a),b=c.newPoints,d=G(b),b=1===d?H(b):null,f.firePointEvent("drag",{origin:c.origin,newPoints:c.newPoints,newPoint:b&&b.newValues,newPointId:b&&b.point.id,numNewPoints:d,chartX:a.chartX,chartY:a.chartY},function(){var b=f.series,c=b.chart,d=c.dragDropData,e=p(b.options.dragDrop, +f.options.dragDrop),g=e.draggableX,k=e.draggableY;b=d.origin;var h=a.chartX-b.chartX,y=a.chartY-b.chartY,u=h;d=d.updateProp;c.inverted&&(h=-y,y=-u);if(v(e.liveRedraw,!0))E(c,!1),f.showDragHandles();else if(d){g=h;c=y;u=f.series;k=u.chart;d=k.dragDropData;e=u.dragDropProps[d.updateProp];var l=d.newPoints[f.id].newValues;var q="function"===typeof e.resizeSide?e.resizeSide(l,f):e.resizeSide;e.beforeResize&&e.beforeResize(k.dragGuideBox,l,f);k=k.dragGuideBox;u="x"===e.axis&&u.xAxis.reversed||"y"===e.axis&& +u.yAxis.reversed?r(q):q;g="x"===e.axis?g-(d.origin.prevdX||0):0;c="y"===e.axis?c-(d.origin.prevdY||0):0;switch(u){case "left":var m={x:k.attr("x")+g,width:Math.max(1,k.attr("width")-g)};break;case "right":m={width:Math.max(1,k.attr("width")+g)};break;case "top":m={y:k.attr("y")+c,height:Math.max(1,k.attr("height")-c)};break;case "bottom":m={height:Math.max(1,k.attr("height")+c)}}k.attr(m)}else c.dragGuideBox.translate(g?h:0,k?y:0);b.prevdX=h;b.prevdY=y}))}}}function A(a,b){var c=b.dragDropData;if(c&& +c.isDragging&&c.draggedPastSensitivity){var d=c.point,f=c.newPoints,e=G(f),g=1===e?H(f):null;b.dragHandles&&b.hideDragHandles();a.preventDefault();b.cancelClick=!0;d.firePointEvent("drop",{origin:c.origin,chartX:a.chartX,chartY:a.chartY,newPoints:f,numNewPoints:e,newPoint:g&&g.newValues,newPointId:g&&g.point.id},function(){E(b)})}delete b.dragDropData;b.dragGuideBox&&(b.dragGuideBox.destroy(),delete b.dragGuideBox)}function S(a){var b=a.container,c=e.doc;L(a)&&(x(b,["mousedown","touchstart"],function(b){b= +w(b,a);var c=a.hoverPoint,d=p(c&&c.series.options.dragDrop,c&&c.options.dragDrop),e=d.draggableX||!1;d=d.draggableY||!1;a.cancelClick=!1;!e&&!d||a.zoomOrPanKeyPressed(b)||a.hasDraggedAnnotation||(a.dragDropData&&a.dragDropData.isDragging?A(b,a):c&&M(c)&&(a.mouseIsDown=!1,D(b,c),c.firePointEvent("dragStart",b)))}),x(b,["mousemove","touchmove"],function(b){R(w(b,a),a)}),t(b,"mouseleave",function(b){A(w(b,a),a)}),a.unbindDragDropMouseUp=x(c,["mouseup","touchend"],function(b){A(w(b,a),a)}),a.hasAddedDragDropEvents= +!0,t(a,"destroy",function(){a.unbindDragDropMouseUp&&a.unbindDragDropMouseUp()}))}var t=l.addEvent,T=l.clamp,p=l.merge,m=l.objectEach,v=l.pick;"";var g=e.seriesTypes;l=function(a){a=a.shapeArgs||a.graphic.getBBox();var b=a.r||0,c=a.height/2;return[["M",0,b],["L",0,c-5],["A",1,1,0,0,0,0,c+5],["A",1,1,0,0,0,0,c-5],["M",0,c+5],["L",0,a.height-b]]};var z=g.line.prototype.dragDropProps={x:{axis:"x",move:!0},y:{axis:"y",move:!0}};g.flags&&(g.flags.prototype.dragDropProps=z);var h=g.column.prototype.dragDropProps= +{x:{axis:"x",move:!0},y:{axis:"y",move:!1,resize:!0,beforeResize:function(a,b,c){var d=c.series.translatedThreshold,f=a.attr("y");b.y>=c.series.options.threshold?(b=a.attr("height"),a.attr({height:Math.max(0,Math.round(b+(d?d-(f+b):0)))})):a.attr({y:Math.round(f+(d?d-f:0))})},resizeSide:function(a,b){var c=b.series.chart.dragHandles;a=a.y>=(b.series.options.threshold||0)?"top":"bottom";b=r(a);c[b]&&(c[b].destroy(),delete c[b]);return a},handlePositioner:function(a){var b=a.shapeArgs||a.graphic.getBBox(); +return{x:b.x,y:a.y>=(a.series.options.threshold||0)?b.y:b.y+b.height}},handleFormatter:function(a){var b=a.shapeArgs||{};a=b.r||0;b=b.width||0;var c=b/2;return[["M",a,0],["L",c-5,0],["A",1,1,0,0,0,c+5,0],["A",1,1,0,0,0,c-5,0],["M",c+5,0],["L",b-a,0]]}}};g.bullet&&(g.bullet.prototype.dragDropProps={x:h.x,y:h.y,target:{optionName:"draggableTarget",axis:"y",move:!0,resize:!0,resizeSide:"top",handlePositioner:function(a){var b=a.targetGraphic.getBBox();return{x:a.barX,y:b.y+b.height/2}},handleFormatter:h.y.handleFormatter}}); +g.columnrange&&(g.columnrange.prototype.dragDropProps={x:{axis:"x",move:!0},low:{optionName:"draggableLow",axis:"y",move:!0,resize:!0,resizeSide:"bottom",handlePositioner:function(a){a=a.shapeArgs||a.graphic.getBBox();return{x:a.x,y:a.y+a.height}},handleFormatter:h.y.handleFormatter,propValidate:function(a,b){return a<=b.high}},high:{optionName:"draggableHigh",axis:"y",move:!0,resize:!0,resizeSide:"top",handlePositioner:function(a){a=a.shapeArgs||a.graphic.getBBox();return{x:a.x,y:a.y}},handleFormatter:h.y.handleFormatter, +propValidate:function(a,b){return a>=b.low}}});g.boxplot&&(g.boxplot.prototype.dragDropProps={x:h.x,low:{optionName:"draggableLow",axis:"y",move:!0,resize:!0,resizeSide:"bottom",handlePositioner:function(a){return{x:a.shapeArgs.x,y:a.lowPlot}},handleFormatter:h.y.handleFormatter,propValidate:function(a,b){return a<=b.q1}},q1:{optionName:"draggableQ1",axis:"y",move:!0,resize:!0,resizeSide:"bottom",handlePositioner:function(a){return{x:a.shapeArgs.x,y:a.q1Plot}},handleFormatter:h.y.handleFormatter, +propValidate:function(a,b){return a<=b.median&&a>=b.low}},median:{axis:"y",move:!0},q3:{optionName:"draggableQ3",axis:"y",move:!0,resize:!0,resizeSide:"top",handlePositioner:function(a){return{x:a.shapeArgs.x,y:a.q3Plot}},handleFormatter:h.y.handleFormatter,propValidate:function(a,b){return a<=b.high&&a>=b.median}},high:{optionName:"draggableHigh",axis:"y",move:!0,resize:!0,resizeSide:"top",handlePositioner:function(a){return{x:a.shapeArgs.x,y:a.highPlot}},handleFormatter:h.y.handleFormatter,propValidate:function(a, +b){return a>=b.q3}}});g.ohlc&&(g.ohlc.prototype.dragDropProps={x:h.x,low:{optionName:"draggableLow",axis:"y",move:!0,resize:!0,resizeSide:"bottom",handlePositioner:function(a){return{x:a.shapeArgs.x,y:a.plotLow}},handleFormatter:h.y.handleFormatter,propValidate:function(a,b){return a<=b.open&&a<=b.close}},high:{optionName:"draggableHigh",axis:"y",move:!0,resize:!0,resizeSide:"top",handlePositioner:function(a){return{x:a.shapeArgs.x,y:a.plotHigh}},handleFormatter:h.y.handleFormatter,propValidate:function(a, +b){return a>=b.open&&a>=b.close}},open:{optionName:"draggableOpen",axis:"y",move:!0,resize:!0,resizeSide:function(a){return a.open>=a.close?"top":"bottom"},handlePositioner:function(a){return{x:a.shapeArgs.x,y:a.plotOpen}},handleFormatter:h.y.handleFormatter,propValidate:function(a,b){return a<=b.high&&a>=b.low}},close:{optionName:"draggableClose",axis:"y",move:!0,resize:!0,resizeSide:function(a){return a.open>=a.close?"bottom":"top"},handlePositioner:function(a){return{x:a.shapeArgs.x,y:a.plotClose}}, +handleFormatter:h.y.handleFormatter,propValidate:function(a,b){return a<=b.high&&a>=b.low}}});if(g.arearange){z=g.columnrange.prototype.dragDropProps;var I=function(a){a=a.graphic?a.graphic.getBBox().width/2+1:4;return[["M",0-a,0],["a",a,a,0,1,0,2*a,0],["a",a,a,0,1,0,-2*a,0]]};g.arearange.prototype.dragDropProps={x:z.x,low:{optionName:"draggableLow",axis:"y",move:!0,resize:!0,resizeSide:"bottom",handlePositioner:function(a){return(a=a.lowerGraphic&&a.lowerGraphic.getBBox())?{x:a.x+a.width/2,y:a.y+ +a.height/2}:{x:-999,y:-999}},handleFormatter:I,propValidate:z.low.propValidate},high:{optionName:"draggableHigh",axis:"y",move:!0,resize:!0,resizeSide:"top",handlePositioner:function(a){return(a=a.upperGraphic&&a.upperGraphic.getBBox())?{x:a.x+a.width/2,y:a.y+a.height/2}:{x:-999,y:-999}},handleFormatter:I,propValidate:z.high.propValidate}}}g.waterfall&&(g.waterfall.prototype.dragDropProps={x:h.x,y:p(h.y,{handleFormatter:function(a){return a.isSum||a.isIntermediateSum?null:h.y.handleFormatter(a)}})}); +if(g.xrange){var J=function(a,b){var c=a.series,d=c.xAxis,f=c.yAxis,e=c.chart.inverted;b=d.toPixels(a[b],!0);var g=f.toPixels(a.y,!0);a=c.columnMetrics?c.columnMetrics.offset:-a.shapeArgs.height/2;e&&(b=d.len-b,g=f.len-g);return{x:Math.round(b),y:Math.round(g+a)}};l=g.xrange.prototype.dragDropProps={y:{axis:"y",move:!0},x:{optionName:"draggableX1",axis:"x",move:!0,resize:!0,resizeSide:"left",handlePositioner:function(a){return J(a,"x")},handleFormatter:l,propValidate:function(a,b){return a<=b.x2}}, +x2:{optionName:"draggableX2",axis:"x",move:!0,resize:!0,resizeSide:"right",handlePositioner:function(a){return J(a,"x2")},handleFormatter:l,propValidate:function(a,b){return a>=b.x}}};g.gantt&&(g.gantt.prototype.dragDropProps={y:l.y,start:p(l.x,{optionName:"draggableStart",validateIndividualDrag:function(a){return!a.milestone}}),end:p(l.x2,{optionName:"draggableEnd",validateIndividualDrag:function(a){return!a.milestone}})})}"gauge pie sunburst wordcloud sankey histogram pareto vector windbarb treemap bellcurve sma map mapline".split(" ").forEach(function(a){g[a]&& +(g[a].prototype.dragDropProps=null)});var U={"default":{className:"highcharts-drag-box-default",lineWidth:1,lineColor:"#888",color:"rgba(0, 0, 0, 0.1)",cursor:"move",zIndex:900}},V={className:"highcharts-drag-handle",color:"#fff",lineColor:"rgba(0, 0, 0, 0.6)",lineWidth:1,zIndex:901};e.Chart.prototype.setGuideBoxState=function(a,b){var c=this.dragGuideBox;b=p(U,b);a=p(b["default"],b[a]);return c.attr({className:a.className,stroke:a.lineColor,strokeWidth:a.lineWidth,fill:a.color,cursor:a.cursor,zIndex:a.zIndex}).css({pointerEvents:"none"})}; +q.prototype.getDropValues=function(a,b,c){var d=this,f=d.series,e=p(f.options.dragDrop,d.options.dragDrop),g={},C=a.points[d.id],h;for(h in c)if(Object.hasOwnProperty.call(c,h)){if("undefined"!==typeof l){var l=!1;break}l=!0}m(c,function(a,c){var h=C[c],n=f[a.axis+"Axis"];n=n.toValue((n.horiz?b.chartX:b.chartY)+C[c+"Offset"]);var k=a.axis.toUpperCase(),m=f[k.toLowerCase()+"Axis"].categories?1:0;m=v(e["dragPrecision"+k],m);var p=v(e["dragMin"+k],-Infinity);k=v(e["dragMax"+k],Infinity);m&&(n=Math.round(n/ +m)*m);n=T(n,p,k);l&&a.propValidate&&!a.propValidate(n,d)||"undefined"===typeof h||(g[c]=n)});return g};e.Series.prototype.getGuideBox=function(a){var b=this.chart,c=Infinity,d=-Infinity,f=Infinity,e=-Infinity,g;a.forEach(function(a){(a=a.graphic&&a.graphic.getBBox()||a.shapeArgs)&&(a.width||a.height||a.x||a.y)&&(g=!0,c=Math.min(a.x,c),d=Math.max(a.x+a.width,d),f=Math.min(a.y,f),e=Math.max(a.y+a.height,e))});return g?b.renderer.rect(c,f,d-c,e-f):b.renderer.g()};q.prototype.showDragHandles=function(){var a= +this,b=a.series,c=b.chart,d=c.renderer,f=p(b.options.dragDrop,a.options.dragDrop);m(b.dragDropProps,function(e,g){var h=p(V,e.handleOptions,f.dragHandle),l={className:h.className,"stroke-width":h.lineWidth,fill:h.color,stroke:h.lineColor},m=h.pathFormatter||e.handleFormatter,k=e.handlePositioner,n=e.validateIndividualDrag?e.validateIndividualDrag(a):!0;e.resize&&n&&e.resizeSide&&m&&(f["draggable"+e.axis.toUpperCase()]||f[e.optionName])&&!1!==f[e.optionName]&&(c.dragHandles||(c.dragHandles={group:d.g("drag-drop-handles").add(b.markerGroup|| +b.group)}),c.dragHandles.point=a.id,k=k(a),l.d=m=m(a),!m||0>k.x||0>k.y||(l.cursor=h.cursor||"x"===e.axis!==!!c.inverted?"ew-resize":"ns-resize",(h=c.dragHandles[e.optionName])||(h=c.dragHandles[e.optionName]=d.path().add(c.dragHandles.group)),h.translate(k.x,k.y).attr(l),x(h.element,["touchstart","mousedown"],function(b){b=w(b,c);var d=a.series.chart;d.zoomOrPanKeyPressed(b)||(d.mouseIsDown=!1,D(b,a),d.dragDropData.updateProp=b.updateProp=g,a.firePointEvent("dragStart",b),b.stopPropagation(),b.preventDefault())}), +t(c.dragHandles.group.element,"mouseover",function(){c.dragDropData=c.dragDropData||{};c.dragDropData.isHoveringHandle=a.id}),x(c.dragHandles.group.element,["touchend","mouseout"],function(){var b=a.series.chart;b.dragDropData&&a.id===b.dragDropData.isHoveringHandle&&delete b.dragDropData.isHoveringHandle;b.hoverPoint||F(a)})))})};e.Chart.prototype.hideDragHandles=function(){this.dragHandles&&(m(this.dragHandles,function(a,b){"group"!==b&&a.destroy&&a.destroy()}),this.dragHandles.group&&this.dragHandles.group.destroy&& +this.dragHandles.group.destroy(),delete this.dragHandles)};t(q,"mouseOver",function(){var a=this;setTimeout(function(){var b=a.series,c=b&&b.chart,d=c&&c.dragDropData,e=c&&c.is3d&&c.is3d();!c||d&&d.isDragging&&d.draggedPastSensitivity||c.isDragDropAnimating||!b.options.dragDrop||e||(c.dragHandles&&c.hideDragHandles(),a.showDragHandles())},12)});t(q,"mouseOut",function(){var a=this;setTimeout(function(){a.series&&F(a)},10)});t(q,"remove",function(){var a=this.series.chart,b=a.dragHandles;b&&b.point=== +this.id&&a.hideDragHandles()});e.Chart.prototype.zoomOrPanKeyPressed=function(a){var b=this.userOptions.chart||{},c=b.panKey&&b.panKey+"Key";return a[b.zoomKey&&b.zoomKey+"Key"]||a[c]};t(e.Chart,"render",function(){this.hasAddedDragDropEvents||S(this)})});r(e,"masters/modules/draggable-points.src.js",[],function(){})}); +//# sourceMappingURL=draggable-points.js.map \ No newline at end of file diff --git a/highcharts/modules/draggable-points.js.map b/highcharts/modules/draggable-points.js.map new file mode 100644 index 0000000..e77511f --- /dev/null +++ b/highcharts/modules/draggable-points.js.map @@ -0,0 +1 @@ +{"version":3,"file":"draggable-points.js.map","lineCount":39,"mappings":"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","sources":["draggable-points.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","Point","U","flipResizeSide","side","left","right","top","bottom","isSeriesDraggable","series","props","i","objectEach","dragDropProps","val","optionName","push","length","options","dragDrop","isChartDraggable","chart","hasCartesianSeries","polar","isPointMovable","point","seriesDragDropOptions","pointDragDropOptions","hasMovableX","hasMovableY","p","axis","move","draggableX","draggableY","yAxis","xAxis","getNormalizedEvent","e","chartX","chartY","pointer","normalize","addEvents","el","types","removeFuncs","map","type","addEvent","forEach","hasDraggedPastSensitivity","sensitivity","orig","dragDropData","origin","oldX","oldY","newX","newY","Math","sqrt","distance","getPositionSnapshot","points","guideBox","res","x","attr","y","width","height","pointProps","key","toPixels","horiz","id","getGroupedPoints","groupKey","groupBy","isSeriesBoosting","data","pointOptions","init","pointClass","index","filter","comparePoint","initDragDrop","groupedPoints","pick","liveRedraw","dragGuideBox","getGuideBox","setGuideBoxState","add","group","isDragging","getNewPoints","newPos","merge","updateProps","resizeProp","updateProp","hashmap","resize","newValues","getDropValues","updatePoints","animate","newPoints","animOptions","duration","animation","isDragDropAnimating","newPoint","update","redraw","setTimeout","hoverPoint","dragHandles","showDragHandles","mouseOut","draggedPastSensitivity","isHoveringHandle","hideDragHandles","countProps","count","Object","call","getFirstProp","mouseMove","zoomOrPanKeyPressed","numNewPoints","seriesDragDropOpts","preventDefault","dragSensitivity","defaultDragSensitivity","firePointEvent","newPointId","dX","dY","oldDx","inverted","resizeSide","beforeResize","reversed","prevdX","prevdY","updateSide","resizeAttrs","rect","max","translate","mouseUp","cancelClick","destroy","addDragDropEvents","container","doc","dragPoint","dragDropOptions","hasDraggedAnnotation","mouseIsDown","unbindDragDropMouseUp","hasAddedDragDropEvents","clamp","seriesTypes","horizHandleFormatter","shapeArgs","graphic","getBBox","r","centerY","lineDragDropProps","line","prototype","flags","columnDragDropProps","column","pointVals","threshold","translatedThreshold","round","diff","flipSide","handlePositioner","bBox","handleFormatter","radius","centerX","bullet","target","targetGraphic","barX","columnrange","low","propValidate","high","boxplot","lowPlot","q1","q1Plot","median","q3","q3Plot","highPlot","ohlc","plotLow","open","close","plotHigh","plotOpen","plotClose","arearange","columnrangeDragDropProps","arearangeHandleFormatter","lowerGraphic","upperGraphic","waterfall","isSum","isIntermediateSum","xrange","xrangeHandlePositioner","xProp","offsetY","columnMetrics","offset","len","xrangeDragDropProps","x2","gantt","start","validateIndividualDrag","milestone","end","defaultGuideBoxOptions","className","lineWidth","lineColor","color","cursor","zIndex","defaultDragHandleOptions","Chart","H.Chart.prototype.setGuideBoxState","state","guideBoxOptions","stateOptions","stroke","strokeWidth","fill","css","pointerEvents","Point.prototype.getDropValues","result","pointOrigin","updateSingleProp","oldVal","toValue","toUpperCase","defaultPrecision","direction","toLowerCase","categories","precision","min","Infinity","newVal","Series","H.Series.prototype.getGuideBox","minX","maxX","minY","maxY","changed","renderer","g","Point.prototype.showDragHandles","handleOptions","dragHandle","handleAttrs","pathFormatter","positioner","validate","markerGroup","pos","d","handle","element","stopPropagation","H.Chart.prototype.hideDragHandles","is3d","H.Chart.prototype.zoomOrPanKeyPressed","chartOptions","userOptions","panKey","zoomKey"]} \ No newline at end of file diff --git a/highcharts/modules/draggable-points.src.js b/highcharts/modules/draggable-points.src.js new file mode 100644 index 0000000..34a2c58 --- /dev/null +++ b/highcharts/modules/draggable-points.src.js @@ -0,0 +1,2387 @@ +/** + * @license Highcharts JS v8.2.0 (2020-08-20) + * + * (c) 2009-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/draggable-points', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'Extensions/DraggablePoints.js', [_modules['Core/Globals.js'], _modules['Core/Series/Point.js'], _modules['Core/Utilities.js']], function (H, Point, U) { + /* * + * + * (c) 2009-2020 Highsoft AS + * + * Authors: Øystein Moseng, Torstein Hønsi, Jon A. Nygård + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + clamp = U.clamp, + merge = U.merge, + objectEach = U.objectEach, + pick = U.pick; + /** + * Current drag and drop position. + * + * @interface Highcharts.DragDropPositionObject + */ /** + * Chart x position + * @name Highcharts.DragDropPositionObject#chartX + * @type {number} + */ /** + * Chart y position + * @name Highcharts.DragDropPositionObject#chartY + * @type {number} + */ /** + * Drag and drop guide box. + * @name Highcharts.DragDropPositionObject#guideBox + * @type {Highcharts.BBoxObject|undefined} + */ /** + * Updated point data. + * @name Highcharts.DragDropPositionObject#points + * @type {Highcharts.Dictionary>} + */ /** + * Delta of previous x position. + * @name Highcharts.DragDropPositionObject#prevdX + * @type {number|undefined} + */ /** + * Delta of previous y position. + * @name Highcharts.DragDropPositionObject#prevdY + * @type {number|undefined} + */ + /** + * Function callback to execute while series points are dragged. Return false to + * stop the default drag action. + * + * @callback Highcharts.PointDragCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {Highcharts.PointDragEventObject} event + * Event arguments. + */ + /** + * Contains information about a points new values. + * + * @interface Highcharts.PointDragDropObject + */ /** + * New values. + * @name Highcharts.PointDragDropObject#newValues + * @type {Highcharts.Dictionary} + */ /** + * Updated point. + * @name Highcharts.PointDragDropObject#point + * @type {Highcharts.Point} + */ + /** + * Contains common information for a drag event on series points. + * + * @interface Highcharts.PointDragEventObject + */ /** + * New point after drag if only a single one. + * @name Highcharts.PointDropEventObject#newPoint + * @type {Highcharts.PointDragDropObject|undefined} + */ /** + * New point id after drag if only a single one. + * @name Highcharts.PointDropEventObject#newPointId + * @type {string|undefined} + */ /** + * New points during drag. + * @name Highcharts.PointDragEventObject#newPoints + * @type {Highcharts.Dictionary} + */ /** + * Original data. + * @name Highcharts.PointDragEventObject#origin + * @type {Highcharts.DragDropPositionObject} + */ /** + * Prevent default drag action. + * @name Highcharts.PointDragEventObject#preventDefault + * @type {Function} + */ /** + * Target point that caused the event. + * @name Highcharts.PointDragEventObject#target + * @type {Highcharts.Point} + */ /** + * Event type. + * @name Highcharts.PointDragEventObject#type + * @type {"drag"} + */ + /** + * Function callback to execute when a series point is dragged. + * + * @callback Highcharts.PointDragStartCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {Highcharts.PointDragStartEventObject} event + * Event arguments. + */ + /** + * Contains common information for a drag event on series point. + * + * @interface Highcharts.PointDragStartEventObject + * @extends global.MouseEvent + */ /** + * Data property being dragged. + * @name Highcharts.PointDragStartEventObject#updateProp + * @type {string|undefined} + */ + /** + * Function callback to execute when series points are dropped. + * + * @callback Highcharts.PointDropCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {Highcharts.PointDropEventObject} event + * Event arguments. + */ + /** + * Contains common information for a drop event on series points. + * + * @interface Highcharts.PointDropEventObject + */ /** + * New point after drop if only a single one. + * @name Highcharts.PointDropEventObject#newPoint + * @type {Highcharts.PointDragDropObject|undefined} + */ /** + * New point id after drop if only a single one. + * @name Highcharts.PointDropEventObject#newPointId + * @type {string|undefined} + */ /** + * New points after drop. + * @name Highcharts.PointDropEventObject#newPoints + * @type {Highcharts.Dictionary} + */ /** + * Number of new points. + * @name Highcharts.PointDropEventObject#numNewPoints + * @type {number} + */ /** + * Original data. + * @name Highcharts.PointDropEventObject#origin + * @type {Highcharts.DragDropPositionObject} + */ /** + * Prevent default drop action. + * @name Highcharts.PointDropEventObject#preventDefault + * @type {Function} + */ /** + * Target point that caused the event. + * @name Highcharts.PointDropEventObject#target + * @type {Highcharts.Point} + */ /** + * Event type. + * @name Highcharts.PointDropEventObject#type + * @type {"drop"} + */ + ''; // detaches doclets above + var seriesTypes = H.seriesTypes; + /** + * Flip a side property, used with resizeRect. If input side is "left", return + * "right" etc. + * + * @private + * @function flipResizeSide + * + * @param {string} side + * Side prop to flip. Can be `left`, `right`, `top` or `bottom`. + * + * @return {"bottom"|"left"|"right"|"top"|undefined} + * The flipped side. + */ + function flipResizeSide(side) { + return { + left: 'right', + right: 'left', + top: 'bottom', + bottom: 'top' + }[side]; + } + /* @todo + Add drag/drop support to specific data props for different series types. + + The dragDrop.draggableX/Y user options on series enable/disable all of these per + irection unless they are specifically set in options using + dragDrop.{optionName}. If the prop does not specify an optionName here, it can + only be enabled/disabled by the user with draggableX/Y. + + Supported options for each prop: + optionName: User option in series.dragDrop that enables/disables + dragging this prop. + axis: Can be 'x' or 'y'. Whether this prop is linked to x or y axis. + move: Whether or not this prop should be updated when moving points. + resize: Whether or not to draw a drag handle and allow user to drag and + update this prop by itself. + beforeResize: Hook to perform tasks before a resize is made. Gets + the guide box, the new points values, and the point as args. + resizeSide: Which side of the guide box to resize when dragging the + handle. Can be "left", "right", "top", "bottom". Chart.inverted is + handled automatically. Can also be a function, taking the new point + values as parameter, as well as the point, and returning a string + with the side. + propValidate: Function that takes the prop value and the point as + arguments, and returns true if the prop value is valid, false if + not. It is used to prevent e.g. resizing "low" above "high". + handlePositioner: For resizeable props, return 0,0 in SVG plot coords of + where to place the dragHandle. Gets point as argument. Should return + object with x and y properties. + handleFormatter: For resizeable props, return the path of the drag + handle as an SVG path array. Gets the point as argument. The handle + is translated according to handlePositioner. + handleOptions: Options to merge with the default handle options. + + TODO: + - It makes sense to have support for resizing the size of bubbles and + e.g variwide columns. This requires us to support dragging along a + z-axis, somehow computing a relative value from old to new pixel + size. + - Moving maps could be useful, although we would have to compute new + point.path values in order to do it properly (using SVG translate + is easier, but won't update the data). + */ + // 90deg rotated column handle path, used in multiple series types + var horizHandleFormatter = function (point) { + var shapeArgs = point.shapeArgs || point.graphic.getBBox(), + top = shapeArgs.r || 0, // Rounding of bar corners + bottom = shapeArgs.height - top, + centerY = shapeArgs.height / 2; + return [ + // Top wick + ['M', 0, top], + ['L', 0, centerY - 5], + // Circle + ['A', 1, 1, 0, 0, 0, 0, centerY + 5], + ['A', 1, 1, 0, 0, 0, 0, centerY - 5], + // Bottom wick + ['M', 0, centerY + 5], + ['L', 0, bottom] + ]; + }; + // Line series - only draggableX/Y, no drag handles + var lineDragDropProps = seriesTypes.line.prototype.dragDropProps = { + x: { + axis: 'x', + move: true + }, + y: { + axis: 'y', + move: true + } + }; + // Flag series - same as line/scatter + if (seriesTypes.flags) { + seriesTypes.flags.prototype.dragDropProps = lineDragDropProps; + } + // Column series - x can be moved, y can only be resized. Note extra + // functionality for handling upside down columns (below threshold). + var columnDragDropProps = seriesTypes.column.prototype.dragDropProps = { + x: { + axis: 'x', + move: true + }, + y: { + axis: 'y', + move: false, + resize: true, + // Force guideBox start coordinates + beforeResize: function (guideBox, + pointVals, + point) { + // We need to ensure that guideBox always starts at threshold. + // We flip whether or not we update the top or bottom of the guide + // box at threshold, but if we drag the mouse fast, the top has not + // reached threshold before we cross over and update the bottom. + var threshold = point.series.translatedThreshold, + y = guideBox.attr('y'), + height, + diff; + if (pointVals.y >= point.series.options.threshold || 0) { + // Above threshold - always set height to hit the threshold + height = guideBox.attr('height'); + diff = threshold ? + threshold - (y + height) : + 0; + guideBox.attr({ + height: Math.max(0, Math.round(height + diff)) + }); + } + else { + // Below - always set y to start at threshold + guideBox.attr({ + y: Math.round(y + (threshold ? threshold - y : 0)) + }); + } + }, + // Flip the side of the resize handle if column is below threshold. + // Make sure we remove the handle on the other side. + resizeSide: function (pointVals, point) { + var chart = point.series.chart, + dragHandles = chart.dragHandles, + side = pointVals.y >= (point.series.options.threshold || 0) ? + 'top' : 'bottom', + flipSide = flipResizeSide(side); + // Force remove handle on other side + if (dragHandles[flipSide]) { + dragHandles[flipSide].destroy(); + delete dragHandles[flipSide]; + } + return side; + }, + // Position handle at bottom if column is below threshold + handlePositioner: function (point) { + var bBox = point.shapeArgs || point.graphic.getBBox(); + return { + x: bBox.x, + y: point.y >= (point.series.options.threshold || 0) ? + bBox.y : bBox.y + bBox.height + }; + }, + // Horizontal handle + handleFormatter: function (point) { + var shapeArgs = point.shapeArgs || {}, + radius = shapeArgs.r || 0, // Rounding of bar corners + width = shapeArgs.width || 0, + centerX = width / 2; + return [ + // Left wick + ['M', radius, 0], + ['L', centerX - 5, 0], + // Circle + ['A', 1, 1, 0, 0, 0, centerX + 5, 0], + ['A', 1, 1, 0, 0, 0, centerX - 5, 0], + // Right wick + ['M', centerX + 5, 0], + ['L', width - radius, 0] + ]; + } + } + }; + // Bullet graph, x/y same as column, but also allow target to be dragged. + if (seriesTypes.bullet) { + seriesTypes.bullet.prototype.dragDropProps = { + x: columnDragDropProps.x, + y: columnDragDropProps.y, + /** + * Allow target value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.bullet.dragDrop.draggableTarget + */ + target: { + optionName: 'draggableTarget', + axis: 'y', + move: true, + resize: true, + resizeSide: 'top', + handlePositioner: function (point) { + var bBox = point.targetGraphic.getBBox(); + return { + x: point.barX, + y: bBox.y + bBox.height / 2 + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter + } + }; + } + // Columnrange series - move x, resize or move low/high + if (seriesTypes.columnrange) { + seriesTypes.columnrange.prototype.dragDropProps = { + x: { + axis: 'x', + move: true + }, + /** + * Allow low value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.columnrange.dragDrop.draggableLow + */ + low: { + optionName: 'draggableLow', + axis: 'y', + move: true, + resize: true, + resizeSide: 'bottom', + handlePositioner: function (point) { + var bBox = point.shapeArgs || point.graphic.getBBox(); + return { + x: bBox.x, + y: bBox.y + bBox.height + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val <= point.high; + } + }, + /** + * Allow high value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.columnrange.dragDrop.draggableHigh + */ + high: { + optionName: 'draggableHigh', + axis: 'y', + move: true, + resize: true, + resizeSide: 'top', + handlePositioner: function (point) { + var bBox = point.shapeArgs || point.graphic.getBBox(); + return { + x: bBox.x, + y: bBox.y + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val >= point.low; + } + } + }; + } + // Boxplot series - move x, resize or move low/q1/q3/high + if (seriesTypes.boxplot) { + seriesTypes.boxplot.prototype.dragDropProps = { + x: columnDragDropProps.x, + /** + * Allow low value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.boxplot.dragDrop.draggableLow + */ + low: { + optionName: 'draggableLow', + axis: 'y', + move: true, + resize: true, + resizeSide: 'bottom', + handlePositioner: function (point) { + return { + x: point.shapeArgs.x, + y: point.lowPlot + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val <= point.q1; + } + }, + /** + * Allow Q1 value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.boxplot.dragDrop.draggableQ1 + */ + q1: { + optionName: 'draggableQ1', + axis: 'y', + move: true, + resize: true, + resizeSide: 'bottom', + handlePositioner: function (point) { + return { + x: point.shapeArgs.x, + y: point.q1Plot + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val <= point.median && val >= point.low; + } + }, + median: { + // Median can not be dragged individually, just move the whole + // point for this. + axis: 'y', + move: true + }, + /** + * Allow Q3 value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.boxplot.dragDrop.draggableQ3 + */ + q3: { + optionName: 'draggableQ3', + axis: 'y', + move: true, + resize: true, + resizeSide: 'top', + handlePositioner: function (point) { + return { + x: point.shapeArgs.x, + y: point.q3Plot + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val <= point.high && val >= point.median; + } + }, + /** + * Allow high value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.boxplot.dragDrop.draggableHigh + */ + high: { + optionName: 'draggableHigh', + axis: 'y', + move: true, + resize: true, + resizeSide: 'top', + handlePositioner: function (point) { + return { + x: point.shapeArgs.x, + y: point.highPlot + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val >= point.q3; + } + } + }; + } + // OHLC series - move x, resize or move open/high/low/close + if (seriesTypes.ohlc) { + seriesTypes.ohlc.prototype.dragDropProps = { + x: columnDragDropProps.x, + /** + * Allow low value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.ohlc.dragDrop.draggableLow + */ + low: { + optionName: 'draggableLow', + axis: 'y', + move: true, + resize: true, + resizeSide: 'bottom', + handlePositioner: function (point) { + return { + x: point.shapeArgs.x, + y: point.plotLow + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val <= point.open && val <= point.close; + } + }, + /** + * Allow high value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.ohlc.dragDrop.draggableHigh + */ + high: { + optionName: 'draggableHigh', + axis: 'y', + move: true, + resize: true, + resizeSide: 'top', + handlePositioner: function (point) { + return { + x: point.shapeArgs.x, + y: point.plotHigh + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val >= point.open && val >= point.close; + } + }, + /** + * Allow open value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.ohlc.dragDrop.draggableOpen + */ + open: { + optionName: 'draggableOpen', + axis: 'y', + move: true, + resize: true, + resizeSide: function (point) { + return point.open >= point.close ? 'top' : 'bottom'; + }, + handlePositioner: function (point) { + return { + x: point.shapeArgs.x, + y: point.plotOpen + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val <= point.high && val >= point.low; + } + }, + /** + * Allow close value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.ohlc.dragDrop.draggableClose + */ + close: { + optionName: 'draggableClose', + axis: 'y', + move: true, + resize: true, + resizeSide: function (point) { + return point.open >= point.close ? 'bottom' : 'top'; + }, + handlePositioner: function (point) { + return { + x: point.shapeArgs.x, + y: point.plotClose + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val <= point.high && val >= point.low; + } + } + }; + } + // Arearange series - move x, resize or move low/high + if (seriesTypes.arearange) { + var columnrangeDragDropProps = seriesTypes.columnrange.prototype.dragDropProps, + // Use a circle covering the marker as drag handle + arearangeHandleFormatter = function (point) { + var radius = point.graphic ? + point.graphic.getBBox().width / 2 + 1 : + 4; + return [ + ['M', 0 - radius, 0], + ['a', radius, radius, 0, 1, 0, radius * 2, 0], + ['a', radius, radius, 0, 1, 0, radius * -2, 0] + ]; + }; + seriesTypes.arearange.prototype.dragDropProps = { + x: columnrangeDragDropProps.x, + /** + * Allow low value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.arearange.dragDrop.draggableLow + */ + low: { + optionName: 'draggableLow', + axis: 'y', + move: true, + resize: true, + resizeSide: 'bottom', + handlePositioner: function (point) { + var bBox = point.lowerGraphic && point.lowerGraphic.getBBox(); + return bBox ? { + x: bBox.x + bBox.width / 2, + y: bBox.y + bBox.height / 2 + } : { x: -999, y: -999 }; + }, + handleFormatter: arearangeHandleFormatter, + propValidate: columnrangeDragDropProps.low.propValidate + }, + /** + * Allow high value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.arearange.dragDrop.draggableHigh + */ + high: { + optionName: 'draggableHigh', + axis: 'y', + move: true, + resize: true, + resizeSide: 'top', + handlePositioner: function (point) { + var bBox = point.upperGraphic && point.upperGraphic.getBBox(); + return bBox ? { + x: bBox.x + bBox.width / 2, + y: bBox.y + bBox.height / 2 + } : { x: -999, y: -999 }; + }, + handleFormatter: arearangeHandleFormatter, + propValidate: columnrangeDragDropProps.high.propValidate + } + }; + } + // Waterfall - mostly as column, but don't show drag handles for sum points + if (seriesTypes.waterfall) { + seriesTypes.waterfall.prototype.dragDropProps = { + x: columnDragDropProps.x, + y: merge(columnDragDropProps.y, { + handleFormatter: function (point) { + return point.isSum || point.isIntermediateSum ? null : + columnDragDropProps.y.handleFormatter(point); + } + }) + }; + } + // Xrange - resize/move x/x2, and move y + if (seriesTypes.xrange) { + // Handle positioner logic is the same for x and x2 apart from the + // x value. shapeArgs does not take yAxis reversed etc into account, so we + // use axis.toPixels to handle positioning. + var xrangeHandlePositioner = function (point, + xProp) { + var series = point.series, + xAxis = series.xAxis, + yAxis = series.yAxis, + inverted = series.chart.inverted, + // Using toPixels handles axis.reversed, but doesn't take + // chart.inverted into account. + newX = xAxis.toPixels(point[xProp], + true), + newY = yAxis.toPixels(point.y, + true), + offsetY = series.columnMetrics ? series.columnMetrics.offset : + -point.shapeArgs.height / 2; + // Handle chart inverted + if (inverted) { + newX = xAxis.len - newX; + newY = yAxis.len - newY; + } + newY += offsetY; // (#12872) + return { + x: Math.round(newX), + y: Math.round(newY) + }; + }, xrangeDragDropProps = seriesTypes.xrange.prototype.dragDropProps = { + y: { + axis: 'y', + move: true + }, + /** + * Allow x value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.xrange.dragDrop.draggableX1 + */ + x: { + optionName: 'draggableX1', + axis: 'x', + move: true, + resize: true, + resizeSide: 'left', + handlePositioner: function (point) { + return xrangeHandlePositioner(point, 'x'); + }, + handleFormatter: horizHandleFormatter, + propValidate: function (val, point) { + return val <= point.x2; + } + }, + /** + * Allow x2 value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.xrange.dragDrop.draggableX2 + */ + x2: { + optionName: 'draggableX2', + axis: 'x', + move: true, + resize: true, + resizeSide: 'right', + handlePositioner: function (point) { + return xrangeHandlePositioner(point, 'x2'); + }, + handleFormatter: horizHandleFormatter, + propValidate: function (val, point) { + return val >= point.x; + } + } + }; + // Gantt - same as xrange, but with aliases + if (seriesTypes.gantt) { + seriesTypes.gantt.prototype.dragDropProps = { + y: xrangeDragDropProps.y, + /** + * Allow start value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.gantt.dragDrop.draggableStart + */ + start: merge(xrangeDragDropProps.x, { + optionName: 'draggableStart', + // Do not allow individual drag handles for milestones + validateIndividualDrag: function (point) { + return !point.milestone; + } + }), + /** + * Allow end value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.gantt.dragDrop.draggableEnd + */ + end: merge(xrangeDragDropProps.x2, { + optionName: 'draggableEnd', + // Do not allow individual drag handles for milestones + validateIndividualDrag: function (point) { + return !point.milestone; + } + }) + }; + } + } + // Don't support certain series types + [ + 'gauge', + 'pie', + 'sunburst', + 'wordcloud', + 'sankey', + 'histogram', + 'pareto', + 'vector', + 'windbarb', + 'treemap', + 'bellcurve', + 'sma', + 'map', + 'mapline' + ].forEach( + /** + * @private + * @param {string} type + * Unsupported series type + * @return {void} + */ + function (type) { + if (seriesTypes[type]) { + seriesTypes[type].prototype.dragDropProps = null; + } + }); + /** + * The draggable-points module allows points to be moved around or modified in + * the chart. In addition to the options mentioned under the `dragDrop` API + * structure, the module fires three events, + * [point.dragStart](plotOptions.series.point.events.dragStart), + * [point.drag](plotOptions.series.point.events.drag) and + * [point.drop](plotOptions.series.point.events.drop). + * + * @sample highcharts/dragdrop/resize-column + * Draggable column and line series + * @sample highcharts/dragdrop/bar-series + * Draggable bar + * @sample highcharts/dragdrop/drag-bubble + * Draggable bubbles + * @sample highcharts/dragdrop/drag-xrange + * Draggable X range series + * + * @declare Highcharts.SeriesDragDropOptionsObject + * @since 6.2.0 + * @requires modules/draggable-points + * @apioption plotOptions.series.dragDrop + */ + /** + * The amount of pixels to drag the pointer before it counts as a drag + * operation. This prevents drag/drop to fire when just clicking or selecting + * points. + * + * @type {number} + * @default 2 + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragSensitivity + * + * @private + */ + var defaultDragSensitivity = 2; + /** + * Style options for the guide box. The guide box has one state by default, the + * `default` state. + * + * @type {Highcharts.Dictionary} + * @since 6.2.0 + * @optionparent plotOptions.series.dragDrop.guideBox + * + * @private + */ + var defaultGuideBoxOptions = { + /** + * Style options for the guide box default state. + * + * @declare Highcharts.DragDropGuideBoxOptionsObject + * @since 6.2.0 + */ + 'default': { + /** + * CSS class name of the guide box in this state. Defaults to + * `highcharts-drag-box-default`. + * + * @since 6.2.0 + */ + className: 'highcharts-drag-box-default', + /** + * Width of the line around the guide box. + * + * @since 6.2.0 + */ + lineWidth: 1, + /** + * Color of the border around the guide box. + * + * @type {Highcharts.ColorString} + * @since 6.2.0 + */ + lineColor: '#888', + /** + * Guide box fill color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 6.2.0 + */ + color: 'rgba(0, 0, 0, 0.1)', + /** + * Guide box cursor. + * + * @since 6.2.0 + */ + cursor: 'move', + /** + * Guide box zIndex. + * + * @since 6.2.0 + */ + zIndex: 900 + } + }; + /** + * Options for the drag handles. + * + * @declare Highcharts.DragDropHandleOptionsObject + * @since 6.2.0 + * @optionparent plotOptions.series.dragDrop.dragHandle + * + * @private + */ + var defaultDragHandleOptions = { + /** + * Function to define the SVG path to use for the drag handles. Takes the + * point as argument. Should return an SVG path in array format. The SVG + * path is automatically positioned on the point. + * + * @type {Function} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragHandle.pathFormatter + */ + // pathFormatter: null, + /** + * The mouse cursor to use for the drag handles. By default this is + * intelligently switching between `ew-resize` and `ns-resize` depending on + * the direction the point is being dragged. + * + * @type {string} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragHandle.cursor + */ + // cursor: null, + /** + * The class name of the drag handles. Defaults to `highcharts-drag-handle`. + * + * @since 6.2.0 + */ + className: 'highcharts-drag-handle', + /** + * The fill color of the drag handles. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 6.2.0 + */ + color: '#fff', + /** + * The line color of the drag handles. + * + * @type {Highcharts.ColorString} + * @since 6.2.0 + */ + lineColor: 'rgba(0, 0, 0, 0.6)', + /** + * The line width for the drag handles. + * + * @since 6.2.0 + */ + lineWidth: 1, + /** + * The z index for the drag handles. + * + * @since 6.2.0 + */ + zIndex: 901 + }; + /** + * Set the minimum X value the points can be moved to. + * + * @sample {gantt} gantt/dragdrop/drag-gantt + * Limit dragging + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * Limit dragging + * + * @type {number} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragMinX + */ + /** + * Set the maximum X value the points can be moved to. + * + * @sample {gantt} gantt/dragdrop/drag-gantt + * Limit dragging + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * Limit dragging + * + * @type {number} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragMaxX + */ + /** + * Set the minimum Y value the points can be moved to. + * + * @sample {gantt} gantt/dragdrop/drag-gantt + * Limit dragging + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * Limit dragging + * + * @type {number} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragMinY + */ + /** + * Set the maximum Y value the points can be moved to. + * + * @sample {gantt} gantt/dragdrop/drag-gantt + * Limit dragging + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * Limit dragging + * + * @type {number} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragMaxY + */ + /** + * The X precision value to drag to for this series. Set to 0 to disable. By + * default this is disabled, except for category axes, where the default is 1. + * + * @type {number} + * @default 0 + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragPrecisionX + */ + /** + * The Y precision value to drag to for this series. Set to 0 to disable. By + * default this is disabled, except for category axes, where the default is 1. + * + * @type {number} + * @default 0 + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragPrecisionY + */ + /** + * Enable dragging in the X dimension. + * + * @type {boolean} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.draggableX + */ + /** + * Enable dragging in the Y dimension. Note that this is not supported for + * TreeGrid axes (the default axis type in Gantt charts). + * + * @type {boolean} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.draggableY + */ + /** + * Group the points by a property. Points with the same property value will be + * grouped together when moving. + * + * @sample {gantt} gantt/dragdrop/drag-gantt + * Drag grouped points + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * Drag grouped points + * + * @type {string} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.groupBy + */ + /** + * Update points as they are dragged. If false, a guide box is drawn to + * illustrate the new point size. + * + * @sample {gantt} gantt/dragdrop/drag-gantt + * liveRedraw disabled + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * liveRedraw disabled + * + * @type {boolean} + * @default true + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.liveRedraw + */ + /** + * Set a key to hold when dragging to zoom the chart. This is useful to avoid + * zooming while moving points. Should be set different than + * [chart.panKey](#chart.panKey). + * + * @type {string} + * @since 6.2.0 + * @validvalue ["alt", "ctrl", "meta", "shift"] + * @requires modules/draggable-points + * @apioption chart.zoomKey + */ + /** + * Callback that fires when starting to drag a point. The mouse event object is + * passed in as an argument. If a drag handle is used, `e.updateProp` is set to + * the data property being dragged. The `this` context is the point. See + * [drag and drop options](plotOptions.series.dragDrop). + * + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * Drag events + * + * @type {Highcharts.PointDragStartCallbackFunction} + * @since 6.2.0 + * @requires modules/draggable-points + * @apioption plotOptions.series.point.events.dragStart + */ + /** + * Callback that fires while dragging a point. The mouse event is passed in as + * parameter. The original data can be accessed from `e.origin`, and the new + * point values can be accessed from `e.newPoints`. If there is only a single + * point being updated, it can be accessed from `e.newPoint` for simplicity, and + * its ID can be accessed from `e.newPointId`. The `this` context is the point + * being dragged. To stop the default drag action, return false. See + * [drag and drop options](plotOptions.series.dragDrop). + * + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * Drag events + * + * @type {Highcharts.PointDragCallbackFunction} + * @since 6.2.0 + * @requires modules/draggable-points + * @apioption plotOptions.series.point.events.drag + */ + /** + * Callback that fires when the point is dropped. The parameters passed are the + * same as for [drag](#plotOptions.series.point.events.drag). To stop the + * default drop action, return false. See + * [drag and drop options](plotOptions.series.dragDrop). + * + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * Drag events + * + * @type {Highcharts.PointDropCallbackFunction} + * @since 6.2.0 + * @requires modules/draggable-points + * @apioption plotOptions.series.point.events.drop + */ + /** + * Point specific options for the draggable-points module. Overrides options on + * `series.dragDrop`. + * + * @declare Highcharts.SeriesLineDataDragDropOptions + * @extends plotOptions.series.dragDrop + * @since 6.2.0 + * @requires modules/draggable-points + * @apioption series.line.data.dragDrop + */ + /** + * Utility function to test if a series is using drag/drop, looking at its + * options. + * + * @private + * @function isSeriesDraggable + * @param {Highcharts.Series} series + * The series to test. + * @return {boolean} + * True if the series is using drag/drop. + */ + function isSeriesDraggable(series) { + var props = ['draggableX', 'draggableY'], i; + // Add optionNames from dragDropProps to the array of props to check for + objectEach(series.dragDropProps, function (val) { + if (val.optionName) { + props.push(val.optionName); + } + }); + // Loop over all options we have that could enable dragDrop for this + // series. If any of them are truthy, this series is draggable. + i = props.length; + while (i--) { + if (series.options.dragDrop[props[i]]) { + return true; + } + } + } + /** + * Utility function to test if a chart should have drag/drop enabled, looking at + * its options. + * + * @private + * @function isChartDraggable + * @param {Highcharts.Chart} chart + * The chart to test. + * @return {boolean} + * True if the chart is drag/droppable. + */ + function isChartDraggable(chart) { + var i = chart.series ? chart.series.length : 0; + if (chart.hasCartesianSeries && !chart.polar) { + while (i--) { + if (chart.series[i].options.dragDrop && + isSeriesDraggable(chart.series[i])) { + return true; + } + } + } + } + /** + * Utility function to test if a point is movable (any of its props can be + * dragged by a move, not just individually). + * + * @private + * @function isPointMovable + * @param {Highcharts.Point} point + * The point to test. + * @return {boolean} + * True if the point is movable. + */ + function isPointMovable(point) { + var series = point.series, + seriesDragDropOptions = series.options.dragDrop || {}, + pointDragDropOptions = point.options && point.options.dragDrop, + updateProps = series.dragDropProps, + hasMovableX, + hasMovableY; + objectEach(updateProps, function (p) { + if (p.axis === 'x' && p.move) { + hasMovableX = true; + } + else if (p.axis === 'y' && p.move) { + hasMovableY = true; + } + }); + // We can only move the point if draggableX/Y is set, even if all the + // individual prop options are set. + return ((seriesDragDropOptions.draggableX && hasMovableX || + seriesDragDropOptions.draggableY && hasMovableY) && + !(pointDragDropOptions && + pointDragDropOptions.draggableX === false && + pointDragDropOptions.draggableY === false) && + series.yAxis && + series.xAxis); + } + /** + * Take a mouse/touch event and return the event object with chartX/chartY. + * + * @private + * @function getNormalizedEvent + * @param {global.PointerEvent} e + * The event to normalize. + * @param {Highcharts.Chart} chart + * The related chart. + * @return {Highcharts.PointerEventLObject} + * The normalized event. + */ + function getNormalizedEvent(e, chart) { + return (typeof e.chartX === 'undefined' || + typeof e.chartY === 'undefined' ? + chart.pointer.normalize(e) : + e); + } + /** + * Add multiple event listeners with the same handler to the same element. + * + * @private + * @function addEvents + * @param {T} el + * The element or object to add listeners to. + * @param {Array} types + * Array with the event types this handler should apply to. + * @param {Function|Highcharts.EventCallbackFunction} fn + * The function callback to execute when the events are fired. + * @param {Highcharts.EventOptionsObject} [options] + * Event options: + * - `order`: The order the event handler should be called. This opens + * for having one handler be called before another, independent of in + * which order they were added. + * @return {Function} + * A callback function to remove the added events. + * @template T + */ + function addEvents(el, types, fn, options) { + var removeFuncs = types.map(function (type) { + return addEvent(el, + type, + fn, + options); + }); + return function () { + removeFuncs.forEach(function (fn) { + fn(); + }); + }; + } + /** + * In mousemove events, check that we have dragged mouse further than the + * dragSensitivity before we call mouseMove handler. + * + * @private + * @function hasDraggedPastSensitivity + * + * @param {Highcharts.PointerEventObject} e + * Mouse move event to test. + * + * @param {Highcharts.Chart} chart + * Chart that has started dragging. + * + * @param {number} sensitivity + * Pixel sensitivity to test against. + * + * @return {boolean} + * True if the event is moved past sensitivity relative to the chart's + * drag origin. + */ + function hasDraggedPastSensitivity(e, chart, sensitivity) { + var orig = chart.dragDropData.origin, + oldX = orig.chartX, + oldY = orig.chartY, + newX = e.chartX, + newY = e.chartY, + distance = Math.sqrt((newX - oldX) * (newX - oldX) + + (newY - oldY) * (newY - oldY)); + return distance > sensitivity; + } + /** + * Get a snapshot of points, mouse position, and guide box dimensions + * + * @private + * @function getPositionSnapshot + * + * @param {Highcharts.PointerEventObject} e + * Mouse event with mouse position to snapshot. + * + * @param {Array} points + * Points to take snapshot of. We store the value of the data properties + * defined in each series' dragDropProps. + * + * @param {Highcharts.SVGElement} [guideBox] + * The guide box to take snapshot of. + * + * @return {object} + * Snapshot object. Point properties are placed in a hashmap with IDs as + * keys. + */ + function getPositionSnapshot(e, points, guideBox) { + var res = { + chartX: e.chartX, + chartY: e.chartY, + guideBox: guideBox && { + x: guideBox.attr('x'), + y: guideBox.attr('y'), + width: guideBox.attr('width'), + height: guideBox.attr('height') + }, + points: {} + }; + // Loop over the points and add their props + points.forEach(function (point) { + var pointProps = {}; + // Add all of the props defined in the series' dragDropProps to the + // snapshot + objectEach(point.series.dragDropProps, function (val, key) { + var axis = point.series[val.axis + 'Axis']; + pointProps[key] = point[key]; + // Record how far cursor was from the point when drag started. + // This later will be used to calculate new value according to the + // current position of the cursor. + // e.g. `high` value is translated to `highOffset` + pointProps[key + 'Offset'] = + // e.g. yAxis.toPixels(point.high), xAxis.toPixels(point.end) + axis.toPixels(point[key]) - + (axis.horiz ? e.chartX : e.chartY); + }); + pointProps.point = point; // Store reference to point + res.points[point.id] = pointProps; + }); + return res; + } + /** + * Get a list of points that are grouped with this point. If only one point is + * in the group, that point is returned by itself in an array. + * + * @private + * @function getGroupedPoints + * @param {Highcharts.Point} point + * Point to find group from. + * @return {Array} + * Array of points in this group. + */ + function getGroupedPoints(point) { + var series = point.series, + points = [], + groupKey = series.options.dragDrop.groupBy; + if (series.isSeriesBoosting) { // #11156 + series.options.data.forEach(function (pointOptions, i) { + points.push((new series.pointClass()).init(// eslint-disable-line new-cap + series, pointOptions)); + points[points.length - 1].index = i; + }); + } + else { + points = series.points; + } + return point.options[groupKey] ? + // If we have a grouping option, filter the points by that + points.filter(function (comparePoint) { + return comparePoint.options[groupKey] === + point.options[groupKey]; + }) : + // Otherwise return the point by itself only + [point]; + } + /** + * Resize a rect element on one side. The element is modified. + * + * @private + * @function resizeRect + * @param {Highcharts.SVGElement} rect + * Rect element to resize. + * @param {string} updateSide + * Which side of the rect to update. Can be `left`, `right`, `top` or + * `bottom`. + * @param {Highcharts.PositionObject} update + * Object with x and y properties, detailing how much to resize each + * dimension. + * @return {void} + */ + function resizeRect(rect, updateSide, update) { + var resizeAttrs; + switch (updateSide) { + case 'left': + resizeAttrs = { + x: rect.attr('x') + update.x, + width: Math.max(1, rect.attr('width') - update.x) + }; + break; + case 'right': + resizeAttrs = { + width: Math.max(1, rect.attr('width') + update.x) + }; + break; + case 'top': + resizeAttrs = { + y: rect.attr('y') + update.y, + height: Math.max(1, rect.attr('height') - update.y) + }; + break; + case 'bottom': + resizeAttrs = { + height: Math.max(1, rect.attr('height') + update.y) + }; + break; + default: + } + rect.attr(resizeAttrs); + } + /** + * Prepare chart.dragDropData with origin info, and show the guide box. + * + * @private + * @function initDragDrop + * @param {Highcharts.PointerEventObject} e + * Mouse event with original mouse position. + * @param {Highcharts.Point} point + * The point the dragging started on. + * @return {void} + */ + function initDragDrop(e, point) { + var groupedPoints = getGroupedPoints(point), + series = point.series, + chart = series.chart, + guideBox; + // If liveRedraw is disabled, show the guide box with the default state + if (!pick(series.options.dragDrop && series.options.dragDrop.liveRedraw, true)) { + chart.dragGuideBox = guideBox = series.getGuideBox(groupedPoints); + chart + .setGuideBoxState('default', series.options.dragDrop.guideBox) + .add(series.group); + } + // Store some data on the chart to pick up later + chart.dragDropData = { + origin: getPositionSnapshot(e, groupedPoints, guideBox), + point: point, + groupedPoints: groupedPoints, + isDragging: true + }; + } + /** + * Calculate new point options from points being dragged. + * + * @private + * @function getNewPoints + * + * @param {object} dragDropData + * A chart's dragDropData with drag/drop origin information, and info on + * which points are being dragged. + * + * @param {Highcharts.PointerEventObject} newPos + * Event with the new position of the mouse (chartX/Y properties). + * + * @return {Highchats.Dictionary} + * Hashmap with point.id mapped to an object with the original point + * reference, as well as the new data values. + */ + function getNewPoints(dragDropData, newPos) { + var point = dragDropData.point, + series = point.series, + options = merge(series.options.dragDrop, + point.options.dragDrop), + updateProps = {}, + resizeProp = dragDropData.updateProp, + hashmap = {}; + // Go through the data props that can be updated on this series and find out + // which ones we want to update. + objectEach(point.series.dragDropProps, function (val, key) { + // If we are resizing, skip if this key is not the correct one or it + // is not resizable. + if (resizeProp && (resizeProp !== key || + !val.resize || + val.optionName && options[val.optionName] === false)) { + return; + } + // If we are resizing, we now know it is good. If we are moving, check + // that moving along this axis is enabled, and the prop is movable. + // If this prop is enabled, add it to be updated. + if (resizeProp || (val.move && + (val.axis === 'x' && options.draggableX || + val.axis === 'y' && options.draggableY))) { + updateProps[key] = val; + } + }); + // Go through the points to be updated and get new options for each of them + ( + // If resizing).forEach(only update the point we are resizing + resizeProp ? + [point] : + dragDropData.groupedPoints).forEach(function (p) { + hashmap[p.id] = { + point: p, + newValues: p.getDropValues(dragDropData.origin, newPos, updateProps) + }; + }); + return hashmap; + } + /** + * Update the points in a chart from dragDropData.newPoints. + * + * @private + * @function updatePoints + * @param {Highcharts.Chart} chart + * A chart with dragDropData.newPoints. + * @param {boolean} [animate=true] + * Animate updating points? + */ + function updatePoints(chart, animate) { + var newPoints = chart.dragDropData.newPoints, + animOptions = animate === false ? false : merge({ + duration: 400 // 400 is the default in animate + }, + chart.options.chart.animation); + chart.isDragDropAnimating = true; + // Update the points + objectEach(newPoints, function (newPoint) { + newPoint.point.update(newPoint.newValues, false); + }); + chart.redraw(animOptions); + // Clear the isAnimating flag after animation duration is complete. + // The complete handler for animation seems to have bugs at this time, so + // we have to use a timeout instead. + setTimeout(function () { + delete chart.isDragDropAnimating; + if (chart.hoverPoint && !chart.dragHandles) { + chart.hoverPoint.showDragHandles(); + } + }, animOptions.duration); + } + /** + * Resize the guide box according to point options and a difference in mouse + * positions. Handles reversed axes. + * + * @private + * @function resizeGuideBox + * @param {Highcharts.Point} point + * The point that is being resized. + * @param {number} dX + * Difference in X position. + * @param {number} dY + * Difference in Y position. + */ + function resizeGuideBox(point, dX, dY) { + var series = point.series, + chart = series.chart, + dragDropData = chart.dragDropData, + resizeSide, + newPoint, + resizeProp = series.dragDropProps[dragDropData.updateProp]; + // dragDropProp.resizeSide holds info on which side to resize. + newPoint = dragDropData.newPoints[point.id].newValues; + resizeSide = typeof resizeProp.resizeSide === 'function' ? + resizeProp.resizeSide(newPoint, point) : resizeProp.resizeSide; + // Call resize hook if it is defined + if (resizeProp.beforeResize) { + resizeProp.beforeResize(chart.dragGuideBox, newPoint, point); + } + // Do the resize + resizeRect(chart.dragGuideBox, resizeProp.axis === 'x' && series.xAxis.reversed || + resizeProp.axis === 'y' && series.yAxis.reversed ? + flipResizeSide(resizeSide) : resizeSide, { + x: resizeProp.axis === 'x' ? + dX - (dragDropData.origin.prevdX || 0) : 0, + y: resizeProp.axis === 'y' ? + dY - (dragDropData.origin.prevdY || 0) : 0 + }); + } + /** + * Default mouse move handler while dragging. Handles updating points or guide + * box. + * + * @private + * @function dragMove + * @param {Highcharts.PointerEventObject} e + * The mouse move event. + * @param {Highcharts.Point} point + * The point that is dragged. + */ + function dragMove(e, point) { + var series = point.series, + chart = series.chart, + data = chart.dragDropData, + options = merge(series.options.dragDrop, + point.options.dragDrop), + draggableX = options.draggableX, + draggableY = options.draggableY, + origin = data.origin, + dX = e.chartX - origin.chartX, + dY = e.chartY - origin.chartY, + oldDx = dX, + updateProp = data.updateProp; + // Handle inverted + if (chart.inverted) { + dX = -dY; + dY = -oldDx; + } + // If we have liveRedraw enabled, update the points immediately. Otherwise + // update the guideBox. + if (pick(options.liveRedraw, true)) { + updatePoints(chart, false); + // Update drag handles + point.showDragHandles(); + } + else { + // No live redraw, update guide box + if (updateProp) { + // We are resizing, so resize the guide box + resizeGuideBox(point, dX, dY); + } + else { + // We are moving, so move the guide box + chart.dragGuideBox.translate(draggableX ? dX : 0, draggableY ? dY : 0); + } + } + // Update stored previous dX/Y + origin.prevdX = dX; + origin.prevdY = dY; + } + /** + * Set the state of the guide box. + * + * @private + * @function Highcharts.Chart#setGuideBoxState + * @param {string} state + * The state to set the guide box to. + * @param {Highcharts.Dictionary} [options] + * Additional overall guideBox options to consider. + * @return {Highcharts.SVGElement} + * The modified guide box. + */ + H.Chart.prototype.setGuideBoxState = function (state, options) { + var guideBox = this.dragGuideBox, + guideBoxOptions = merge(defaultGuideBoxOptions, + options), + stateOptions = merge(guideBoxOptions['default'], // eslint-disable-line dot-notation + guideBoxOptions[state]); + return guideBox + .attr({ + className: stateOptions.className, + stroke: stateOptions.lineColor, + strokeWidth: stateOptions.lineWidth, + fill: stateOptions.color, + cursor: stateOptions.cursor, + zIndex: stateOptions.zIndex + }) + // Use pointerEvents 'none' to avoid capturing the click event + .css({ pointerEvents: 'none' }); + }; + /** + * Get updated point values when dragging a point. + * + * @private + * @function Highcharts.Point#getDropValues + * + * @param {object} origin + * Mouse position (chartX/Y) and point props at current data values. + * Point props should be organized per point.id in a hashmap. + * + * @param {Highcharts.PointerEventObject} newPos + * New mouse position (chartX/Y). + * + * @param {Highcharts.Dictionary>>} updateProps + * Point props to modify. Map of prop objects where each key refers to + * the prop, and the value is an object with an axis property. Example: + * { + * x: { + * axis: 'x' + * }, + * x2: { + * axis: 'x' + * } + * } + * + * @return {Highcharts.Dictionary} + * An object with updated data values. + */ + Point.prototype.getDropValues = function (origin, newPos, updateProps) { + var point = this, + series = point.series, + options = merge(series.options.dragDrop, + point.options.dragDrop), + result = {}, + updateSingleProp, + pointOrigin = origin.points[point.id]; + // Find out if we only have one prop to update + for (var key in updateProps) { + if (Object.hasOwnProperty.call(updateProps, key)) { + if (typeof updateSingleProp !== 'undefined') { + updateSingleProp = false; + break; + } + updateSingleProp = true; + } + } + /** + * Utility function to apply precision and limit a value within the + * draggable range. + * @private + * @param {number} val + * Value to limit + * @param {string} direction + * Axis direction + * @return {number} + * Limited value + */ + var limitToRange = function (val, direction) { + var defaultPrecision = series[direction.toLowerCase() + 'Axis'] + .categories ? 1 : 0, precision = pick(options['dragPrecision' + direction], defaultPrecision), min = pick(options['dragMin' + direction], -Infinity), max = pick(options['dragMax' + direction], Infinity), res = val; + if (precision) { + res = Math.round(res / precision) * precision; + } + return clamp(res, min, max); + }; + // Assign new value to property. Adds dX/YValue to the old value, limiting + // it within min/max ranges. + objectEach(updateProps, function (val, key) { + var oldVal = pointOrigin[key], + axis = series[val.axis + 'Axis'], + newVal = limitToRange(axis.toValue((axis.horiz ? newPos.chartX : newPos.chartY) + + pointOrigin[key + 'Offset']), + val.axis.toUpperCase()); + // If we are updating a single prop, and it has a validation function + // for the prop, run it. If it fails, don't update the value. + if (!(updateSingleProp && + val.propValidate && + !val.propValidate(newVal, point)) && + typeof oldVal !== 'undefined') { + result[key] = newVal; + } + }); + return result; + }; + /** + * Returns an SVGElement to use as the guide box for a set of points. + * + * @private + * @function Highcharts.Series#getGuideBox + * + * @param {Array} points + * The state to set the guide box to. + * + * @return {Highcharts.SVGElement} + * An SVG element for the guide box, not added to DOM. + */ + H.Series.prototype.getGuideBox = function (points) { + var chart = this.chart, + minX = Infinity, + maxX = -Infinity, + minY = Infinity, + maxY = -Infinity, + changed; + // Find bounding box of all points + points.forEach(function (point) { + var bBox = point.graphic && point.graphic.getBBox() || point.shapeArgs; + if (bBox && (bBox.width || bBox.height || bBox.x || bBox.y)) { + changed = true; + minX = Math.min(bBox.x, minX); + maxX = Math.max(bBox.x + bBox.width, maxX); + minY = Math.min(bBox.y, minY); + maxY = Math.max(bBox.y + bBox.height, maxY); + } + }); + return changed ? chart.renderer.rect(minX, minY, maxX - minX, maxY - minY) : chart.renderer.g(); + }; + /** + * On point mouse out. Hide drag handles, depending on state. + * + * @private + * @function mouseOut + * @param {Highcharts.Point} point + * The point mousing out of. + */ + function mouseOut(point) { + var chart = point.series && point.series.chart, + dragDropData = chart && chart.dragDropData; + if (chart && + chart.dragHandles && + !(dragDropData && + (dragDropData.isDragging && + dragDropData.draggedPastSensitivity || + dragDropData.isHoveringHandle === point.id))) { + chart.hideDragHandles(); + } + } + /** + * Mouseout on resize handle. Handle states, and possibly run mouseOut on point. + * + * @private + * @function onResizeHandleMouseOut + * @param {Highcharts.Point} point + * The point mousing out of. + */ + function onResizeHandleMouseOut(point) { + var chart = point.series.chart; + if (chart.dragDropData && + point.id === chart.dragDropData.isHoveringHandle) { + delete chart.dragDropData.isHoveringHandle; + } + if (!chart.hoverPoint) { + mouseOut(point); + } + } + /** + * Mousedown on resize handle. Init a drag if the conditions are right. + * + * @private + * @function onResizeHandleMouseDown + * @param {Highcharts.PointerEventObject} e + * The mousedown event. + * @param {Highcharts.Point} point + * The point mousing down on. + * @param {string} updateProp + * The data property this resize handle is attached to for this point. + */ + function onResizeHandleMouseDown(e, point, updateProp) { + var chart = point.series.chart; + // Ignore if zoom/pan key is pressed + if (chart.zoomOrPanKeyPressed(e)) { + return; + } + // Prevent zooming + chart.mouseIsDown = false; + // We started a drag + initDragDrop(e, point); + chart.dragDropData.updateProp = + e.updateProp = updateProp; + point.firePointEvent('dragStart', e); + // Prevent default to avoid point click for dragging too + e.stopPropagation(); + e.preventDefault(); + } + /** + * Render drag handles on a point - depending on which handles are enabled - and + * attach events to them. + * + * @private + * @function Highcharts.Point#showDragHandles + * @return {void} + */ + Point.prototype.showDragHandles = function () { + var point = this, + series = point.series, + chart = series.chart, + renderer = chart.renderer, + options = merge(series.options.dragDrop, + point.options.dragDrop); + // Go through each updateProp and see if we are supposed to create a handle + // for it. + objectEach(series.dragDropProps, function (val, key) { + var handleOptions = merge(defaultDragHandleOptions, + val.handleOptions, + options.dragHandle), + handleAttrs = { + className: handleOptions.className, + 'stroke-width': handleOptions.lineWidth, + fill: handleOptions.color, + stroke: handleOptions.lineColor + }, + pathFormatter = handleOptions.pathFormatter || val.handleFormatter, + positioner = val.handlePositioner, + pos, + handle, + path, + // Run validation function on whether or not we allow individual + // updating of this prop. + validate = val.validateIndividualDrag ? + val.validateIndividualDrag(point) : true; + if (val.resize && + validate && + val.resizeSide && + pathFormatter && + (options['draggable' + val.axis.toUpperCase()] || + options[val.optionName]) && + options[val.optionName] !== false) { + // Create group if it doesn't exist + if (!chart.dragHandles) { + chart.dragHandles = { + group: renderer + .g('drag-drop-handles') + .add(series.markerGroup || series.group) + }; + } + // Store which point this is + chart.dragHandles.point = point.id; + // Find position and path of handle + pos = positioner(point); + handleAttrs.d = path = pathFormatter(point); + if (!path || pos.x < 0 || pos.y < 0) { + return; + } + // If cursor is not set explicitly, use axis direction + handleAttrs.cursor = handleOptions.cursor || + (val.axis === 'x') !== !!chart.inverted ? + 'ew-resize' : 'ns-resize'; + // Create and add the handle element if it doesn't exist + handle = chart.dragHandles[val.optionName]; + if (!handle) { + handle = chart.dragHandles[val.optionName] = renderer + .path() + .add(chart.dragHandles.group); + } + // Move and update handle + handle.translate(pos.x, pos.y).attr(handleAttrs); + // Add events + addEvents(handle.element, ['touchstart', 'mousedown'], function (e) { + onResizeHandleMouseDown(getNormalizedEvent(e, chart), point, key); + }); + addEvent(chart.dragHandles.group.element, 'mouseover', function () { + chart.dragDropData = chart.dragDropData || {}; + chart.dragDropData.isHoveringHandle = point.id; + }); + addEvents(chart.dragHandles.group.element, ['touchend', 'mouseout'], function () { + onResizeHandleMouseOut(point); + }); + } + }); + }; + /** + * Remove the chart's drag handles if they exist. + * + * @private + * @function Highcharts.Chart#hideDragHandles + * @return {void} + */ + H.Chart.prototype.hideDragHandles = function () { + var chart = this; + if (chart.dragHandles) { + objectEach(chart.dragHandles, function (val, key) { + if (key !== 'group' && val.destroy) { + val.destroy(); + } + }); + if (chart.dragHandles.group && chart.dragHandles.group.destroy) { + chart.dragHandles.group.destroy(); + } + delete chart.dragHandles; + } + }; + /** + * Utility function to count the number of props in an object. + * + * @private + * @function countProps + * + * @param {object} obj + * The object to count. + * + * @return {number} + * Number of own properties on the object. + */ + function countProps(obj) { + var count = 0; + for (var p in obj) { + if (Object.hasOwnProperty.call(obj, p)) { + count++; + } + } + return count; + } + /** + * Utility function to get the value of the first prop of an object. (Note that + * the order of keys in an object is usually not guaranteed.) + * + * @private + * @function getFirstProp + * @param {Highcharts.Dictionary} obj + * The object to count. + * @return {T} + * Value of the first prop in the object. + * @template T + */ + function getFirstProp(obj) { + for (var p in obj) { + if (Object.hasOwnProperty.call(obj, p)) { + return obj[p]; + } + } + } + /** + * Mouseover on a point. Show drag handles if the conditions are right. + * + * @private + * @function mouseOver + * @param {Highcharts.Point} point + * The point mousing over. + */ + function mouseOver(point) { + var series = point.series, + chart = series && series.chart, + dragDropData = chart && chart.dragDropData, + is3d = chart && chart.is3d && chart.is3d(); + if (chart && + !(dragDropData && + dragDropData.isDragging && // Ignore if dragging a point + dragDropData.draggedPastSensitivity) && + !chart.isDragDropAnimating && // Ignore if animating + series.options.dragDrop && // No need to compute handles without this + !is3d // No 3D support + ) { + // Hide the handles if they exist on another point already + if (chart.dragHandles) { + chart.hideDragHandles(); + } + point.showDragHandles(); + } + } + /** + * On container mouse move. Handle drag sensitivity and fire drag event. + * + * @private + * @function mouseMove + * @param {Highcharts.PointerEventObject} e + * The mouse move event. + * @param {Highcharts.Chart} chart + * The chart we are moving across. + */ + function mouseMove(e, chart) { + // Ignore if zoom/pan key is pressed + if (chart.zoomOrPanKeyPressed(e)) { + return; + } + var dragDropData = chart.dragDropData, + point, + seriesDragDropOpts, + newPoints, + numNewPoints = 0, + newPoint; + if (dragDropData && dragDropData.isDragging) { + point = dragDropData.point; + seriesDragDropOpts = point.series.options.dragDrop; + // No tooltip for dragging + e.preventDefault(); + // Update sensitivity test if not passed yet + if (!dragDropData.draggedPastSensitivity) { + dragDropData.draggedPastSensitivity = hasDraggedPastSensitivity(e, chart, pick(point.options.dragDrop && + point.options.dragDrop.dragSensitivity, seriesDragDropOpts && + seriesDragDropOpts.dragSensitivity, defaultDragSensitivity)); + } + // If we have dragged past dragSensitivity, run the mousemove handler + // for dragging + if (dragDropData.draggedPastSensitivity) { + // Find the new point values from the moving + dragDropData.newPoints = getNewPoints(dragDropData, e); + // If we are only dragging one point, add it to the event + newPoints = dragDropData.newPoints; + numNewPoints = countProps(newPoints); + newPoint = numNewPoints === 1 ? + getFirstProp(newPoints) : + null; + // Run the handler + point.firePointEvent('drag', { + origin: dragDropData.origin, + newPoints: dragDropData.newPoints, + newPoint: newPoint && newPoint.newValues, + newPointId: newPoint && newPoint.point.id, + numNewPoints: numNewPoints, + chartX: e.chartX, + chartY: e.chartY + }, function () { + dragMove(e, point); + }); + } + } + } + /** + * On container mouse up. Fire drop event and reset state. + * + * @private + * @function mouseUp + * @param {Highcharts.PointerEventObject} e + * The mouse up event. + * @param {Highcharts.Chart} chart + * The chart we were dragging in. + */ + function mouseUp(e, chart) { + var dragDropData = chart.dragDropData; + if (dragDropData && + dragDropData.isDragging && + dragDropData.draggedPastSensitivity) { + var point = dragDropData.point, + newPoints = dragDropData.newPoints, + numNewPoints = countProps(newPoints), + newPoint = numNewPoints === 1 ? + getFirstProp(newPoints) : + null; + // Hide the drag handles + if (chart.dragHandles) { + chart.hideDragHandles(); + } + // Prevent default action + e.preventDefault(); + chart.cancelClick = true; + // Fire the event, with a default handler that updates the points + point.firePointEvent('drop', { + origin: dragDropData.origin, + chartX: e.chartX, + chartY: e.chartY, + newPoints: newPoints, + numNewPoints: numNewPoints, + newPoint: newPoint && newPoint.newValues, + newPointId: newPoint && newPoint.point.id + }, function () { + updatePoints(chart); + }); + } + // Reset + delete chart.dragDropData; + // Clean up the drag guide box if it exists. This is always added on + // drag start, even if user is overriding events. + if (chart.dragGuideBox) { + chart.dragGuideBox.destroy(); + delete chart.dragGuideBox; + } + } + /** + * On container mouse down. Init dragdrop if conditions are right. + * + * @private + * @function mouseDown + * @param {Highcharts.PointerEventObject} e + * The mouse down event. + * @param {Highcharts.Chart} chart + * The chart we are clicking. + */ + function mouseDown(e, chart) { + var dragPoint = chart.hoverPoint, + dragDropOptions = merge(dragPoint && dragPoint.series.options.dragDrop, + dragPoint && dragPoint.options.dragDrop), + draggableX = dragDropOptions.draggableX || false, + draggableY = dragDropOptions.draggableY || false; + // Reset cancel click + chart.cancelClick = false; + // Ignore if: + if ( + // Option is disabled for the point + !(draggableX || draggableY) || + // Zoom/pan key is pressed + chart.zoomOrPanKeyPressed(e) || + // Dragging an annotation + chart.hasDraggedAnnotation) { + return; + } + // If we somehow get a mousedown event while we are dragging, cancel + if (chart.dragDropData && chart.dragDropData.isDragging) { + mouseUp(e, chart); + return; + } + // If this point is movable, start dragging it + if (dragPoint && isPointMovable(dragPoint)) { + chart.mouseIsDown = false; // Prevent zooming + initDragDrop(e, dragPoint); + dragPoint.firePointEvent('dragStart', e); + } + } + /* eslint-disable no-invalid-this */ + // Point hover event. We use a short timeout due to issues with coordinating + // point mouseover/out events on dragHandles and points. Particularly arearange + // series are finicky since the markers are not individual points. This logic + // should preferably be improved in the future. Notice that the mouseOut event + // below must have a shorter timeout to ensure event order. + addEvent(Point, 'mouseOver', function () { + var point = this; + setTimeout(function () { + mouseOver(point); + }, 12); + }); + // Point mouseleave event. See above function for explanation of the timeout. + addEvent(Point, 'mouseOut', function () { + var point = this; + setTimeout(function () { + if (point.series) { + mouseOut(point); + } + }, 10); + }); + // Hide drag handles on a point if it is removed + addEvent(Point, 'remove', function () { + var chart = this.series.chart, + dragHandles = chart.dragHandles; + if (dragHandles && dragHandles.point === this.id) { + chart.hideDragHandles(); + } + }); + /** + * Check whether the zoomKey or panKey is pressed. + * + * @private + * @function Highcharts.Chart#zoomOrPanKeyPressed + * @param {global.Event} e + * A mouse event. + * @return {boolean} + * True if the zoom or pan keys are pressed. False otherwise. + */ + H.Chart.prototype.zoomOrPanKeyPressed = function (e) { + // Check whether the panKey and zoomKey are set in chart.userOptions + var chartOptions = this.userOptions.chart || {}, panKey = chartOptions.panKey && chartOptions.panKey + 'Key', zoomKey = chartOptions.zoomKey && chartOptions.zoomKey + 'Key'; + return (e[zoomKey] || e[panKey]); + }; + /** + * Add events to document and chart if the chart is draggable. + * + * @private + * @function addDragDropEvents + * @param {Highcharts.Chart} chart + * The chart to add events to. + */ + function addDragDropEvents(chart) { + var container = chart.container, + doc = H.doc; + // Only enable if we have a draggable chart + if (isChartDraggable(chart)) { + addEvents(container, ['mousedown', 'touchstart'], function (e) { + mouseDown(getNormalizedEvent(e, chart), chart); + }); + addEvents(container, ['mousemove', 'touchmove'], function (e) { + mouseMove(getNormalizedEvent(e, chart), chart); + }); + addEvent(container, 'mouseleave', function (e) { + mouseUp(getNormalizedEvent(e, chart), chart); + }); + chart.unbindDragDropMouseUp = addEvents(doc, ['mouseup', 'touchend'], function (e) { + mouseUp(getNormalizedEvent(e, chart), chart); + }); + // Add flag to avoid doing this again + chart.hasAddedDragDropEvents = true; + // Add cleanup to make sure we don't pollute document + addEvent(chart, 'destroy', function () { + if (chart.unbindDragDropMouseUp) { + chart.unbindDragDropMouseUp(); + } + }); + } + } + // Add event listener to Chart.render that checks whether or not we should add + // dragdrop. + addEvent(H.Chart, 'render', function () { + // If we don't have dragDrop events, see if we should add them + if (!this.hasAddedDragDropEvents) { + addDragDropEvents(this); + } + }); + + }); + _registerModule(_modules, 'masters/modules/draggable-points.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/drilldown.js b/highcharts/modules/drilldown.js new file mode 100644 index 0000000..69a4c1c --- /dev/null +++ b/highcharts/modules/drilldown.js @@ -0,0 +1,31 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Highcharts Drilldown module + + Author: Torstein Honsi + License: www.highcharts.com/license + +*/ +(function(c){"object"===typeof module&&module.exports?(c["default"]=c,module.exports=c):"function"===typeof define&&define.amd?define("highcharts/modules/drilldown",["highcharts"],function(m){c(m);c.Highcharts=m;return c}):c("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(c){function m(c,m,p,t){c.hasOwnProperty(m)||(c[m]=t.apply(null,p))}c=c?c._modules:{};m(c,"Extensions/Drilldown.js",[c["Core/Chart/Chart.js"],c["Core/Color.js"],c["Core/Globals.js"],c["Core/Options.js"],c["Core/Series/Point.js"], +c["Core/Renderer/SVG/SVGRenderer.js"],c["Core/Axis/Tick.js"],c["Core/Utilities.js"]],function(c,m,p,t,y,E,A,k){t=t.defaultOptions;var n=k.addEvent,F=k.removeEvent,B=k.animObject,u=k.extend,x=k.fireEvent,G=k.format,v=k.merge,C=k.objectEach,w=k.pick,H=k.syncTimeout,I=p.noop,q=p.seriesTypes;k=q.pie;q=q.column;var D=1;u(t.lang,{drillUpText:"\u25c1 Back to {series.name}"});t.drilldown={activeAxisLabelStyle:{cursor:"pointer",color:"#003399",fontWeight:"bold",textDecoration:"underline"},activeDataLabelStyle:{cursor:"pointer", +color:"#003399",fontWeight:"bold",textDecoration:"underline"},animation:{duration:500},drillUpButton:{position:{align:"right",x:-10,y:10}}};E.prototype.Element.prototype.fadeIn=function(a){this.attr({opacity:.1,visibility:"inherit"}).animate({opacity:w(this.newOpacity,1)},a||{duration:250})};c.prototype.addSeriesAsDrilldown=function(a,b){this.addSingleSeriesAsDrilldown(a,b);this.applyDrilldown()};c.prototype.addSingleSeriesAsDrilldown=function(a,b){var d=a.series,f=d.xAxis,e=d.yAxis,g=[],r=[],h;var l= +this.styledMode?{colorIndex:w(a.colorIndex,d.colorIndex)}:{color:a.color||d.color};this.drilldownLevels||(this.drilldownLevels=[]);var c=d.options._levelNumber||0;(h=this.drilldownLevels[this.drilldownLevels.length-1])&&h.levelNumber!==c&&(h=void 0);b=u(u({_ddSeriesId:D++},l),b);var k=d.points.indexOf(a);d.chart.series.forEach(function(a){a.xAxis!==f||a.isDrilling||(a.options._ddSeriesId=a.options._ddSeriesId||D++,a.options._colorIndex=a.userOptions._colorIndex,a.options._levelNumber=a.options._levelNumber|| +c,h?(g=h.levelSeries,r=h.levelSeriesOptions):(g.push(a),a.purgedOptions=v({_ddSeriesId:a.options._ddSeriesId,_levelNumber:a.options._levelNumber,selected:a.options.selected},a.userOptions),r.push(a.purgedOptions)))});a=u({levelNumber:c,seriesOptions:d.options,seriesPurgedOptions:d.purgedOptions,levelSeriesOptions:r,levelSeries:g,shapeArgs:a.shapeArgs,bBox:a.graphic?a.graphic.getBBox():{},color:a.isNull?(new m(l.color)).setOpacity(0).get():l.color,lowerSeriesOptions:b,pointOptions:d.options.data[k], +pointIndex:k,oldExtremes:{xMin:f&&f.userMin,xMax:f&&f.userMax,yMin:e&&e.userMin,yMax:e&&e.userMax},resetZoomButton:this.resetZoomButton},l);this.drilldownLevels.push(a);f&&f.names&&(f.names.length=0);b=a.lowerSeries=this.addSeries(b,!1);b.options._levelNumber=c+1;f&&(f.oldPos=f.pos,f.userMin=f.userMax=null,e.userMin=e.userMax=null);d.type===b.type&&(b.animate=b.animateDrilldown||I,b.options.animation=!0)};c.prototype.applyDrilldown=function(){var a=this.drilldownLevels;if(a&&0|undefined} + */ /** + * Options for the new series. If the event is utilized for async drilldown, the + * seriesOptions are not added, but rather loaded async. + * @name Highcharts.DrilldownEventObject#seriesOptions + * @type {Highcharts.SeriesOptionsType|undefined} + */ /** + * The event target. + * @name Highcharts.DrilldownEventObject#target + * @type {Highcharts.Chart} + */ /** + * The event type. + * @name Highcharts.DrilldownEventObject#type + * @type {"drilldown"} + */ + /** + * This gets fired after all the series have been drilled up. This is especially + * usefull in a chart with multiple drilldown series. + * + * @callback Highcharts.DrillupAllCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart where the event occurs. + * + * @param {Highcharts.DrillupAllEventObject} e + * The final drillup event. + */ + /** + * The event arguments when all the series have been drilled up. + * + * @interface Highcharts.DrillupAllEventObject + */ /** + * Prevents the default behaviour of the event. + * @name Highcharts.DrillupAllEventObject#preventDefault + * @type {Function} + */ /** + * The event target. + * @name Highcharts.DrillupAllEventObject#target + * @type {Highcharts.Chart} + */ /** + * The event type. + * @name Highcharts.DrillupAllEventObject#type + * @type {"drillupall"} + */ + /** + * Gets fired when drilling up from a drilldown series. + * + * @callback Highcharts.DrillupCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart where the event occurs. + * + * @param {Highcharts.DrillupEventObject} e + * The drillup event. + */ + /** + * The event arguments when drilling up from a drilldown series. + * + * @interface Highcharts.DrillupEventObject + */ /** + * Prevents the default behaviour of the event. + * @name Highcharts.DrillupEventObject#preventDefault + * @type {Function} + */ /** + * Options for the new series. + * @name Highcharts.DrillupEventObject#seriesOptions + * @type {Highcharts.SeriesOptionsType|undefined} + */ /** + * The event target. + * @name Highcharts.DrillupEventObject#target + * @type {Highcharts.Chart} + */ /** + * The event type. + * @name Highcharts.DrillupEventObject#type + * @type {"drillup"} + */ + var noop = H.noop, + seriesTypes = H.seriesTypes, + PieSeries = seriesTypes.pie, + ColumnSeries = seriesTypes.column, + ddSeriesId = 1; + // Add language + extend(defaultOptions.lang, + /** + * @optionparent lang + */ + { + /** + * The text for the button that appears when drilling down, linking back + * to the parent series. The parent series' name is inserted for + * `{series.name}`. + * + * @since 3.0.8 + * @product highcharts highmaps + * @requires modules/drilldown + * + * @private + */ + drillUpText: '◁ Back to {series.name}' + }); + /** + * Options for drill down, the concept of inspecting increasingly high + * resolution data through clicking on chart items like columns or pie slices. + * + * The drilldown feature requires the drilldown.js file to be loaded, + * found in the modules directory of the download package, or online at + * [code.highcharts.com/modules/drilldown.js + * ](https://code.highcharts.com/modules/drilldown.js). + * + * @product highcharts highmaps + * @requires modules/drilldown + * @optionparent drilldown + */ + defaultOptions.drilldown = { + /** + * When this option is false, clicking a single point will drill down + * all points in the same category, equivalent to clicking the X axis + * label. + * + * @sample {highcharts} highcharts/drilldown/allowpointdrilldown-false/ + * Don't allow point drilldown + * + * @type {boolean} + * @default true + * @since 4.1.7 + * @product highcharts + * @apioption drilldown.allowPointDrilldown + */ + /** + * An array of series configurations for the drill down. Each series + * configuration uses the same syntax as the [series](#series) option set. + * These drilldown series are hidden by default. The drilldown series is + * linked to the parent series' point by its `id`. + * + * @type {Array} + * @since 3.0.8 + * @product highcharts highmaps + * @apioption drilldown.series + */ + /** + * Additional styles to apply to the X axis label for a point that + * has drilldown data. By default it is underlined and blue to invite + * to interaction. + * + * In styled mode, active label styles can be set with the + * `.highcharts-drilldown-axis-label` class. + * + * @sample {highcharts} highcharts/drilldown/labels/ + * Label styles + * + * @type {Highcharts.CSSObject} + * @default { "cursor": "pointer", "color": "#003399", "fontWeight": "bold", "textDecoration": "underline" } + * @since 3.0.8 + * @product highcharts highmaps + */ + activeAxisLabelStyle: { + /** @ignore-option */ + cursor: 'pointer', + /** @ignore-option */ + color: '#003399', + /** @ignore-option */ + fontWeight: 'bold', + /** @ignore-option */ + textDecoration: 'underline' + }, + /** + * Additional styles to apply to the data label of a point that has + * drilldown data. By default it is underlined and blue to invite to + * interaction. + * + * In styled mode, active data label styles can be applied with the + * `.highcharts-drilldown-data-label` class. + * + * @sample {highcharts} highcharts/drilldown/labels/ + * Label styles + * + * @type {Highcharts.CSSObject} + * @default { "cursor": "pointer", "color": "#003399", "fontWeight": "bold", "textDecoration": "underline" } + * @since 3.0.8 + * @product highcharts highmaps + */ + activeDataLabelStyle: { + cursor: 'pointer', + color: '#003399', + fontWeight: 'bold', + textDecoration: 'underline' + }, + /** + * Set the animation for all drilldown animations. Animation of a drilldown + * occurs when drilling between a column point and a column series, + * or a pie slice and a full pie series. Drilldown can still be used + * between series and points of different types, but animation will + * not occur. + * + * The animation can either be set as a boolean or a configuration + * object. If `true`, it will use the 'swing' jQuery easing and a duration + * of 500 ms. If used as a configuration object, the following properties + * are supported: + * + * - `duration`: The duration of the animation in milliseconds. + * + * - `easing`: A string reference to an easing function set on the `Math` + * object. See + * [the easing demo](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-animation-easing/). + * + * @type {boolean|Partial} + * @since 3.0.8 + * @product highcharts highmaps + */ + animation: { + /** @internal */ + duration: 500 + }, + /** + * Options for the drill up button that appears when drilling down on a + * series. The text for the button is defined in + * [lang.drillUpText](#lang.drillUpText). + * + * @sample {highcharts} highcharts/drilldown/drillupbutton/ + * Drill up button + * @sample {highmaps} highcharts/drilldown/drillupbutton/ + * Drill up button + * + * @since 3.0.8 + * @product highcharts highmaps + */ + drillUpButton: { + /** + * What box to align the button to. Can be either `plotBox` or + * `spacingBox`. + * + * @type {Highcharts.ButtonRelativeToValue} + * @default plotBox + * @since 3.0.8 + * @product highcharts highmaps + * @apioption drilldown.drillUpButton.relativeTo + */ + /** + * A collection of attributes for the button. The object takes SVG + * attributes like `fill`, `stroke`, `stroke-width` or `r`, the border + * radius. The theme also supports `style`, a collection of CSS + * properties for the text. Equivalent attributes for the hover state + * are given in `theme.states.hover`. + * + * In styled mode, drill-up button styles can be applied with the + * `.highcharts-drillup-button` class. + * + * @sample {highcharts} highcharts/drilldown/drillupbutton/ + * Button theming + * @sample {highmaps} highcharts/drilldown/drillupbutton/ + * Button theming + * + * @type {object} + * @since 3.0.8 + * @product highcharts highmaps + * @apioption drilldown.drillUpButton.theme + */ + /** + * Positioning options for the button within the `relativeTo` box. + * Available properties are `x`, `y`, `align` and `verticalAlign`. + * + * @type {Highcharts.AlignObject} + * @since 3.0.8 + * @product highcharts highmaps + */ + position: { + /** + * Vertical alignment of the button. + * + * @type {Highcharts.VerticalAlignValue} + * @default top + * @product highcharts highmaps + * @apioption drilldown.drillUpButton.position.verticalAlign + */ + /** + * Horizontal alignment. + * + * @type {Highcharts.AlignValue} + */ + align: 'right', + /** + * The X offset of the button. + */ + x: -10, + /** + * The Y offset of the button. + */ + y: 10 + } + } + }; + /** + * Fires when a drilldown point is clicked, before the new series is added. This + * event is also utilized for async drilldown, where the seriesOptions are not + * added by option, but rather loaded async. Note that when clicking a category + * label to trigger multiple series drilldown, one `drilldown` event is + * triggered per point in the category. + * + * Event arguments: + * + * - `category`: If a category label was clicked, which index. + * + * - `originalEvent`: The original browser event (usually click) that triggered + * the drilldown. + * + * - `point`: The originating point. + * + * - `points`: If a category label was clicked, this array holds all points + * corresponding to the category. + * + * - `seriesOptions`: Options for the new series. + * + * @sample {highcharts} highcharts/drilldown/async/ + * Async drilldown + * + * @type {Highcharts.DrilldownCallbackFunction} + * @since 3.0.8 + * @product highcharts highmaps + * @context Highcharts.Chart + * @requires modules/drilldown + * @apioption chart.events.drilldown + */ + /** + * Fires when drilling up from a drilldown series. + * + * @type {Highcharts.DrillupCallbackFunction} + * @since 3.0.8 + * @product highcharts highmaps + * @context Highcharts.Chart + * @requires modules/drilldown + * @apioption chart.events.drillup + */ + /** + * In a chart with multiple drilldown series, this event fires after all the + * series have been drilled up. + * + * @type {Highcharts.DrillupAllCallbackFunction} + * @since 4.2.4 + * @product highcharts highmaps + * @context Highcharts.Chart + * @requires modules/drilldown + * @apioption chart.events.drillupall + */ + /** + * The `id` of a series in the [drilldown.series](#drilldown.series) array to + * use for a drilldown for this point. + * + * @sample {highcharts} highcharts/drilldown/basic/ + * Basic drilldown + * + * @type {string} + * @since 3.0.8 + * @product highcharts + * @requires modules/drilldown + * @apioption series.line.data.drilldown + */ + /** + * A general fadeIn method. + * + * @requires module:modules/drilldown + * + * @function Highcharts.SVGElement#fadeIn + * + * @param {boolean|Partial} [animation] + * The animation options for the element fade. + */ + SVGRenderer.prototype.Element.prototype.fadeIn = function (animation) { + this + .attr({ + opacity: 0.1, + visibility: 'inherit' + }) + .animate({ + opacity: pick(this.newOpacity, 1) // newOpacity used in maps + }, animation || { + duration: 250 + }); + }; + /** + * Add a series to the chart as drilldown from a specific point in the parent + * series. This method is used for async drilldown, when clicking a point in a + * series should result in loading and displaying a more high-resolution series. + * When not async, the setup is simpler using the + * [drilldown.series](https://api.highcharts.com/highcharts/drilldown.series) + * options structure. + * + * @sample highcharts/drilldown/async/ + * Async drilldown + * + * @function Highcharts.Chart#addSeriesAsDrilldown + * + * @param {Highcharts.Point} point + * The point from which the drilldown will start. + * + * @param {Highcharts.SeriesOptionsType} options + * The series options for the new, detailed series. + */ + Chart.prototype.addSeriesAsDrilldown = function (point, options) { + this.addSingleSeriesAsDrilldown(point, options); + this.applyDrilldown(); + }; + Chart.prototype.addSingleSeriesAsDrilldown = function (point, ddOptions) { + var oldSeries = point.series, + xAxis = oldSeries.xAxis, + yAxis = oldSeries.yAxis, + newSeries, + pointIndex, + levelSeries = [], + levelSeriesOptions = [], + level, + levelNumber, + last, + colorProp; + colorProp = this.styledMode ? + { colorIndex: pick(point.colorIndex, oldSeries.colorIndex) } : + { color: point.color || oldSeries.color }; + if (!this.drilldownLevels) { + this.drilldownLevels = []; + } + levelNumber = oldSeries.options._levelNumber || 0; + // See if we can reuse the registered series from last run + last = this.drilldownLevels[this.drilldownLevels.length - 1]; + if (last && last.levelNumber !== levelNumber) { + last = void 0; + } + ddOptions = extend(extend({ + _ddSeriesId: ddSeriesId++ + }, colorProp), ddOptions); + pointIndex = oldSeries.points.indexOf(point); + // Record options for all current series + oldSeries.chart.series.forEach(function (series) { + if (series.xAxis === xAxis && !series.isDrilling) { + series.options._ddSeriesId = + series.options._ddSeriesId || ddSeriesId++; + series.options._colorIndex = series.userOptions._colorIndex; + series.options._levelNumber = + series.options._levelNumber || levelNumber; // #3182 + if (last) { + levelSeries = last.levelSeries; + levelSeriesOptions = last.levelSeriesOptions; + } + else { + levelSeries.push(series); + // (#10597) + series.purgedOptions = merge({ + _ddSeriesId: series.options._ddSeriesId, + _levelNumber: series.options._levelNumber, + selected: series.options.selected + }, series.userOptions); + levelSeriesOptions.push(series.purgedOptions); + } + } + }); + // Add a record of properties for each drilldown level + level = extend({ + levelNumber: levelNumber, + seriesOptions: oldSeries.options, + seriesPurgedOptions: oldSeries.purgedOptions, + levelSeriesOptions: levelSeriesOptions, + levelSeries: levelSeries, + shapeArgs: point.shapeArgs, + // no graphic in line series with markers disabled + bBox: point.graphic ? point.graphic.getBBox() : {}, + color: point.isNull ? + new Color(colorProp.color).setOpacity(0).get() : + colorProp.color, + lowerSeriesOptions: ddOptions, + pointOptions: oldSeries.options.data[pointIndex], + pointIndex: pointIndex, + oldExtremes: { + xMin: xAxis && xAxis.userMin, + xMax: xAxis && xAxis.userMax, + yMin: yAxis && yAxis.userMin, + yMax: yAxis && yAxis.userMax + }, + resetZoomButton: this.resetZoomButton + }, colorProp); + // Push it to the lookup array + this.drilldownLevels.push(level); + // Reset names to prevent extending (#6704) + if (xAxis && xAxis.names) { + xAxis.names.length = 0; + } + newSeries = level.lowerSeries = this.addSeries(ddOptions, false); + newSeries.options._levelNumber = levelNumber + 1; + if (xAxis) { + xAxis.oldPos = xAxis.pos; + xAxis.userMin = xAxis.userMax = null; + yAxis.userMin = yAxis.userMax = null; + } + // Run fancy cross-animation on supported and equal types + if (oldSeries.type === newSeries.type) { + newSeries.animate = newSeries.animateDrilldown || noop; + newSeries.options.animation = true; + } + }; + Chart.prototype.applyDrilldown = function () { + var drilldownLevels = this.drilldownLevels, + levelToRemove; + if (drilldownLevels && drilldownLevels.length > 0) { // #3352, async loading + levelToRemove = drilldownLevels[drilldownLevels.length - 1].levelNumber; + this.drilldownLevels.forEach(function (level) { + if (level.levelNumber === levelToRemove) { + level.levelSeries.forEach(function (series) { + // Not removed, not added as part of a multi-series + // drilldown + if (series.options && + series.options._levelNumber === levelToRemove) { + series.remove(false); + } + }); + } + }); + } + // We have a reset zoom button. Hide it and detatch it from the chart. It + // is preserved to the layer config above. + if (this.resetZoomButton) { + this.resetZoomButton.hide(); + delete this.resetZoomButton; + } + this.pointer.reset(); + this.redraw(); + this.showDrillUpButton(); + fireEvent(this, 'afterDrilldown'); + }; + Chart.prototype.getDrilldownBackText = function () { + var drilldownLevels = this.drilldownLevels, + lastLevel; + if (drilldownLevels && drilldownLevels.length > 0) { // #3352, async loading + lastLevel = drilldownLevels[drilldownLevels.length - 1]; + lastLevel.series = lastLevel.seriesOptions; + return format(this.options.lang.drillUpText, lastLevel); + } + }; + Chart.prototype.showDrillUpButton = function () { + var chart = this, + backText = this.getDrilldownBackText(), + buttonOptions = chart.options.drilldown.drillUpButton, + attr, + states; + if (!this.drillUpButton) { + attr = buttonOptions.theme; + states = attr && attr.states; + this.drillUpButton = this.renderer.button(backText, null, null, function () { + chart.drillUp(); + }, attr, states && states.hover, states && states.select) + .addClass('highcharts-drillup-button') + .attr({ + align: buttonOptions.position.align, + zIndex: 7 + }) + .add() + .align(buttonOptions.position, false, buttonOptions.relativeTo || 'plotBox'); + } + else { + this.drillUpButton.attr({ + text: backText + }) + .align(); + } + }; + /** + * When the chart is drilled down to a child series, calling `chart.drillUp()` + * will drill up to the parent series. + * + * @requires modules/drilldown + * + * @function Highcharts.Chart#drillUp + */ + Chart.prototype.drillUp = function () { + if (!this.drilldownLevels || this.drilldownLevels.length === 0) { + return; + } + var chart = this, + drilldownLevels = chart.drilldownLevels, + levelNumber = drilldownLevels[drilldownLevels.length - 1].levelNumber, + i = drilldownLevels.length, + chartSeries = chart.series, + seriesI, + level, + oldSeries, + newSeries, + oldExtremes, + addSeries = function (seriesOptions) { + var addedSeries; + chartSeries.forEach(function (series) { + if (series.options._ddSeriesId === seriesOptions._ddSeriesId) { + addedSeries = series; + } + }); + addedSeries = addedSeries || chart.addSeries(seriesOptions, false); + if (addedSeries.type === oldSeries.type && + addedSeries.animateDrillupTo) { + addedSeries.animate = addedSeries.animateDrillupTo; + } + if (seriesOptions === level.seriesPurgedOptions) { + newSeries = addedSeries; + } + }; + while (i--) { + level = drilldownLevels[i]; + if (level.levelNumber === levelNumber) { + drilldownLevels.pop(); + // Get the lower series by reference or id + oldSeries = level.lowerSeries; + if (!oldSeries.chart) { // #2786 + seriesI = chartSeries.length; // #2919 + while (seriesI--) { + if (chartSeries[seriesI].options.id === + level.lowerSeriesOptions.id && + chartSeries[seriesI].options._levelNumber === + levelNumber + 1) { // #3867 + oldSeries = chartSeries[seriesI]; + break; + } + } + } + oldSeries.xData = []; // Overcome problems with minRange (#2898) + level.levelSeriesOptions.forEach(addSeries); + fireEvent(chart, 'drillup', { + seriesOptions: level.seriesPurgedOptions || + level.seriesOptions + }); + if (newSeries.type === oldSeries.type) { + newSeries.drilldownLevel = level; + newSeries.options.animation = + chart.options.drilldown.animation; + if (oldSeries.animateDrillupFrom && oldSeries.chart) { // #2919 + oldSeries.animateDrillupFrom(level); + } + } + newSeries.options._levelNumber = levelNumber; + oldSeries.remove(false); + // Reset the zoom level of the upper series + if (newSeries.xAxis) { + oldExtremes = level.oldExtremes; + newSeries.xAxis.setExtremes(oldExtremes.xMin, oldExtremes.xMax, false); + newSeries.yAxis.setExtremes(oldExtremes.yMin, oldExtremes.yMax, false); + } + // We have a resetZoomButton tucked away for this level. Attatch + // it to the chart and show it. + if (level.resetZoomButton) { + chart.resetZoomButton = level.resetZoomButton; + chart.resetZoomButton.show(); + } + } + } + this.redraw(); + if (this.drilldownLevels.length === 0) { + this.drillUpButton = this.drillUpButton.destroy(); + } + else { + this.drillUpButton.attr({ + text: this.getDrilldownBackText() + }) + .align(); + } + this.ddDupes.length = []; // #3315 + // Fire a once-off event after all series have been drilled up (#5158) + fireEvent(chart, 'drillupall'); + }; + /* eslint-disable no-invalid-this */ + // Add update function to be called internally from Chart.update + // (#7600, #12855) + addEvent(Chart, 'afterInit', function () { + var chart = this; + chart.drilldown = { + update: function (options, redraw) { + merge(true, chart.options.drilldown, options); + if (pick(redraw, true)) { + chart.redraw(); + } + } + }; + }); + // Don't show the reset button if we already are displaying the drillUp button. + addEvent(Chart, 'beforeShowResetZoom', function () { + if (this.drillUpButton) { + return false; + } + }); + addEvent(Chart, 'render', function () { + (this.xAxis || []).forEach(function (axis) { + axis.ddPoints = {}; + axis.series.forEach(function (series) { + var i, + xData = series.xData || [], + points = series.points, + p; + for (i = 0; i < xData.length; i++) { + p = series.options.data[i]; + // The `drilldown` property can only be set on an array or an + // object + if (typeof p !== 'number') { + // Convert array to object (#8008) + p = series.pointClass.prototype.optionsToObject + .call({ series: series }, p); + if (p.drilldown) { + if (!axis.ddPoints[xData[i]]) { + axis.ddPoints[xData[i]] = []; + } + axis.ddPoints[xData[i]].push(points ? points[i] : true); + } + } + } + }); + // Add drillability to ticks, and always keep it drillability updated + // (#3951) + objectEach(axis.ticks, Tick.prototype.drillable); + }); + }); + /** + * When drilling up, keep the upper series invisible until the lower series has + * moved into place. + * + * @private + * @function Highcharts.ColumnSeries#animateDrillupTo + * @param {boolean} [init=false] + * Whether to initialize animation + */ + ColumnSeries.prototype.animateDrillupTo = function (init) { + if (!init) { + var newSeries = this, + level = newSeries.drilldownLevel; + // First hide all items before animating in again + this.points.forEach(function (point) { + var dataLabel = point.dataLabel; + if (point.graphic) { // #3407 + point.graphic.hide(); + } + if (dataLabel) { + // The data label is initially hidden, make sure it is not faded + // in (#6127) + dataLabel.hidden = dataLabel.attr('visibility') === 'hidden'; + if (!dataLabel.hidden) { + dataLabel.hide(); + if (point.connector) { + point.connector.hide(); + } + } + } + }); + // Do dummy animation on first point to get to complete + syncTimeout(function () { + if (newSeries.points) { // May be destroyed in the meantime, #3389 + newSeries.points.forEach(function (point, i) { + // Fade in other points + var verb = i === (level && level.pointIndex) ? 'show' : 'fadeIn', inherit = verb === 'show' ? true : void 0, dataLabel = point.dataLabel; + if (point.graphic) { // #3407 + point.graphic[verb](inherit); + } + if (dataLabel && !dataLabel.hidden) { // #6127 + dataLabel.fadeIn(); // #7384 + if (point.connector) { + point.connector.fadeIn(); + } + } + }); + } + }, Math.max(this.chart.options.drilldown.animation.duration - 50, 0)); + // Reset to prototype + delete this.animate; + } + }; + ColumnSeries.prototype.animateDrilldown = function (init) { + var series = this, + chart = this.chart, + drilldownLevels = chart.drilldownLevels, + animateFrom, + animationOptions = animObject(chart.options.drilldown.animation), + xAxis = this.xAxis, + styledMode = chart.styledMode; + if (!init) { + drilldownLevels.forEach(function (level) { + if (series.options._ddSeriesId === + level.lowerSeriesOptions._ddSeriesId) { + animateFrom = level.shapeArgs; + if (!styledMode) { + // Add the point colors to animate from + animateFrom.fill = level.color; + } + } + }); + animateFrom.x += pick(xAxis.oldPos, xAxis.pos) - xAxis.pos; + this.points.forEach(function (point) { + var animateTo = point.shapeArgs; + if (!styledMode) { + // Add the point colors to animate to + animateTo.fill = point.color; + } + if (point.graphic) { + point.graphic + .attr(animateFrom) + .animate(extend(point.shapeArgs, { fill: point.color || series.color }), animationOptions); + } + if (point.dataLabel) { + point.dataLabel.fadeIn(animationOptions); + } + }); + // Reset to prototype + delete this.animate; + } + }; + /** + * When drilling up, pull out the individual point graphics from the lower + * series and animate them into the origin point in the upper series. + * + * @private + * @function Highcharts.ColumnSeries#animateDrillupFrom + * @param {Highcharts.DrilldownLevelObject} level + * Level container + * @return {void} + */ + ColumnSeries.prototype.animateDrillupFrom = function (level) { + var animationOptions = animObject(this.chart.options.drilldown.animation), + group = this.group, + // For 3d column series all columns are added to one group + // so we should not delete the whole group. #5297 + removeGroup = group !== this.chart.columnGroup, + series = this; + // Cancel mouse events on the series group (#2787) + series.trackerGroups.forEach(function (key) { + if (series[key]) { // we don't always have dataLabelsGroup + series[key].on('mouseover'); + } + }); + if (removeGroup) { + delete this.group; + } + this.points.forEach(function (point) { + var graphic = point.graphic, + animateTo = level.shapeArgs, + complete = function () { + graphic.destroy(); + if (group && removeGroup) { + group = group.destroy(); + } + }; + if (graphic && animateTo) { + delete point.graphic; + if (!series.chart.styledMode) { + animateTo.fill = level.color; + } + if (animationOptions.duration) { + graphic.animate(animateTo, merge(animationOptions, { complete: complete })); + } + else { + graphic.attr(animateTo); + complete(); + } + } + }); + }; + if (PieSeries) { + extend(PieSeries.prototype, { + animateDrillupTo: ColumnSeries.prototype.animateDrillupTo, + animateDrillupFrom: ColumnSeries.prototype.animateDrillupFrom, + animateDrilldown: function (init) { + var level = this.chart.drilldownLevels[this.chart.drilldownLevels.length - 1], + animationOptions = this.chart.options.drilldown.animation; + if (this.is('item')) { + animationOptions.duration = 0; + } + // Unable to drill down in the horizontal item series #13372 + if (this.center) { + var animateFrom = level.shapeArgs, + start = animateFrom.start, + angle = animateFrom.end - start, + startAngle = angle / this.points.length, + styledMode = this.chart.styledMode; + if (!init) { + this.points.forEach(function (point, i) { + var animateTo = point.shapeArgs; + if (!styledMode) { + animateFrom.fill = level.color; + animateTo.fill = point.color; + } + if (point.graphic) { + point.graphic + .attr(merge(animateFrom, { + start: start + i * startAngle, + end: start + (i + 1) * startAngle + }))[animationOptions ? 'animate' : 'attr'](animateTo, animationOptions); + } + }); + // Reset to prototype + delete this.animate; + } + } + } + }); + } + Point.prototype.doDrilldown = function (_holdRedraw, category, originalEvent) { + var series = this.series, + chart = series.chart, + drilldown = chart.options.drilldown, + i = (drilldown.series || []).length, + seriesOptions; + if (!chart.ddDupes) { + chart.ddDupes = []; + } + while (i-- && !seriesOptions) { + if (drilldown.series[i].id === this.drilldown && + chart.ddDupes.indexOf(this.drilldown) === -1) { + seriesOptions = drilldown.series[i]; + chart.ddDupes.push(this.drilldown); + } + } + // Fire the event. If seriesOptions is undefined, the implementer can check + // for seriesOptions, and call addSeriesAsDrilldown async if necessary. + fireEvent(chart, 'drilldown', { + point: this, + seriesOptions: seriesOptions, + category: category, + originalEvent: originalEvent, + points: (typeof category !== 'undefined' && + this.series.xAxis.getDDPoints(category).slice(0)) + }, function (e) { + var chart = e.point.series && e.point.series.chart, + seriesOptions = e.seriesOptions; + if (chart && seriesOptions) { + if (_holdRedraw) { + chart.addSingleSeriesAsDrilldown(e.point, seriesOptions); + } + else { + chart.addSeriesAsDrilldown(e.point, seriesOptions); + } + } + }); + }; + /** + * Drill down to a given category. This is the same as clicking on an axis + * label. + * + * @private + * @function Highcharts.Axis#drilldownCategory + * @param {number} x + * Tick position + * @param {global.MouseEvent} e + * Click event + */ + H.Axis.prototype.drilldownCategory = function (x, e) { + objectEach(this.getDDPoints(x), function (point) { + if (point && + point.series && + point.series.visible && + point.doDrilldown) { // #3197 + point.doDrilldown(true, x, e); + } + }); + this.chart.applyDrilldown(); + }; + /** + * Return drillable points for this specific X value. + * + * @private + * @function Highcharts.Axis#getDDPoints + * @param {number} x + * Tick position + * @return {Array<(boolean|Highcharts.Point)>|undefined} + * Drillable points + */ + H.Axis.prototype.getDDPoints = function (x) { + return this.ddPoints && this.ddPoints[x]; + }; + /** + * Make a tick label drillable, or remove drilling on update. + * + * @private + * @function Highcharts.Axis#drillable + */ + Tick.prototype.drillable = function () { + var pos = this.pos, + label = this.label, + axis = this.axis, + isDrillable = axis.coll === 'xAxis' && axis.getDDPoints, + ddPointsX = isDrillable && axis.getDDPoints(pos), + styledMode = axis.chart.styledMode; + if (isDrillable) { + if (label && ddPointsX && ddPointsX.length) { + label.drillable = true; + if (!label.basicStyles && !styledMode) { + label.basicStyles = merge(label.styles); + } + label.addClass('highcharts-drilldown-axis-label'); + // #12656 - avoid duplicate of attach event + if (label.removeOnDrillableClick) { + removeEvent(label.element, 'click'); + } + label.removeOnDrillableClick = addEvent(label.element, 'click', function (e) { + e.preventDefault(); + axis.drilldownCategory(pos, e); + }); + if (!styledMode) { + label.css(axis.chart.options.drilldown.activeAxisLabelStyle); + } + } + else if (label && label.drillable && label.removeOnDrillableClick) { + if (!styledMode) { + label.styles = {}; // reset for full overwrite of styles + label.css(label.basicStyles); + } + label.removeOnDrillableClick(); // #3806 + label.removeClass('highcharts-drilldown-axis-label'); + } + } + }; + // On initialization of each point, identify its label and make it clickable. + // Also, provide a list of points associated to that label. + addEvent(Point, 'afterInit', function () { + var point = this, + series = point.series; + if (point.drilldown) { + // Add the click event to the point + addEvent(point, 'click', function (e) { + if (series.xAxis && + series.chart.options.drilldown.allowPointDrilldown === + false) { + // #5822, x changed + series.xAxis.drilldownCategory(point.x, e); + } + else { + point.doDrilldown(void 0, void 0, e); + } + }); + } + return point; + }); + addEvent(H.Series, 'afterDrawDataLabels', function () { + var css = this.chart.options.drilldown.activeDataLabelStyle, + renderer = this.chart.renderer, + styledMode = this.chart.styledMode; + this.points.forEach(function (point) { + var dataLabelsOptions = point.options.dataLabels, + pointCSS = pick(point.dlOptions, + dataLabelsOptions && dataLabelsOptions.style, {}); + if (point.drilldown && point.dataLabel) { + if (css.color === 'contrast' && !styledMode) { + pointCSS.color = renderer.getContrast(point.color || this.color); + } + if (dataLabelsOptions && dataLabelsOptions.color) { + pointCSS.color = dataLabelsOptions.color; + } + point.dataLabel + .addClass('highcharts-drilldown-data-label'); + if (!styledMode) { + point.dataLabel + .css(css) + .css(pointCSS); + } + } + }, this); + }); + var applyCursorCSS = function (element, + cursor, + addClass, + styledMode) { + element[addClass ? 'addClass' : 'removeClass']('highcharts-drilldown-point'); + if (!styledMode) { + element.css({ cursor: cursor }); + } + }; + // Mark the trackers with a pointer + addEvent(H.Series, 'afterDrawTracker', function () { + var styledMode = this.chart.styledMode; + this.points.forEach(function (point) { + if (point.drilldown && point.graphic) { + applyCursorCSS(point.graphic, 'pointer', true, styledMode); + } + }); + }); + addEvent(Point, 'afterSetState', function () { + var styledMode = this.series.chart.styledMode; + if (this.drilldown && this.series.halo && this.state === 'hover') { + applyCursorCSS(this.series.halo, 'pointer', true, styledMode); + } + else if (this.series.halo) { + applyCursorCSS(this.series.halo, 'auto', false, styledMode); + } + }); + + }); + _registerModule(_modules, 'masters/modules/drilldown.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/dumbbell.js b/highcharts/modules/dumbbell.js new file mode 100644 index 0000000..1c77b6c --- /dev/null +++ b/highcharts/modules/dumbbell.js @@ -0,0 +1,27 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + (c) 2009-2019 Sebastian Bochan, Rafal Sebestjanski + + License: www.highcharts.com/license +*/ +(function(d){"object"===typeof module&&module.exports?(d["default"]=d,module.exports=d):"function"===typeof define&&define.amd?define("highcharts/modules/dumbbell",["highcharts"],function(t){d(t);d.Highcharts=t;return d}):d("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(d){function t(d,r,m,x){d.hasOwnProperty(r)||(d[r]=x.apply(null,m))}d=d?d._modules:{};t(d,"Series/AreaRangeSeries.js",[d["Core/Globals.js"],d["Core/Series/Point.js"],d["Core/Utilities.js"]],function(d,r,m){var x=m.defined, +n=m.extend,t=m.isArray,y=m.isNumber,v=m.pick;m=m.seriesType;var w=d.seriesTypes,u=d.Series.prototype,a=r.prototype;m("arearange","area",{lineWidth:1,threshold:null,tooltip:{pointFormat:'\u25cf {series.name}: {point.low} - {point.high}
    '},trackByArea:!0,dataLabels:{align:void 0,verticalAlign:void 0,xLow:0,xHigh:0,yLow:0,yHigh:0}},{pointArrayMap:["low","high"],pointValKey:"low",deferTranslatePolar:!0,toYData:function(a){return[a.low,a.high]}, +highToXY:function(a){var c=this.chart,b=this.xAxis.postTranslate(a.rectPlotX,this.yAxis.len-a.plotHigh);a.plotHighX=b.x-c.plotLeft;a.plotHigh=b.y-c.plotTop;a.plotLowX=a.plotX},translate:function(){var a=this,c=a.yAxis,b=!!a.modifyValue;w.area.prototype.translate.apply(a);a.points.forEach(function(g){var k=g.high,e=g.plotY;g.isNull?g.plotY=null:(g.plotLow=e,g.plotHigh=c.translate(b?a.modifyValue(k,g):k,0,1,0,1),b&&(g.yBottom=g.plotHigh))});this.chart.polar&&this.points.forEach(function(b){a.highToXY(b); +b.tooltipPos=[(b.plotHighX+b.plotLowX)/2,(b.plotHigh+b.plotLow)/2]})},getGraphPath:function(a){var c=[],b=[],g,f=w.area.prototype.getGraphPath;var e=this.options;var d=this.chart.polar,p=d&&!1!==e.connectEnds,q=e.connectNulls,l=e.step;a=a||this.points;for(g=a.length;g--;){var h=a[g];var n=d?{plotX:h.rectPlotX,plotY:h.yBottom,doCurve:!1}:{plotX:h.plotX,plotY:h.plotY,doCurve:!1};h.isNull||p||q||a[g+1]&&!a[g+1].isNull||b.push(n);var m={polarPlotY:h.polarPlotY,rectPlotX:h.rectPlotX,yBottom:h.yBottom, +plotX:v(h.plotHighX,h.plotX),plotY:h.plotHigh,isNull:h.isNull};b.push(m);c.push(m);h.isNull||p||q||a[g-1]&&!a[g-1].isNull||b.push(n)}a=f.call(this,a);l&&(!0===l&&(l="left"),e.step={left:"right",center:"center",right:"left"}[l]);c=f.call(this,c);b=f.call(this,b);e.step=l;e=[].concat(a,c);!this.chart.polar&&b[0]&&"M"===b[0][0]&&(b[0]=["L",b[0][1],b[0][2]]);this.graphPath=e;this.areaPath=a.concat(b);e.isArea=!0;e.xMap=a.xMap;this.areaPath.xMap=a.xMap;return e},drawDataLabels:function(){var a=this.points, +c=a.length,b,d=[],f=this.options.dataLabels,e,m=this.chart.inverted;if(t(f))if(1e.plotLow;e.y=e.high;e._plotY=e.plotY;e.plotY=e.plotHigh;d[b]=e.dataLabel;e.dataLabel=e.dataLabelUpper;e.below=l;m?p.align||(p.align=l?"right":"left"):p.verticalAlign||(p.verticalAlign= +l?"top":"bottom")}this.options.dataLabels=p;u.drawDataLabels&&u.drawDataLabels.apply(this,arguments);for(b=c;b--;)if(e=a[b])e.dataLabelUpper=e.dataLabel,e.dataLabel=d[b],delete e.dataLabels,e.y=e.low,e.plotY=e._plotY}if(q.enabled||this._hasPointLabels){for(b=c;b--;)if(e=a[b])l=q.inside?e.plotHighe.plotLow,e.below=!l,m?q.align||(q.align=l?"left":"right"):q.verticalAlign||(q.verticalAlign=l?"bottom":"top");this.options.dataLabels=q;u.drawDataLabels&&u.drawDataLabels.apply(this, +arguments)}if(p.enabled)for(b=c;b--;)if(e=a[b])e.dataLabels=[e.dataLabelUpper,e.dataLabel].filter(function(a){return!!a});this.options.dataLabels=f},alignDataLabel:function(){w.column.prototype.alignDataLabel.apply(this,arguments)},drawPoints:function(){var a=this.points.length,c;u.drawPoints.apply(this,arguments);for(c=0;cl?l=0:l>=f.len&&(l=f.len);0>h?h=0:h>=f.len&&(h=f.len);if(0>a.plotX||a.plotX>d.len)e=0;a.upperGraphic&&(d={y:a.y,zone:a.zone},a.y=a.high,a.zone=a.zone?a.getZone():void 0,r=n(c.connectorColor,b.connectorColor,c.color,a.zone?a.zone.color:void 0,a.color), +t(a,d));a={d:m.prototype.crispLine([["M",a.plotX,l],["L",a.plotX,h]],e,"ceil")};g.styledMode||(a.stroke=r,a["stroke-width"]=e,q&&(a.dashstyle=q));return a},drawConnector:function(a){var d=n(this.options.animationLimit,250);d=a.connector&&this.chart.pointCount\u25CF ' + + '{series.name}: {point.low} - {point.high}
    ' + }, + /** + * Whether the whole area or just the line should respond to mouseover + * tooltips and other mouse or touch events. + * + * @since 2.3.0 + * + * @private + */ + trackByArea: true, + /** + * Extended data labels for range series types. Range series data labels use + * no `x` and `y` options. Instead, they have `xLow`, `xHigh`, `yLow` and + * `yHigh` options to allow the higher and lower data label sets + * individually. + * + * @declare Highcharts.SeriesAreaRangeDataLabelsOptionsObject + * @exclude x, y + * @since 2.3.0 + * @product highcharts highstock + * + * @private + */ + dataLabels: { + align: void 0, + verticalAlign: void 0, + /** + * X offset of the lower data labels relative to the point value. + * + * @sample highcharts/plotoptions/arearange-datalabels/ + * Data labels on range series + * @sample highcharts/plotoptions/arearange-datalabels/ + * Data labels on range series + */ + xLow: 0, + /** + * X offset of the higher data labels relative to the point value. + * + * @sample highcharts/plotoptions/arearange-datalabels/ + * Data labels on range series + */ + xHigh: 0, + /** + * Y offset of the lower data labels relative to the point value. + * + * @sample highcharts/plotoptions/arearange-datalabels/ + * Data labels on range series + */ + yLow: 0, + /** + * Y offset of the higher data labels relative to the point value. + * + * @sample highcharts/plotoptions/arearange-datalabels/ + * Data labels on range series + */ + yHigh: 0 + } + // Prototype members + }, { + pointArrayMap: ['low', 'high'], + pointValKey: 'low', + deferTranslatePolar: true, + /* eslint-disable valid-jsdoc */ + /** + * @private + */ + toYData: function (point) { + return [point.low, point.high]; + }, + /** + * Translate a point's plotHigh from the internal angle and radius measures + * to true plotHigh coordinates. This is an addition of the toXY method + * found in Polar.js, because it runs too early for arearanges to be + * considered (#3419). + * @private + */ + highToXY: function (point) { + // Find the polar plotX and plotY + var chart = this.chart, + xy = this.xAxis.postTranslate(point.rectPlotX, + this.yAxis.len - point.plotHigh); + point.plotHighX = xy.x - chart.plotLeft; + point.plotHigh = xy.y - chart.plotTop; + point.plotLowX = point.plotX; + }, + /** + * Translate data points from raw values x and y to plotX and plotY. + * @private + */ + translate: function () { + var series = this, + yAxis = series.yAxis, + hasModifyValue = !!series.modifyValue; + seriesTypes.area.prototype.translate.apply(series); + // Set plotLow and plotHigh + series.points.forEach(function (point) { + var high = point.high, + plotY = point.plotY; + if (point.isNull) { + point.plotY = null; + } + else { + point.plotLow = plotY; + point.plotHigh = yAxis.translate(hasModifyValue ? + series.modifyValue(high, point) : + high, 0, 1, 0, 1); + if (hasModifyValue) { + point.yBottom = point.plotHigh; + } + } + }); + // Postprocess plotHigh + if (this.chart.polar) { + this.points.forEach(function (point) { + series.highToXY(point); + point.tooltipPos = [ + (point.plotHighX + point.plotLowX) / 2, + (point.plotHigh + point.plotLow) / 2 + ]; + }); + } + }, + /** + * Extend the line series' getSegmentPath method by applying the segment + * path to both lower and higher values of the range. + * @private + */ + getGraphPath: function (points) { + var highPoints = [], + highAreaPoints = [], + i, + getGraphPath = seriesTypes.area.prototype.getGraphPath, + point, + pointShim, + linePath, + lowerPath, + options = this.options, + polar = this.chart.polar, + connectEnds = polar && options.connectEnds !== false, + connectNulls = options.connectNulls, + step = options.step, + higherPath, + higherAreaPath; + points = points || this.points; + // Create the top line and the top part of the area fill. The area fill + // compensates for null points by drawing down to the lower graph, + // moving across the null gap and starting again at the lower graph. + i = points.length; + while (i--) { + point = points[i]; + // Support for polar + var highAreaPoint = polar ? { + plotX: point.rectPlotX, + plotY: point.yBottom, + doCurve: false // #5186, gaps in areasplinerange fill + } : { + plotX: point.plotX, + plotY: point.plotY, + doCurve: false // #5186, gaps in areasplinerange fill + }; + if (!point.isNull && + !connectEnds && + !connectNulls && + (!points[i + 1] || points[i + 1].isNull)) { + highAreaPoints.push(highAreaPoint); + } + pointShim = { + polarPlotY: point.polarPlotY, + rectPlotX: point.rectPlotX, + yBottom: point.yBottom, + // plotHighX is for polar charts + plotX: pick(point.plotHighX, point.plotX), + plotY: point.plotHigh, + isNull: point.isNull + }; + highAreaPoints.push(pointShim); + highPoints.push(pointShim); + if (!point.isNull && + !connectEnds && + !connectNulls && + (!points[i - 1] || points[i - 1].isNull)) { + highAreaPoints.push(highAreaPoint); + } + } + // Get the paths + lowerPath = getGraphPath.call(this, points); + if (step) { + if (step === true) { + step = 'left'; + } + options.step = { + left: 'right', + center: 'center', + right: 'left' + }[step]; // swap for reading in getGraphPath + } + higherPath = getGraphPath.call(this, highPoints); + higherAreaPath = getGraphPath.call(this, highAreaPoints); + options.step = step; + // Create a line on both top and bottom of the range + linePath = [] + .concat(lowerPath, higherPath); + // For the area path, we need to change the 'move' statement + // into 'lineTo' + if (!this.chart.polar && higherAreaPath[0] && higherAreaPath[0][0] === 'M') { + // This probably doesn't work for spline + higherAreaPath[0] = ['L', higherAreaPath[0][1], higherAreaPath[0][2]]; + } + this.graphPath = linePath; + this.areaPath = lowerPath.concat(higherAreaPath); + // Prepare for sideways animation + linePath.isArea = true; + linePath.xMap = lowerPath.xMap; + this.areaPath.xMap = lowerPath.xMap; + return linePath; + }, + /** + * Extend the basic drawDataLabels method by running it for both lower and + * higher values. + * @private + */ + drawDataLabels: function () { + var data = this.points, + length = data.length, + i, + originalDataLabels = [], + dataLabelOptions = this.options.dataLabels, + point, + up, + inverted = this.chart.inverted, + upperDataLabelOptions, + lowerDataLabelOptions; + // Split into upper and lower options. If data labels is an array, the + // first element is the upper label, the second is the lower. + // + // TODO: We want to change this and allow multiple labels for both upper + // and lower values in the future - introducing some options for which + // point value to use as Y for the dataLabel, so that this could be + // handled in Series.drawDataLabels. This would also improve performance + // since we now have to loop over all the points multiple times to work + // around the data label logic. + if (isArray(dataLabelOptions)) { + if (dataLabelOptions.length > 1) { + upperDataLabelOptions = dataLabelOptions[0]; + lowerDataLabelOptions = dataLabelOptions[1]; + } + else { + upperDataLabelOptions = dataLabelOptions[0]; + lowerDataLabelOptions = { enabled: false }; + } + } + else { + // Make copies + upperDataLabelOptions = extend({}, dataLabelOptions); + upperDataLabelOptions.x = dataLabelOptions.xHigh; + upperDataLabelOptions.y = dataLabelOptions.yHigh; + lowerDataLabelOptions = extend({}, dataLabelOptions); + lowerDataLabelOptions.x = dataLabelOptions.xLow; + lowerDataLabelOptions.y = dataLabelOptions.yLow; + } + // Draw upper labels + if (upperDataLabelOptions.enabled || this._hasPointLabels) { + // Set preliminary values for plotY and dataLabel + // and draw the upper labels + i = length; + while (i--) { + point = data[i]; + if (point) { + up = upperDataLabelOptions.inside ? + point.plotHigh < point.plotLow : + point.plotHigh > point.plotLow; + point.y = point.high; + point._plotY = point.plotY; + point.plotY = point.plotHigh; + // Store original data labels and set preliminary label + // objects to be picked up in the uber method + originalDataLabels[i] = point.dataLabel; + point.dataLabel = point.dataLabelUpper; + // Set the default offset + point.below = up; + if (inverted) { + if (!upperDataLabelOptions.align) { + upperDataLabelOptions.align = up ? 'right' : 'left'; + } + } + else { + if (!upperDataLabelOptions.verticalAlign) { + upperDataLabelOptions.verticalAlign = up ? + 'top' : + 'bottom'; + } + } + } + } + this.options.dataLabels = upperDataLabelOptions; + if (seriesProto.drawDataLabels) { + // #1209: + seriesProto.drawDataLabels.apply(this, arguments); + } + // Reset state after the upper labels were created. Move + // it to point.dataLabelUpper and reassign the originals. + // We do this here to support not drawing a lower label. + i = length; + while (i--) { + point = data[i]; + if (point) { + point.dataLabelUpper = point.dataLabel; + point.dataLabel = originalDataLabels[i]; + delete point.dataLabels; + point.y = point.low; + point.plotY = point._plotY; + } + } + } + // Draw lower labels + if (lowerDataLabelOptions.enabled || this._hasPointLabels) { + i = length; + while (i--) { + point = data[i]; + if (point) { + up = lowerDataLabelOptions.inside ? + point.plotHigh < point.plotLow : + point.plotHigh > point.plotLow; + // Set the default offset + point.below = !up; + if (inverted) { + if (!lowerDataLabelOptions.align) { + lowerDataLabelOptions.align = up ? 'left' : 'right'; + } + } + else { + if (!lowerDataLabelOptions.verticalAlign) { + lowerDataLabelOptions.verticalAlign = up ? + 'bottom' : + 'top'; + } + } + } + } + this.options.dataLabels = lowerDataLabelOptions; + if (seriesProto.drawDataLabels) { + seriesProto.drawDataLabels.apply(this, arguments); + } + } + // Merge upper and lower into point.dataLabels for later destroying + if (upperDataLabelOptions.enabled) { + i = length; + while (i--) { + point = data[i]; + if (point) { + point.dataLabels = [ + point.dataLabelUpper, + point.dataLabel + ].filter(function (label) { + return !!label; + }); + } + } + } + // Reset options + this.options.dataLabels = dataLabelOptions; + }, + alignDataLabel: function () { + seriesTypes.column.prototype.alignDataLabel + .apply(this, arguments); + }, + drawPoints: function () { + var series = this, + pointLength = series.points.length, + point, + i; + // Draw bottom points + seriesProto.drawPoints + .apply(series, arguments); + // Prepare drawing top points + i = 0; + while (i < pointLength) { + point = series.points[i]; + // Save original props to be overridden by temporary props for top + // points + point.origProps = { + plotY: point.plotY, + plotX: point.plotX, + isInside: point.isInside, + negative: point.negative, + zone: point.zone, + y: point.y + }; + point.lowerGraphic = point.graphic; + point.graphic = point.upperGraphic; + point.plotY = point.plotHigh; + if (defined(point.plotHighX)) { + point.plotX = point.plotHighX; + } + point.y = point.high; + point.negative = point.high < (series.options.threshold || 0); + point.zone = (series.zones.length && point.getZone()); + if (!series.chart.polar) { + point.isInside = point.isTopInside = (typeof point.plotY !== 'undefined' && + point.plotY >= 0 && + point.plotY <= series.yAxis.len && // #3519 + point.plotX >= 0 && + point.plotX <= series.xAxis.len); + } + i++; + } + // Draw top points + seriesProto.drawPoints.apply(series, arguments); + // Reset top points preliminary modifications + i = 0; + while (i < pointLength) { + point = series.points[i]; + point.upperGraphic = point.graphic; + point.graphic = point.lowerGraphic; + extend(point, point.origProps); + delete point.origProps; + i++; + } + }, + /* eslint-enable valid-jsdoc */ + setStackedPoints: noop + }, { + /** + * Range series only. The high or maximum value for each data point. + * @name Highcharts.Point#high + * @type {number|undefined} + */ + /** + * Range series only. The low or minimum value for each data point. + * @name Highcharts.Point#low + * @type {number|undefined} + */ + /* eslint-disable valid-jsdoc */ + /** + * @private + */ + setState: function () { + var prevState = this.state, + series = this.series, + isPolar = series.chart.polar; + if (!defined(this.plotHigh)) { + // Boost doesn't calculate plotHigh + this.plotHigh = series.yAxis.toPixels(this.high, true); + } + if (!defined(this.plotLow)) { + // Boost doesn't calculate plotLow + this.plotLow = this.plotY = series.yAxis.toPixels(this.low, true); + } + if (series.stateMarkerGraphic) { + series.lowerStateMarkerGraphic = series.stateMarkerGraphic; + series.stateMarkerGraphic = series.upperStateMarkerGraphic; + } + // Change state also for the top marker + this.graphic = this.upperGraphic; + this.plotY = this.plotHigh; + if (isPolar) { + this.plotX = this.plotHighX; + } + // Top state: + pointProto.setState.apply(this, arguments); + this.state = prevState; + // Now restore defaults + this.plotY = this.plotLow; + this.graphic = this.lowerGraphic; + if (isPolar) { + this.plotX = this.plotLowX; + } + if (series.stateMarkerGraphic) { + series.upperStateMarkerGraphic = series.stateMarkerGraphic; + series.stateMarkerGraphic = series.lowerStateMarkerGraphic; + // Lower marker is stored at stateMarkerGraphic + // to avoid reference duplication (#7021) + series.lowerStateMarkerGraphic = void 0; + } + pointProto.setState.apply(this, arguments); + }, + haloPath: function () { + var isPolar = this.series.chart.polar, + path = []; + // Bottom halo + this.plotY = this.plotLow; + if (isPolar) { + this.plotX = this.plotLowX; + } + if (this.isInside) { + path = pointProto.haloPath.apply(this, arguments); + } + // Top halo + this.plotY = this.plotHigh; + if (isPolar) { + this.plotX = this.plotHighX; + } + if (this.isTopInside) { + path = path.concat(pointProto.haloPath.apply(this, arguments)); + } + return path; + }, + destroyElements: function () { + var graphics = ['lowerGraphic', 'upperGraphic']; + graphics.forEach(function (graphicName) { + if (this[graphicName]) { + this[graphicName] = + this[graphicName].destroy(); + } + }, this); + // Clear graphic for states, removed in the above each: + this.graphic = null; + return pointProto.destroyElements.apply(this, arguments); + }, + isValid: function () { + return isNumber(this.low) && isNumber(this.high); + } + /* eslint-enable valid-jsdoc */ + }); + /** + * A `arearange` series. If the [type](#series.arearange.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * + * @extends series,plotOptions.arearange + * @excluding dataParser, dataURL, stack, stacking + * @product highcharts highstock + * @requires highcharts-more + * @apioption series.arearange + */ + /** + * An array of data points for the series. For the `arearange` series type, + * points can be given in the following ways: + * + * 1. An array of arrays with 3 or 2 values. In this case, the values + * correspond to `x,low,high`. If the first value is a string, it is + * applied as the name of the point, and the `x` value is inferred. + * The `x` value can also be omitted, in which case the inner arrays + * should be of length 2\. Then the `x` value is automatically calculated, + * either starting at 0 and incremented by 1, or from `pointStart` + * and `pointInterval` given in the series options. + * ```js + * data: [ + * [0, 8, 3], + * [1, 1, 1], + * [2, 6, 8] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.arearange.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * x: 1, + * low: 9, + * high: 0, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * low: 3, + * high: 4, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|Array<(number|string),number,number>|*>} + * @extends series.line.data + * @excluding marker, y + * @product highcharts highstock + * @apioption series.arearange.data + */ + /** + * @extends series.arearange.dataLabels + * @product highcharts highstock + * @apioption series.arearange.data.dataLabels + */ + /** + * The high or maximum value for each data point. + * + * @type {number} + * @product highcharts highstock + * @apioption series.arearange.data.high + */ + /** + * The low or minimum value for each data point. + * + * @type {number} + * @product highcharts highstock + * @apioption series.arearange.data.low + */ + ''; // adds doclets above to tranpiled file + + }); + _registerModule(_modules, 'Series/DumbbellSeries.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Sebastian Bochan, Rafal Sebestjanski + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var SVGRenderer = H.SVGRenderer; + var extend = U.extend, + pick = U.pick, + seriesType = U.seriesType; + var seriesTypes = H.seriesTypes, + seriesProto = H.Series.prototype, + areaRangeProto = seriesTypes.arearange.prototype, + columnRangeProto = seriesTypes.columnrange.prototype, + colProto = seriesTypes.column.prototype, + areaRangePointProto = areaRangeProto.pointClass.prototype; + /** + * The dumbbell series is a cartesian series with higher and lower values for + * each point along an X axis, connected with a line between the values. + * Requires `highcharts-more.js` and `modules/dumbbell.js`. + * + * @sample {highcharts} highcharts/demo/dumbbell/ + * Dumbbell chart + * @sample {highcharts} highcharts/series-dumbbell/styled-mode-dumbbell/ + * Styled mode + * + * @extends plotOptions.arearange + * @product highcharts highstock + * @excluding fillColor, fillOpacity, lineWidth, stack, stacking, + * stickyTracking, trackByArea, boostThreshold, boostBlending + * @since 8.0.0 + * @optionparent plotOptions.dumbbell + */ + seriesType('dumbbell', 'arearange', { + /** @ignore-option */ + trackByArea: false, + /** @ignore-option */ + fillColor: 'none', + /** @ignore-option */ + lineWidth: 0, + pointRange: 1, + /** + * Pixel width of the line that connects the dumbbell point's values. + * + * @since 8.0.0 + * @product highcharts highstock + */ + connectorWidth: 1, + /** @ignore-option */ + stickyTracking: false, + groupPadding: 0.2, + crisp: false, + pointPadding: 0.1, + /** + * Color of the start markers in a dumbbell graph. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 8.0.0 + * @product highcharts highstock + */ + lowColor: '#333333', + /** + * Color of the line that connects the dumbbell point's values. + * By default it is the series' color. + * + * @type {string} + * @product highcharts highstock + * @since 8.0.0 + * @apioption plotOptions.dumbbell.connectorColor + */ + states: { + hover: { + /** @ignore-option */ + lineWidthPlus: 0, + /** + * The additional connector line width for a hovered point. + * + * @since 8.0.0 + * @product highcharts highstock + */ + connectorWidthPlus: 1, + /** @ignore-option */ + halo: false + } + } + }, { + trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'], + drawTracker: H.TrackerMixin.drawTrackerPoint, + drawGraph: H.noop, + crispCol: colProto.crispCol, + /** + * Get connector line path and styles that connects dumbbell point's low and + * high values. + * @private + * + * @param {Highcharts.Series} this The series of points. + * @param {Highcharts.Point} point The point to inspect. + * + * @return {Highcharts.SVGAttributes} attribs The path and styles. + */ + getConnectorAttribs: function (point) { + var series = this, + chart = series.chart, + pointOptions = point.options, + seriesOptions = series.options, + xAxis = series.xAxis, + yAxis = series.yAxis, + connectorWidth = pick(pointOptions.connectorWidth, + seriesOptions.connectorWidth), + connectorColor = pick(pointOptions.connectorColor, + seriesOptions.connectorColor, + pointOptions.color, + point.zone ? point.zone.color : void 0, + point.color), + connectorWidthPlus = pick(seriesOptions.states && + seriesOptions.states.hover && + seriesOptions.states.hover.connectorWidthPlus, 1), + dashStyle = pick(pointOptions.dashStyle, + seriesOptions.dashStyle), + pointTop = pick(point.plotLow, + point.plotY), + pxThreshold = yAxis.toPixels(seriesOptions.threshold || 0, + true), + pointHeight = chart.inverted ? + yAxis.len - pxThreshold : pxThreshold, + pointBottom = pick(point.plotHigh, + pointHeight), + attribs, + origProps; + if (point.state) { + connectorWidth = connectorWidth + connectorWidthPlus; + } + if (pointTop < 0) { + pointTop = 0; + } + else if (pointTop >= yAxis.len) { + pointTop = yAxis.len; + } + if (pointBottom < 0) { + pointBottom = 0; + } + else if (pointBottom >= yAxis.len) { + pointBottom = yAxis.len; + } + if (point.plotX < 0 || point.plotX > xAxis.len) { + connectorWidth = 0; + } + // Connector should reflect upper marker's zone color + if (point.upperGraphic) { + origProps = { + y: point.y, + zone: point.zone + }; + point.y = point.high; + point.zone = point.zone ? point.getZone() : void 0; + connectorColor = pick(pointOptions.connectorColor, seriesOptions.connectorColor, pointOptions.color, point.zone ? point.zone.color : void 0, point.color); + extend(point, origProps); + } + attribs = { + d: SVGRenderer.prototype.crispLine([[ + 'M', + point.plotX, + pointTop + ], [ + 'L', + point.plotX, + pointBottom + ]], connectorWidth, 'ceil') + }; + if (!chart.styledMode) { + attribs.stroke = connectorColor; + attribs['stroke-width'] = connectorWidth; + if (dashStyle) { + attribs.dashstyle = dashStyle; + } + } + return attribs; + }, + /** + * Draw connector line that connects dumbbell point's low and high values. + * @private + * + * @param {Highcharts.Series} this The series of points. + * @param {Highcharts.Point} point The point to inspect. + * + * @return {void} + */ + drawConnector: function (point) { + var series = this, + animationLimit = pick(series.options.animationLimit, 250), + verb = point.connector && series.chart.pointCount < animationLimit ? + 'animate' : 'attr'; + if (!point.connector) { + point.connector = series.chart.renderer.path() + .addClass('highcharts-lollipop-stem') + .attr({ + zIndex: -1 + }) + .add(series.markerGroup); + } + point.connector[verb](this.getConnectorAttribs(point)); + }, + /** + * Return the width and x offset of the dumbbell adjusted for grouping, + * groupPadding, pointPadding, pointWidth etc. + * + * @private + * + * @function Highcharts.seriesTypes.column#getColumnMetrics + * + * @param {Highcharts.Series} this The series of points. + * + * @return {Highcharts.ColumnMetricsObject} metrics shapeArgs + * + */ + getColumnMetrics: function () { + var metrics = colProto.getColumnMetrics.apply(this, + arguments); + metrics.offset += metrics.width / 2; + return metrics; + }, + translatePoint: areaRangeProto.translate, + setShapeArgs: columnRangeProto.translate, + /** + * Translate each point to the plot area coordinate system and find + * shape positions + * + * @private + * + * @function Highcharts.seriesTypes.dumbbell#translate + * + * @param {Highcharts.Series} this The series of points. + * + * @return {void} + */ + translate: function () { + // Calculate shapeargs + this.setShapeArgs.apply(this); + // Calculate point low / high values + this.translatePoint.apply(this, arguments); + // Correct x position + this.points.forEach(function (point) { + var shapeArgs = point.shapeArgs, + pointWidth = point.pointWidth; + point.plotX = shapeArgs.x; + shapeArgs.x = point.plotX - pointWidth / 2; + point.tooltipPos = null; + }); + this.columnMetrics.offset -= this.columnMetrics.width / 2; + }, + seriesDrawPoints: areaRangeProto.drawPoints, + /** + * Extend the arearange series' drawPoints method by applying a connector + * and coloring markers. + * @private + * + * @function Highcharts.Series#drawPoints + * + * @param {Highcharts.Series} this The series of points. + * + * @return {void} + */ + drawPoints: function () { + var series = this, + chart = series.chart, + pointLength = series.points.length, + seriesLowColor = series.lowColor = series.options.lowColor, + i = 0, + lowerGraphicColor, + point, + zoneColor; + this.seriesDrawPoints.apply(series, arguments); + // Draw connectors and color upper markers + while (i < pointLength) { + point = series.points[i]; + series.drawConnector(point); + if (point.upperGraphic) { + point.upperGraphic.element.point = point; + point.upperGraphic.addClass('highcharts-lollipop-high'); + } + point.connector.element.point = point; + if (point.lowerGraphic) { + zoneColor = point.zone && point.zone.color; + lowerGraphicColor = pick(point.options.lowColor, seriesLowColor, point.options.color, zoneColor, point.color, series.color); + if (!chart.styledMode) { + point.lowerGraphic.attr({ + fill: lowerGraphicColor + }); + } + point.lowerGraphic.addClass('highcharts-lollipop-low'); + } + i++; + } + }, + /** + * Get non-presentational attributes for a point. Used internally for + * both styled mode and classic. Set correct position in link with connector + * line. + * + * @see Series#pointAttribs + * + * @function Highcharts.Series#markerAttribs + * + * @param {Highcharts.Series} this The series of points. + * + * @return {Highcharts.SVGAttributes} + * A hash containing those attributes that are not settable from + * CSS. + */ + markerAttribs: function () { + var ret = areaRangeProto.markerAttribs.apply(this, + arguments); + ret.x = Math.floor(ret.x); + ret.y = Math.floor(ret.y); + return ret; + }, + /** + * Get presentational attributes + * + * @private + * @function Highcharts.seriesTypes.column#pointAttribs + * + * @param {Highcharts.Series} this The series of points. + * @param {Highcharts.Point} point The point to inspect. + * @param {string} state current state of point (normal, hover, select) + * + * @return {Highcharts.SVGAttributes} pointAttribs SVGAttributes + */ + pointAttribs: function (point, state) { + var pointAttribs; + pointAttribs = seriesProto.pointAttribs.apply(this, arguments); + if (state === 'hover') { + delete pointAttribs.fill; + } + return pointAttribs; + } + }, { + // seriesTypes doesn't inherit from arearange point proto so put below + // methods rigidly. + destroyElements: areaRangePointProto.destroyElements, + isValid: areaRangePointProto.isValid, + pointSetState: areaRangePointProto.setState, + /** + * Set the point's state extended by have influence on the connector + * (between low and high value). + * + * @private + * @param {Highcharts.Point} this The point to inspect. + * + * @return {void} + */ + setState: function () { + var point = this, + series = point.series, + chart = series.chart, + seriesLowColor = series.options.lowColor, + seriesMarker = series.options.marker, + pointOptions = point.options, + pointLowColor = pointOptions.lowColor, + zoneColor = point.zone && point.zone.color, + lowerGraphicColor = pick(pointLowColor, + seriesLowColor, + pointOptions.color, + zoneColor, + point.color, + series.color), + verb = 'attr', + upperGraphicColor, + origProps; + this.pointSetState.apply(this, arguments); + if (!point.state) { + verb = 'animate'; + if (point.lowerGraphic && !chart.styledMode) { + point.lowerGraphic.attr({ + fill: lowerGraphicColor + }); + if (point.upperGraphic) { + origProps = { + y: point.y, + zone: point.zone + }; + point.y = point.high; + point.zone = point.zone ? point.getZone() : void 0; + upperGraphicColor = pick(point.marker ? point.marker.fillColor : void 0, seriesMarker ? seriesMarker.fillColor : void 0, pointOptions.color, point.zone ? point.zone.color : void 0, point.color); + point.upperGraphic.attr({ + fill: upperGraphicColor + }); + extend(point, origProps); + } + } + } + point.connector[verb](series.getConnectorAttribs(point)); + } + }); + /** + * The `dumbbell` series. If the [type](#series.dumbbell.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.dumbbell + * @excluding boostThreshold, boostBlending + * @product highcharts highstock + * @requires highcharts-more + * @requires modules/dumbbell + * @apioption series.dumbbell + */ + /** + * An array of data points for the series. For the `dumbbell` series + * type, points can be given in the following ways: + * + * 1. An array of arrays with 3 or 2 values. In this case, the values correspond + * to `x,low,high`. If the first value is a string, it is applied as the name + * of the point, and the `x` value is inferred. The `x` value can also be + * omitted, in which case the inner arrays should be of length 2\. Then the + * `x` value is automatically calculated, either starting at 0 and + * incremented by 1, or from `pointStart` and `pointInterval` given in the + * series options. + * ```js + * data: [ + * [0, 4, 2], + * [1, 2, 1], + * [2, 9, 10] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.dumbbell.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * low: 0, + * high: 4, + * name: "Point2", + * color: "#00FF00", + * lowColor: "#00FFFF", + * connectorWidth: 3, + * connectorColor: "#FF00FF" + * }, { + * x: 1, + * low: 5, + * high: 3, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|Array<(number|string),number,number>|*>} + * @extends series.arearange.data + * @product highcharts highstock + * @apioption series.dumbbell.data + */ + /** + * Color of the line that connects the dumbbell point's values. + * By default it is the series' color. + * + * @type {string} + * @since 8.0.0 + * @product highcharts highstock + * @apioption series.dumbbell.data.connectorColor + */ + /** + * Pixel width of the line that connects the dumbbell point's values. + * + * @type {number} + * @since 8.0.0 + * @default 1 + * @product highcharts highstock + * @apioption series.dumbbell.data.connectorWidth + */ + /** + * Color of the start markers in a dumbbell graph. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 8.0.0 + * @default #333333 + * @product highcharts highstock + * @apioption series.dumbbell.data.lowColor + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/dumbbell.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/export-data.js b/highcharts/modules/export-data.js new file mode 100644 index 0000000..f16ac91 --- /dev/null +++ b/highcharts/modules/export-data.js @@ -0,0 +1,30 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Exporting module + + (c) 2010-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/export-data",["highcharts","highcharts/modules/exporting"],function(g){a(g);a.Highcharts=g;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function g(a,d,e,c){a.hasOwnProperty(d)||(a[d]=c.apply(null,e))}a=a?a._modules:{};g(a,"Extensions/DownloadURL.js",[a["Core/Globals.js"]],function(a){var d=a.win,e=d.navigator,c=d.document, +g=d.URL||d.webkitURL||d,u=/Edge\/\d+/.test(e.userAgent),v=a.dataURLtoBlob=function(f){if((f=f.match(/data:([^;]*)(;base64)?,([0-9A-Za-z+/]+)/))&&3b.userAgent.indexOf("Chrome"),c=p.URL||p.webkitURL||p;try{if(b.msSaveOrOpenBlob&&p.MSBlobBuilder){var q=new p.MSBlobBuilder;q.append(a);return q.getBlob("image/svg+xml")}if(!f)return c.createObjectURL(new p.Blob(["\ufeff"+a],{type:d}))}catch(M){}}var v=e.doc,f=e.seriesTypes,p=e.win;e=c.addEvent;var I=c.defined,J=c.extend,E=c.find,D= +c.fireEvent,K=c.getOptions,L=c.isNumber,w=c.pick;c=c.setOptions;var F=g.downloadURL;c({exporting:{csv:{annotations:{itemDelimiter:"; ",join:!1},columnHeaderFormatter:null,dateFormat:"%Y-%m-%d %H:%M:%S",decimalPoint:null,itemDelimiter:null,lineDelimiter:"\n"},showTable:!1,useMultiLevelHeaders:!0,useRowspanHeaders:!0},lang:{downloadCSV:"Descargar en CSV",downloadXLS:"Descargar en XLS",exportData:{annotationHeader:"Annotations",categoryHeader:"Categoria",categoryDatetimeHeader:"DateTime"},viewData:"Ver tabla de datos", +hideData:"Ocultar tabla de datos"}});e(d,"render",function(){this.options&&this.options.exporting&&this.options.exporting.showTable&&!this.options.chart.forExport&&!this.dataTableDiv&&this.viewData()});d.prototype.setUpKeyToAxis=function(){f.arearange&&(f.arearange.prototype.keyToAxis={low:"y",high:"y"});f.gantt&&(f.gantt.prototype.keyToAxis={start:"x",end:"x"})};d.prototype.getDataRows=function(b){var d=this.hasParallelCoordinates,f=this.time,c=this.options.exporting&&this.options.exporting.csv||{},e=this.xAxis, +q={},g=[],p=[],n=[],r;var t=this.options.lang.exportData;var A=t.categoryHeader,x=t.categoryDatetimeHeader,G=function(l,d,f){if(c.columnHeaderFormatter){var h=c.columnHeaderFormatter(l,d,f);if(!1!==h)return h}return l?l instanceof a?l.options.title&&l.options.title.text||(l.dateTime?x:A):b?{columnTitle:1',c=this.options,d=a?(1.1).toLocaleString()[1]:".",f=w(c.exporting.useMultiLevelHeaders,!0);a=this.getDataRows(f);var e=0,g=f?a.shift():null,p=a.shift(),n=function(a,b,c,f){var e=w(f,""); +b="text"+(b?" "+b:"");"number"===typeof e?(e=e.toString(),","===d&&(e=e.replace(".",d)),b="number"):f||(b="empty");return"<"+a+(c?" "+c:"")+' class="'+b+'">'+e+""};!1!==c.exporting.tableCaption&&(b+=''+w(c.exporting.tableCaption,c.title.text?c.title.text.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/"):"Chart")+"");for(var r=0,t=a.length;r +e&&(e=a[r].length);b+=function(a,b,d){var e="",g=0;d=d||b&&b.length;var h,k=0;if(h=f&&a&&b){a:if(h=a.length,b.length===h){for(;h--;)if(a[h]!==b[h]){h=!1;break a}h=!0}else h=!1;h=!h}if(h){for(e+="";g"}return e+""}(g,p,Math.max(e,p.length));b+="";a.forEach(function(a){b+="";for(var c=0;c"});b+="";a={html:b};D(this,"afterGetTable",a);return a.html};d.prototype.downloadCSV=function(){var a=this.getCSV(!0);F(u(a,"text/csv")||"data:text/csv,\ufeff"+encodeURIComponent(a),this.getFilename()+ +".csv")};d.prototype.downloadXLS=function(){var a='\x3c!--[if gte mso 9]>Ark1td{border:none;font-family: Calibri, sans-serif;} .number{mso-number-format:"0.00";} .text{ mso-number-format:"@";}'+ +this.getTable(!0)+"";F(u(a,"application/vnd.ms-excel")||"data:application/vnd.ms-excel;base64,"+p.btoa(unescape(encodeURIComponent(a))),this.getFilename()+".xls")};d.prototype.viewData=function(){this.dataTableDiv||(this.dataTableDiv=v.createElement("div"),this.dataTableDiv.className="highcharts-data-table",this.renderTo.parentNode.insertBefore(this.dataTableDiv,this.renderTo.nextSibling),this.dataTableDiv.innerHTML=this.getTable());if(""===this.dataTableDiv.style.display||"none"=== +this.dataTableDiv.style.display)this.dataTableDiv.style.display="block";this.isDataTableVisible=!0;D(this,"afterViewData",this.dataTableDiv)};d.prototype.hideData=function(){this.dataTableDiv&&"block"===this.dataTableDiv.style.display&&(this.dataTableDiv.style.display="none");this.isDataTableVisible=!1};d.prototype.toggleDataTable=function(){var a,c=this.exportDivElements,d=null===(a=null===n||void 0===n?void 0:n.buttons)||void 0===a?void 0:a.contextButton.menuItems;a=this.options.lang;this.isDataTableVisible? +this.hideData():this.viewData();(null===n||void 0===n?0:n.menuItemDefinitions)&&(null===a||void 0===a?0:a.viewData)&&a.hideData&&d&&c&&c.length&&(c[d.indexOf("viewData")].innerHTML=this.isDataTableVisible?a.hideData:a.viewData)};var n=K().exporting;n&&(J(n.menuItemDefinitions,{downloadCSV:{textKey:"downloadCSV",onclick:function(){this.downloadCSV()}},downloadXLS:{textKey:"downloadXLS",onclick:function(){this.downloadXLS()}},viewData:{textKey:"viewData",onclick:function(){this.toggleDataTable()}}}), +n.buttons&&n.buttons.contextButton.menuItems.push("separator","downloadCSV","downloadXLS","viewData"));f.map&&(f.map.prototype.exportKey="name");f.mapbubble&&(f.mapbubble.prototype.exportKey="name");f.treemap&&(f.treemap.prototype.exportKey="name")});g(a,"masters/modules/export-data.src.js",[],function(){})}); +//# sourceMappingURL=export-data.js.map \ No newline at end of file diff --git a/highcharts/modules/export-data.js.map b/highcharts/modules/export-data.js.map new file mode 100644 index 0000000..7060a30 --- /dev/null +++ b/highcharts/modules/export-data.js.map @@ -0,0 +1 @@ +{"version":3,"file":"export-data.js.map","lineCount":29,"mappings":"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","sources":["export-data.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","win","nav","navigator","doc","document","domurl","URL","webkitURL","isEdgeBrowser","test","userAgent","dataURLtoBlob","Highcharts.dataURLtoBlob","dataURL","parts","match","length","atob","ArrayBuffer","Uint8Array","Blob","createObjectURL","binStr","buf","binary","i","charCodeAt","blob","downloadURL","Highcharts.downloadURL","filename","a","createElement","String","msSaveOrOpenBlob","Error","download","href","body","appendChild","click","removeChild","windowRef","open","e","location","Axis","Chart","H","U","DownloadURL","getBlobFromContent","content","type","webKit","indexOf","MSBlobBuilder","append","getBlob","seriesTypes","addEvent","defined","extend","find","fireEvent","getOptions","isNumber","pick","setOptions","exporting","csv","annotations","itemDelimiter","join","columnHeaderFormatter","dateFormat","decimalPoint","lineDelimiter","showTable","useMultiLevelHeaders","useRowspanHeaders","lang","downloadCSV","downloadXLS","exportData","annotationHeader","categoryHeader","categoryDatetimeHeader","viewData","hideData","options","chart","forExport","dataTableDiv","prototype","setUpKeyToAxis","Chart.prototype.setUpKeyToAxis","arearange","keyToAxis","low","high","gantt","start","end","getDataRows","Chart.prototype.getDataRows","multiLevelHeaders","hasParallelCoords","hasParallelCoordinates","time","csvOptions","xAxes","xAxis","rows","rowArr","topLevelColumnTitles","columnTitles","columnTitleObj","exportDataOptions","item","key","keyLength","s","title","text","dateTime","columnTitle","name","topLevelColumnTitle","getCategoryAndDateTimeMap","series","pointArrayMap","pIdx","categoryMap","dateTimeValueAxisMap","forEach","prop","axisName","axis","categories","getPointArray","data","filter","namedPoints","d","y","pointArrayMapCheck","p","unshift","xAxisIndices","keys","valueCount","xTaken","requireSorting","xAxisIndex","categoryAndDatetimeMap","j","includeInDataExport","isInternal","visible","index","push","mockSeries","autoIncrement","eachData","point","pointClass","applyOptions","x","exportKey","hasNames","xValues","val","Object","call","dataRows","column","sort","b","xTitle","splice","row","category","Date","getTime","names","concat","getCSV","Chart.prototype.getCSV","useLocalDecimalPoint","toLocaleString","toString","replace","getTable","Chart.prototype.getTable","html","rowLength","topHeaders","shift","subHeaders","getCellHTMLFromValue","tag","classes","attrs","value","className","tableCaption","len","getTableHeaderHTML","topheaders","subheaders","cur","curColspan","row1","row2","next","rowspan","Math","max","Chart.prototype.downloadCSV","encodeURIComponent","getFilename","Chart.prototype.downloadXLS","template","uri","btoa","unescape","Chart.prototype.viewData","renderTo","parentNode","insertBefore","nextSibling","innerHTML","style","display","isDataTableVisible","Chart.prototype.hideData","toggleDataTable","Chart.prototype.toggleDataTable","_a","exportDivElements","menuItems","exportingOptions","buttons","contextButton","menuItemDefinitions","textKey","onclick","map","mapbubble","treemap"]} \ No newline at end of file diff --git a/highcharts/modules/export-data.src.js b/highcharts/modules/export-data.src.js new file mode 100644 index 0000000..6eb2682 --- /dev/null +++ b/highcharts/modules/export-data.src.js @@ -0,0 +1,1124 @@ +/** + * @license Highcharts JS v8.2.0 (2020-08-20) + * + * Exporting module + * + * (c) 2010-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/export-data', ['highcharts', 'highcharts/modules/exporting'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'Extensions/DownloadURL.js', [_modules['Core/Globals.js']], function (Highcharts) { + /* * + * + * (c) 2015-2020 Oystein Moseng + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * Mixin for downloading content in the browser + * + * */ + var win = Highcharts.win, + nav = win.navigator, + doc = win.document, + domurl = win.URL || win.webkitURL || win, + isEdgeBrowser = /Edge\/\d+/.test(nav.userAgent); + /** + * Convert base64 dataURL to Blob if supported, otherwise returns undefined. + * @private + * @function Highcharts.dataURLtoBlob + * @param {string} dataURL + * URL to convert + * @return {string|undefined} + * Blob + */ + var dataURLtoBlob = Highcharts.dataURLtoBlob = function (dataURL) { + var parts = dataURL.match(/data:([^;]*)(;base64)?,([0-9A-Za-z+/]+)/); + if (parts && + parts.length > 3 && + win.atob && + win.ArrayBuffer && + win.Uint8Array && + win.Blob && + domurl.createObjectURL) { + // Try to convert data URL to Blob + var binStr = win.atob(parts[3]), + buf = new win.ArrayBuffer(binStr.length), + binary = new win.Uint8Array(buf), + blob; + for (var i = 0; i < binary.length; ++i) { + binary[i] = binStr.charCodeAt(i); + } + blob = new win.Blob([binary], { 'type': parts[1] }); + return domurl.createObjectURL(blob); + } + }; + /** + * Download a data URL in the browser. Can also take a blob as first param. + * + * @private + * @function Highcharts.downloadURL + * @param {string|global.URL} dataURL + * The dataURL/Blob to download + * @param {string} filename + * The name of the resulting file (w/extension) + * @return {void} + */ + var downloadURL = Highcharts.downloadURL = function (dataURL, + filename) { + var a = doc.createElement('a'), + windowRef; + // IE specific blob implementation + // Don't use for normal dataURLs + if (typeof dataURL !== 'string' && + !(dataURL instanceof String) && + nav.msSaveOrOpenBlob) { + nav.msSaveOrOpenBlob(dataURL, filename); + return; + } + dataURL = "" + dataURL; + // Some browsers have limitations for data URL lengths. Try to convert to + // Blob or fall back. Edge always needs that blob. + if (isEdgeBrowser || dataURL.length > 2000000) { + dataURL = dataURLtoBlob(dataURL) || ''; + if (!dataURL) { + throw new Error('Failed to convert to blob'); + } + } + // Try HTML5 download attr if supported + if (typeof a.download !== 'undefined') { + a.href = dataURL; + a.download = filename; // HTML5 download attribute + doc.body.appendChild(a); + a.click(); + doc.body.removeChild(a); + } + else { + // No download attr, just opening data URI + try { + windowRef = win.open(dataURL, 'chart'); + if (typeof windowRef === 'undefined' || windowRef === null) { + throw new Error('Failed to open window'); + } + } + catch (e) { + // window.open failed, trying location.href + win.location.href = dataURL; + } + } + }; + var exports = { + dataURLtoBlob: dataURLtoBlob, + downloadURL: downloadURL + }; + + return exports; + }); + _registerModule(_modules, 'Extensions/ExportData.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Chart/Chart.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js'], _modules['Extensions/DownloadURL.js']], function (Axis, Chart, H, U, DownloadURL) { + /* * + * + * Experimental data export module for Highcharts + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + // @todo + // - Set up systematic tests for all series types, paired with tests of the data + // module importing the same data. + var doc = H.doc, + seriesTypes = H.seriesTypes, + win = H.win; + var addEvent = U.addEvent, + defined = U.defined, + extend = U.extend, + find = U.find, + fireEvent = U.fireEvent, + getOptions = U.getOptions, + isNumber = U.isNumber, + pick = U.pick, + setOptions = U.setOptions; + /** + * Function callback to execute while data rows are processed for exporting. + * This allows the modification of data rows before processed into the final + * format. + * + * @callback Highcharts.ExportDataCallbackFunction + * @extends Highcharts.EventCallbackFunction + * + * @param {Highcharts.Chart} this + * Chart context where the event occured. + * + * @param {Highcharts.ExportDataEventObject} event + * Event object with data rows that can be modified. + */ + /** + * Contains information about the export data event. + * + * @interface Highcharts.ExportDataEventObject + */ /** + * Contains the data rows for the current export task and can be modified. + * @name Highcharts.ExportDataEventObject#dataRows + * @type {Array>} + */ + var downloadURL = DownloadURL.downloadURL; + // Can we add this to utils? Also used in screen-reader.js + /** + * HTML encode some characters vulnerable for XSS. + * @private + * @param {string} html The input string + * @return {string} The excaped string + */ + function htmlencode(html) { + return html + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(/\//g, '/'); + } + setOptions({ + /** + * Callback that fires while exporting data. This allows the modification of + * data rows before processed into the final format. + * + * @type {Highcharts.ExportDataCallbackFunction} + * @context Highcharts.Chart + * @requires modules/export-data + * @apioption chart.events.exportData + */ + /** + * When set to `false` will prevent the series data from being included in + * any form of data export. + * + * Since version 6.0.0 until 7.1.0 the option was existing undocumented + * as `includeInCSVExport`. + * + * @type {boolean} + * @since 7.1.0 + * @requires modules/export-data + * @apioption plotOptions.series.includeInDataExport + */ + /** + * @optionparent exporting + * @private + */ + exporting: { + /** + * Caption for the data table. Same as chart title by default. Set to + * `false` to disable. + * + * @sample highcharts/export-data/multilevel-table + * Multiple table headers + * + * @type {boolean|string} + * @since 6.0.4 + * @requires modules/export-data + * @apioption exporting.tableCaption + */ + /** + * Options for exporting data to CSV or ExCel, or displaying the data + * in a HTML table or a JavaScript structure. + * + * This module adds data export options to the export menu and provides + * functions like `Chart.getCSV`, `Chart.getTable`, `Chart.getDataRows` + * and `Chart.viewData`. + * + * The XLS converter is limited and only creates a HTML string that is + * passed for download, which works but creates a warning before + * opening. The workaround for this is to use a third party XLSX + * converter, as demonstrated in the sample below. + * + * @sample highcharts/export-data/categorized/ Categorized data + * @sample highcharts/export-data/stock-timeaxis/ Highstock time axis + * @sample highcharts/export-data/xlsx/ + * Using a third party XLSX converter + * + * @since 6.0.0 + * @requires modules/export-data + */ + csv: { + /** + * + * Options for annotations in the export-data table. + * + * @since 8.2.0 + * @requires modules/export-data + * @requires modules/annotations + * + * + */ + annotations: { + /** + * The way to mark the separator for annotations + * combined in one export-data table cell. + * + * @since 8.2.0 + * @requires modules/annotations + */ + itemDelimiter: '; ', + /** + * When several labels are assigned to a specific point, + * they will be displayed in one field in the table. + * + * @sample highcharts/export-data/join-annotations/ + * Concatenate point annotations with itemDelimiter set. + * + * @since 8.2.0 + * @requires modules/annotations + */ + join: false + }, + /** + * Formatter callback for the column headers. Parameters are: + * - `item` - The series or axis object) + * - `key` - The point key, for example y or z + * - `keyLength` - The amount of value keys for this item, for + * example a range series has the keys `low` and `high` so the + * key length is 2. + * + * If [useMultiLevelHeaders](#exporting.useMultiLevelHeaders) is + * true, columnHeaderFormatter by default returns an object with + * columnTitle and topLevelColumnTitle for each key. Columns with + * the same topLevelColumnTitle have their titles merged into a + * single cell with colspan for table/Excel export. + * + * If `useMultiLevelHeaders` is false, or for CSV export, it returns + * the series name, followed by the key if there is more than one + * key. + * + * For the axis it returns the axis title or "Category" or + * "DateTime" by default. + * + * Return `false` to use Highcharts' proposed header. + * + * @sample highcharts/export-data/multilevel-table + * Multiple table headers + * + * @type {Function|null} + */ + columnHeaderFormatter: null, + /** + * Which date format to use for exported dates on a datetime X axis. + * See `Highcharts.dateFormat`. + */ + dateFormat: '%Y-%m-%d %H:%M:%S', + /** + * Which decimal point to use for exported CSV. Defaults to the same + * as the browser locale, typically `.` (English) or `,` (German, + * French etc). + * + * @type {string|null} + * @since 6.0.4 + */ + decimalPoint: null, + /** + * The item delimiter in the exported data. Use `;` for direct + * exporting to Excel. Defaults to a best guess based on the browser + * locale. If the locale _decimal point_ is `,`, the `itemDelimiter` + * defaults to `;`, otherwise the `itemDelimiter` defaults to `,`. + * + * @type {string|null} + */ + itemDelimiter: null, + /** + * The line delimiter in the exported data, defaults to a newline. + */ + lineDelimiter: '\n' + }, + /** + * Show a HTML table below the chart with the chart's current data. + * + * @sample highcharts/export-data/showtable/ + * Show the table + * @sample highcharts/studies/exporting-table-html + * Experiment with putting the table inside the subtitle to + * allow exporting it. + * + * @since 6.0.0 + * @requires modules/export-data + */ + showTable: false, + /** + * Use multi level headers in data table. If [csv.columnHeaderFormatter + * ](#exporting.csv.columnHeaderFormatter) is defined, it has to return + * objects in order for multi level headers to work. + * + * @sample highcharts/export-data/multilevel-table + * Multiple table headers + * + * @since 6.0.4 + * @requires modules/export-data + */ + useMultiLevelHeaders: true, + /** + * If using multi level table headers, use rowspans for headers that + * have only one level. + * + * @sample highcharts/export-data/multilevel-table + * Multiple table headers + * + * @since 6.0.4 + * @requires modules/export-data + */ + useRowspanHeaders: true + }, + /** + * @optionparent lang + * + * @private + */ + lang: { + /** + * The text for the menu item. + * + * @since 6.0.0 + * @requires modules/export-data + */ + downloadCSV: 'Download CSV', + /** + * The text for the menu item. + * + * @since 6.0.0 + * @requires modules/export-data + */ + downloadXLS: 'Download XLS', + /** + * The text for exported table. + * + * @since 8.1.0 + * @requires modules/export-data + */ + exportData: { + /** + * The annotation column title. + */ + annotationHeader: 'Annotations', + /** + * The category column title. + */ + categoryHeader: 'Category', + /** + * The category column title when axis type set to "datetime". + */ + categoryDatetimeHeader: 'DateTime' + }, + /** + * The text for the menu item. + * + * @since 6.0.0 + * @requires modules/export-data + */ + viewData: 'View data table', + /** + * The text for the menu item. + * + * @since 8.2.0 + * @requires modules/export-data + */ + hideData: 'Hide data table' + } + }); + /* eslint-disable no-invalid-this */ + // Add an event listener to handle the showTable option + addEvent(Chart, 'render', function () { + if (this.options && + this.options.exporting && + this.options.exporting.showTable && + !this.options.chart.forExport && + !this.dataTableDiv) { + this.viewData(); + } + }); + /* eslint-enable no-invalid-this */ + /** + * Set up key-to-axis bindings. This is used when the Y axis is datetime or + * categorized. For example in an arearange series, the low and high values + * should be formatted according to the Y axis type, and in order to link them + * we need this map. + * + * @private + * @function Highcharts.Chart#setUpKeyToAxis + */ + Chart.prototype.setUpKeyToAxis = function () { + if (seriesTypes.arearange) { + seriesTypes.arearange.prototype.keyToAxis = { + low: 'y', + high: 'y' + }; + } + if (seriesTypes.gantt) { + seriesTypes.gantt.prototype.keyToAxis = { + start: 'x', + end: 'x' + }; + } + }; + /** + * Export-data module required. Returns a two-dimensional array containing the + * current chart data. + * + * @function Highcharts.Chart#getDataRows + * + * @param {boolean} [multiLevelHeaders] + * Use multilevel headers for the rows by default. Adds an extra row with + * top level headers. If a custom columnHeaderFormatter is defined, this + * can override the behavior. + * + * @return {Array>} + * The current chart data + * + * @fires Highcharts.Chart#event:exportData + */ + Chart.prototype.getDataRows = function (multiLevelHeaders) { + var hasParallelCoords = this.hasParallelCoordinates, + time = this.time, + csvOptions = ((this.options.exporting && this.options.exporting.csv) || {}), + xAxis, + xAxes = this.xAxis, + rows = {}, + rowArr = [], + dataRows, + topLevelColumnTitles = [], + columnTitles = [], + columnTitleObj, + i, + x, + xTitle, + langOptions = this.options.lang, + exportDataOptions = langOptions.exportData, + categoryHeader = exportDataOptions.categoryHeader, + categoryDatetimeHeader = exportDataOptions.categoryDatetimeHeader, + // Options + columnHeaderFormatter = function (item, + key, + keyLength) { + if (csvOptions.columnHeaderFormatter) { + var s = csvOptions.columnHeaderFormatter(item, + key, + keyLength); + if (s !== false) { + return s; + } + } + if (!item) { + return categoryHeader; + } + if (item instanceof Axis) { + return (item.options.title && item.options.title.text) || + (item.dateTime ? categoryDatetimeHeader : categoryHeader); + } + if (multiLevelHeaders) { + return { + columnTitle: keyLength > 1 ? + key : + item.name, + topLevelColumnTitle: item.name + }; + } + return item.name + (keyLength > 1 ? ' (' + key + ')' : ''); + }, + // Map the categories for value axes + getCategoryAndDateTimeMap = function (series, pointArrayMap, pIdx) { + var categoryMap = {}, + dateTimeValueAxisMap = {}; + pointArrayMap.forEach(function (prop) { + var axisName = ((series.keyToAxis && series.keyToAxis[prop]) || + prop) + 'Axis', + // Points in parallel coordinates refers to all yAxis + // not only `series.yAxis` + axis = isNumber(pIdx) ? + series.chart[axisName][pIdx] : + series[axisName]; + categoryMap[prop] = (axis && axis.categories) || []; + dateTimeValueAxisMap[prop] = (axis && axis.dateTime); + }); + return { + categoryMap: categoryMap, + dateTimeValueAxisMap: dateTimeValueAxisMap + }; + }, + // Create point array depends if xAxis is category + // or point.name is defined #13293 + getPointArray = function (series, xAxis) { + var namedPoints = series.data.filter(function (d) { + return (typeof d.y !== 'undefined') && d.name; + }); + if (namedPoints.length && + xAxis && + !xAxis.categories && + !series.keyToAxis) { + if (series.pointArrayMap) { + var pointArrayMapCheck = series.pointArrayMap.filter(function (p) { return p === 'x'; }); + if (pointArrayMapCheck.length) { + series.pointArrayMap.unshift('x'); + return series.pointArrayMap; + } + } + return ['x', 'y']; + } + return series.pointArrayMap || ['y']; + }, xAxisIndices = []; + // Loop the series and index values + i = 0; + this.setUpKeyToAxis(); + this.series.forEach(function (series) { + var keys = series.options.keys, + xAxis = series.xAxis, + pointArrayMap = keys || getPointArray(series, + xAxis), + valueCount = pointArrayMap.length, + xTaken = !series.requireSorting && {}, + xAxisIndex = xAxes.indexOf(xAxis), + categoryAndDatetimeMap = getCategoryAndDateTimeMap(series, + pointArrayMap), + mockSeries, + j; + if (series.options.includeInDataExport !== false && + !series.options.isInternal && + series.visible !== false // #55 + ) { + // Build a lookup for X axis index and the position of the first + // series that belongs to that X axis. Includes -1 for non-axis + // series types like pies. + if (!find(xAxisIndices, function (index) { + return index[0] === xAxisIndex; + })) { + xAxisIndices.push([xAxisIndex, i]); + } + // Compute the column headers and top level headers, usually the + // same as series names + j = 0; + while (j < valueCount) { + columnTitleObj = columnHeaderFormatter(series, pointArrayMap[j], pointArrayMap.length); + columnTitles.push(columnTitleObj.columnTitle || columnTitleObj); + if (multiLevelHeaders) { + topLevelColumnTitles.push(columnTitleObj.topLevelColumnTitle || + columnTitleObj); + } + j++; + } + mockSeries = { + chart: series.chart, + autoIncrement: series.autoIncrement, + options: series.options, + pointArrayMap: series.pointArrayMap + }; + // Export directly from options.data because we need the uncropped + // data (#7913), and we need to support Boost (#7026). + series.options.data.forEach(function eachData(options, pIdx) { + var key, + prop, + val, + name, + point; + // In parallel coordinates chart, each data point is connected + // to a separate yAxis, conform this + if (hasParallelCoords) { + categoryAndDatetimeMap = getCategoryAndDateTimeMap(series, pointArrayMap, pIdx); + } + point = { series: mockSeries }; + series.pointClass.prototype.applyOptions.apply(point, [options]); + key = point.x; + name = series.data[pIdx] && series.data[pIdx].name; + j = 0; + // Pies, funnels, geo maps etc. use point name in X row + if (!xAxis || + series.exportKey === 'name' || + (!hasParallelCoords && xAxis && xAxis.hasNames) && name) { + key = name; + } + if (xTaken) { + if (xTaken[key]) { + key += '|' + pIdx; + } + xTaken[key] = true; + } + if (!rows[key]) { + // Generate the row + rows[key] = []; + // Contain the X values from one or more X axes + rows[key].xValues = []; + } + rows[key].x = point.x; + rows[key].name = name; + rows[key].xValues[xAxisIndex] = point.x; + while (j < valueCount) { + prop = pointArrayMap[j]; // y, z etc + val = point[prop]; + rows[key][i + j] = pick( + // Y axis category if present + categoryAndDatetimeMap.categoryMap[prop][val], + // datetime yAxis + categoryAndDatetimeMap.dateTimeValueAxisMap[prop] ? + time.dateFormat(csvOptions.dateFormat, val) : + null, + // linear/log yAxis + val); + j++; + } + }); + i = i + j; + } + }); + // Make a sortable array + for (x in rows) { + if (Object.hasOwnProperty.call(rows, x)) { + rowArr.push(rows[x]); + } + } + var xAxisIndex, + column; + // Add computed column headers and top level headers to final row set + dataRows = multiLevelHeaders ? [topLevelColumnTitles, columnTitles] : + [columnTitles]; + i = xAxisIndices.length; + while (i--) { // Start from end to splice in + xAxisIndex = xAxisIndices[i][0]; + column = xAxisIndices[i][1]; + xAxis = xAxes[xAxisIndex]; + // Sort it by X values + rowArr.sort(function (// eslint-disable-line no-loop-func + a, b) { + return a.xValues[xAxisIndex] - b.xValues[xAxisIndex]; + }); + // Add header row + xTitle = columnHeaderFormatter(xAxis); + dataRows[0].splice(column, 0, xTitle); + if (multiLevelHeaders && dataRows[1]) { + // If using multi level headers, we just added top level header. + // Also add for sub level + dataRows[1].splice(column, 0, xTitle); + } + // Add the category column + rowArr.forEach(function (// eslint-disable-line no-loop-func + row) { + var category = row.name; + if (xAxis && !defined(category)) { + if (xAxis.dateTime) { + if (row.x instanceof Date) { + row.x = row.x.getTime(); + } + category = time.dateFormat(csvOptions.dateFormat, row.x); + } + else if (xAxis.categories) { + category = pick(xAxis.names[row.x], xAxis.categories[row.x], row.x); + } + else { + category = row.x; + } + } + // Add the X/date/category + row.splice(column, 0, category); + }); + } + dataRows = dataRows.concat(rowArr); + fireEvent(this, 'exportData', { dataRows: dataRows }); + return dataRows; + }; + /** + * Export-data module required. Returns the current chart data as a CSV string. + * + * @function Highcharts.Chart#getCSV + * + * @param {boolean} [useLocalDecimalPoint] + * Whether to use the local decimal point as detected from the browser. + * This makes it easier to export data to Excel in the same locale as the + * user is. + * + * @return {string} + * CSV representation of the data + */ + Chart.prototype.getCSV = function (useLocalDecimalPoint) { + var csv = '', rows = this.getDataRows(), csvOptions = this.options.exporting.csv, decimalPoint = pick(csvOptions.decimalPoint, csvOptions.itemDelimiter !== ',' && useLocalDecimalPoint ? + (1.1).toLocaleString()[1] : + '.'), + // use ';' for direct to Excel + itemDelimiter = pick(csvOptions.itemDelimiter, decimalPoint === ',' ? ';' : ','), + // '\n' isn't working with the js csv data extraction + lineDelimiter = csvOptions.lineDelimiter; + // Transform the rows to CSV + rows.forEach(function (row, i) { + var val = '', + j = row.length; + while (j--) { + val = row[j]; + if (typeof val === 'string') { + val = '"' + val + '"'; + } + if (typeof val === 'number') { + if (decimalPoint !== '.') { + val = val.toString().replace('.', decimalPoint); + } + } + row[j] = val; + } + // Add the values + csv += row.join(itemDelimiter); + // Add the line delimiter + if (i < rows.length - 1) { + csv += lineDelimiter; + } + }); + return csv; + }; + /** + * Export-data module required. Build a HTML table with the chart's current + * data. + * + * @sample highcharts/export-data/viewdata/ + * View the data from the export menu + * + * @function Highcharts.Chart#getTable + * + * @param {boolean} [useLocalDecimalPoint] + * Whether to use the local decimal point as detected from the browser. + * This makes it easier to export data to Excel in the same locale as the + * user is. + * + * @return {string} + * HTML representation of the data. + * + * @fires Highcharts.Chart#event:afterGetTable + */ + Chart.prototype.getTable = function (useLocalDecimalPoint) { + var html = '', options = this.options, decimalPoint = useLocalDecimalPoint ? (1.1).toLocaleString()[1] : '.', useMultiLevelHeaders = pick(options.exporting.useMultiLevelHeaders, true), rows = this.getDataRows(useMultiLevelHeaders), rowLength = 0, topHeaders = useMultiLevelHeaders ? rows.shift() : null, subHeaders = rows.shift(), + // Compare two rows for equality + isRowEqual = function (row1, row2) { + var i = row1.length; + if (row2.length === i) { + while (i--) { + if (row1[i] !== row2[i]) { + return false; + } + } + } + else { + return false; + } + return true; + }, + // Get table cell HTML from value + getCellHTMLFromValue = function (tag, classes, attrs, value) { + var val = pick(value, ''), className = 'text' + (classes ? ' ' + classes : ''); + // Convert to string if number + if (typeof val === 'number') { + val = val.toString(); + if (decimalPoint === ',') { + val = val.replace('.', decimalPoint); + } + className = 'number'; + } + else if (!value) { + className = 'empty'; + } + return '<' + tag + (attrs ? ' ' + attrs : '') + + ' class="' + className + '">' + + val + ''; + }, + // Get table header markup from row data + getTableHeaderHTML = function (topheaders, subheaders, rowLength) { + var html = '', + i = 0, + len = rowLength || subheaders && subheaders.length, + next, + cur, + curColspan = 0, + rowspan; + // Clean up multiple table headers. Chart.getDataRows() returns two + // levels of headers when using multilevel, not merged. We need to + // merge identical headers, remove redundant headers, and keep it + // all marked up nicely. + if (useMultiLevelHeaders && + topheaders && + subheaders && + !isRowEqual(topheaders, subheaders)) { + html += ''; + for (; i < len; ++i) { + cur = topheaders[i]; + next = topheaders[i + 1]; + if (cur === next) { + ++curColspan; + } + else if (curColspan) { + // Ended colspan + // Add cur to HTML with colspan. + html += getCellHTMLFromValue('th', 'highcharts-table-topheading', 'scope="col" ' + + 'colspan="' + (curColspan + 1) + '"', cur); + curColspan = 0; + } + else { + // Cur is standalone. If it is same as sublevel, + // remove sublevel and add just toplevel. + if (cur === subheaders[i]) { + if (options.exporting.useRowspanHeaders) { + rowspan = 2; + delete subheaders[i]; + } + else { + rowspan = 1; + subheaders[i] = ''; + } + } + else { + rowspan = 1; + } + html += getCellHTMLFromValue('th', 'highcharts-table-topheading', 'scope="col"' + + (rowspan > 1 ? + ' valign="top" rowspan="' + rowspan + '"' : + ''), cur); + } + } + html += ''; + } + // Add the subheaders (the only headers if not using multilevels) + if (subheaders) { + html += ''; + for (i = 0, len = subheaders.length; i < len; ++i) { + if (typeof subheaders[i] !== 'undefined') { + html += getCellHTMLFromValue('th', null, 'scope="col"', subheaders[i]); + } + } + html += ''; + } + html += ''; + return html; + }; + // Add table caption + if (options.exporting.tableCaption !== false) { + html += ''; + } + // Find longest row + for (var i = 0, len = rows.length; i < len; ++i) { + if (rows[i].length > rowLength) { + rowLength = rows[i].length; + } + } + // Add header + html += getTableHeaderHTML(topHeaders, subHeaders, Math.max(rowLength, subHeaders.length)); + // Transform the rows to HTML + html += ''; + rows.forEach(function (row) { + html += ''; + for (var j = 0; j < rowLength; j++) { + // Make first column a header too. Especially important for + // category axes, but also might make sense for datetime? Should + // await user feedback on this. + html += getCellHTMLFromValue(j ? 'td' : 'th', null, j ? '' : 'scope="row"', row[j]); + } + html += ''; + }); + html += '
    ' + pick(options.exporting.tableCaption, (options.title.text ? + htmlencode(options.title.text) : + 'Chart')) + '
    '; + var e = { html: html }; + fireEvent(this, 'afterGetTable', e); + return e.html; + }; + /** + * Get a blob object from content, if blob is supported + * + * @private + * @param {string} content + * The content to create the blob from. + * @param {string} type + * The type of the content. + * @return {string|undefined} + * The blob object, or undefined if not supported. + */ + function getBlobFromContent(content, type) { + var nav = win.navigator, + webKit = (nav.userAgent.indexOf('WebKit') > -1 && + nav.userAgent.indexOf('Chrome') < 0), + domurl = win.URL || win.webkitURL || win; + try { + // MS specific + if (nav.msSaveOrOpenBlob && win.MSBlobBuilder) { + var blob = new win.MSBlobBuilder(); + blob.append(content); + return blob.getBlob('image/svg+xml'); + } + // Safari requires data URI since it doesn't allow navigation to blob + // URLs. + if (!webKit) { + return domurl.createObjectURL(new win.Blob(['\uFEFF' + content], // #7084 + { type: type })); + } + } + catch (e) { + // Ignore + } + } + /** + * Generates a data URL of CSV for local download in the browser. This is the + * default action for a click on the 'Download CSV' button. + * + * See {@link Highcharts.Chart#getCSV} to get the CSV data itself. + * + * @function Highcharts.Chart#downloadCSV + * + * @requires modules/exporting + */ + Chart.prototype.downloadCSV = function () { + var csv = this.getCSV(true); + downloadURL(getBlobFromContent(csv, 'text/csv') || + 'data:text/csv,\uFEFF' + encodeURIComponent(csv), this.getFilename() + '.csv'); + }; + /** + * Generates a data URL of an XLS document for local download in the browser. + * This is the default action for a click on the 'Download XLS' button. + * + * See {@link Highcharts.Chart#getTable} to get the table data itself. + * + * @function Highcharts.Chart#downloadXLS + * + * @requires modules/exporting + */ + Chart.prototype.downloadXLS = function () { + var uri = 'data:application/vnd.ms-excel;base64,', template = '' + + '' + + '' + + '' + + '' + + '' + + this.getTable(true) + + '', base64 = function (s) { + return win.btoa(unescape(encodeURIComponent(s))); // #50 + }; + downloadURL(getBlobFromContent(template, 'application/vnd.ms-excel') || + uri + base64(template), this.getFilename() + '.xls'); + }; + /** + * Export-data module required. View the data in a table below the chart. + * + * @function Highcharts.Chart#viewData + * + * @fires Highcharts.Chart#event:afterViewData + */ + Chart.prototype.viewData = function () { + // Create div and generate the data table. + if (!this.dataTableDiv) { + this.dataTableDiv = doc.createElement('div'); + this.dataTableDiv.className = 'highcharts-data-table'; + // Insert after the chart container + this.renderTo.parentNode.insertBefore(this.dataTableDiv, this.renderTo.nextSibling); + this.dataTableDiv.innerHTML = this.getTable(); + } + // Show the data table again. + if (this.dataTableDiv.style.display === '' || this.dataTableDiv.style.display === 'none') { + this.dataTableDiv.style.display = 'block'; + } + this.isDataTableVisible = true; + fireEvent(this, 'afterViewData', this.dataTableDiv); + }; + /** + * Export-data module required. Hide the data table when visible. + * + * @function Highcharts.Chart#hideData + */ + Chart.prototype.hideData = function () { + if (this.dataTableDiv && this.dataTableDiv.style.display === 'block') { + this.dataTableDiv.style.display = 'none'; + } + this.isDataTableVisible = false; + }; + Chart.prototype.toggleDataTable = function () { + var _a; + var exportDivElements = this.exportDivElements, + menuItems = (_a = exportingOptions === null || exportingOptions === void 0 ? void 0 : exportingOptions.buttons) === null || _a === void 0 ? void 0 : _a.contextButton.menuItems, + lang = this.options.lang; + if (this.isDataTableVisible) { + this.hideData(); + } + else { + this.viewData(); + } + // Change the button text based on table visibility. + if ((exportingOptions === null || exportingOptions === void 0 ? void 0 : exportingOptions.menuItemDefinitions) && (lang === null || lang === void 0 ? void 0 : lang.viewData) && + lang.hideData && + menuItems && + exportDivElements && + exportDivElements.length) { + exportDivElements[menuItems.indexOf('viewData')] + .innerHTML = this.isDataTableVisible ? lang.hideData : lang.viewData; + } + }; + // Add "Download CSV" to the exporting menu. + var exportingOptions = getOptions().exporting; + if (exportingOptions) { + extend(exportingOptions.menuItemDefinitions, { + downloadCSV: { + textKey: 'downloadCSV', + onclick: function () { + this.downloadCSV(); + } + }, + downloadXLS: { + textKey: 'downloadXLS', + onclick: function () { + this.downloadXLS(); + } + }, + viewData: { + textKey: 'viewData', + onclick: function () { + this.toggleDataTable(); + } + } + }); + if (exportingOptions.buttons) { + exportingOptions.buttons.contextButton.menuItems.push('separator', 'downloadCSV', 'downloadXLS', 'viewData'); + } + } + // Series specific + if (seriesTypes.map) { + seriesTypes.map.prototype.exportKey = 'name'; + } + if (seriesTypes.mapbubble) { + seriesTypes.mapbubble.prototype.exportKey = 'name'; + } + if (seriesTypes.treemap) { + seriesTypes.treemap.prototype.exportKey = 'name'; + } + + }); + _registerModule(_modules, 'masters/modules/export-data.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/exporting.js b/highcharts/modules/exporting.js new file mode 100644 index 0000000..51da1b9 --- /dev/null +++ b/highcharts/modules/exporting.js @@ -0,0 +1,43 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Exporting module + + (c) 2010-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(c){"object"===typeof module&&module.exports?(c["default"]=c,module.exports=c):"function"===typeof define&&define.amd?define("highcharts/modules/exporting",["highcharts"],function(p){c(p);c.Highcharts=p;return c}):c("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(c){function p(c,l,h,k){c.hasOwnProperty(l)||(c[l]=k.apply(null,h))}c=c?c._modules:{};p(c,"Extensions/FullScreen.js",[c["Core/Chart/Chart.js"],c["Core/Globals.js"],c["Core/Utilities.js"]],function(c,l,h){var k=h.addEvent; +h=function(){function c(e){this.chart=e;this.isOpen=!1;e=e.renderTo;this.browserProps||("function"===typeof e.requestFullscreen?this.browserProps={fullscreenChange:"fullscreenchange",requestFullscreen:"requestFullscreen",exitFullscreen:"exitFullscreen"}:e.mozRequestFullScreen?this.browserProps={fullscreenChange:"mozfullscreenchange",requestFullscreen:"mozRequestFullScreen",exitFullscreen:"mozCancelFullScreen"}:e.webkitRequestFullScreen?this.browserProps={fullscreenChange:"webkitfullscreenchange", +requestFullscreen:"webkitRequestFullScreen",exitFullscreen:"webkitExitFullscreen"}:e.msRequestFullscreen&&(this.browserProps={fullscreenChange:"MSFullscreenChange",requestFullscreen:"msRequestFullscreen",exitFullscreen:"msExitFullscreen"}))}c.prototype.close=function(){var e=this.chart;if(this.isOpen&&this.browserProps&&e.container.ownerDocument instanceof Document)e.container.ownerDocument[this.browserProps.exitFullscreen]();this.unbindFullscreenEvent&&this.unbindFullscreenEvent();this.isOpen=!1; +this.setButtonText()};c.prototype.open=function(){var e=this,c=e.chart;if(e.browserProps){e.unbindFullscreenEvent=k(c.container.ownerDocument,e.browserProps.fullscreenChange,function(){e.isOpen?(e.isOpen=!1,e.close()):(e.isOpen=!0,e.setButtonText())});var h=c.renderTo[e.browserProps.requestFullscreen]();if(h)h["catch"](function(){alert("Full screen is not supported inside a frame.")});k(c,"destroy",e.unbindFullscreenEvent)}};c.prototype.setButtonText=function(){var e,c=this.chart,h=c.exportDivElements, +k=c.options.exporting,l=null===(e=null===k||void 0===k?void 0:k.buttons)||void 0===e?void 0:e.contextButton.menuItems;e=c.options.lang;(null===k||void 0===k?0:k.menuItemDefinitions)&&(null===e||void 0===e?0:e.exitFullscreen)&&e.viewFullscreen&&l&&h&&h.length&&(h[l.indexOf("viewFullscreen")].innerHTML=this.isOpen?e.exitFullscreen:k.menuItemDefinitions.viewFullscreen.text||e.viewFullscreen)};c.prototype.toggle=function(){this.isOpen?this.close():this.open()};return c}();l.Fullscreen=h;k(c,"beforeRender", +function(){this.fullscreen=new l.Fullscreen(this)});return l.Fullscreen});p(c,"Mixins/Navigation.js",[],function(){return{initUpdate:function(c){c.navigation||(c.navigation={updates:[],update:function(c,h){this.updates.forEach(function(k){k.update.call(k.context,c,h)})}})},addUpdate:function(c,l){l.navigation||this.initUpdate(l);l.navigation.updates.push({update:c,context:l})}}});p(c,"Extensions/Exporting.js",[c["Core/Chart/Chart.js"],c["Mixins/Navigation.js"],c["Core/Globals.js"],c["Core/Options.js"], +c["Core/Renderer/SVG/SVGRenderer.js"],c["Core/Utilities.js"]],function(c,l,h,k,p,e){var x=h.doc,H=h.isTouchDevice,z=h.win;k=k.defaultOptions;var t=e.addEvent,u=e.css,y=e.createElement,D=e.discardElement,w=e.extend,I=e.find,B=e.fireEvent,J=e.isObject,n=e.merge,E=e.objectEach,q=e.pick,K=e.removeEvent,L=e.uniqueKey,F=z.navigator.userAgent,G=h.Renderer.prototype.symbols,M=/Edge\/|Trident\/|MSIE /.test(F),N=/firefox/i.test(F);w(k.lang,{viewFullscreen:"Ver en pantalla completa",exitFullscreen:"Exit from full screen", +printChart:"Imprimir gráfica",downloadPNG:"Descargar imagen en PNG",downloadJPEG:"Descargar imagen en JPEG",downloadPDF:"Descargar documento en PDF",downloadSVG:"Descargar imagen en vector SVG",contextButtonTitle:"Chart context menu"});k.navigation||(k.navigation={});n(!0,k.navigation,{buttonOptions:{theme:{},symbolSize:14,symbolX:12.5,symbolY:10.5,align:"right",buttonSpacing:3,height:22,verticalAlign:"top",width:24}});n(!0,k.navigation,{menuStyle:{border:"1px solid #999999",background:"#ffffff",padding:"5px 0"},menuItemStyle:{padding:"0.5em 1em", +color:"#333333",background:"none",fontSize:H?"14px":"11px",transition:"background 250ms, color 250ms"},menuItemHoverStyle:{background:"#335cad",color:"#ffffff"},buttonOptions:{symbolFill:"#666666",symbolStroke:"#666666",symbolStrokeWidth:3,theme:{padding:5}}});k.exporting={type:"image/png",url:"https://export.highcharts.com/",printMaxWidth:780,scale:2,buttons:{contextButton:{className:"highcharts-contextbutton",menuClassName:"highcharts-contextmenu",symbol:"menu",titleKey:"contextButtonTitle",menuItems:"viewFullscreen printChart separator downloadPNG downloadJPEG downloadPDF downloadSVG".split(" ")}}, +menuItemDefinitions:{viewFullscreen:{textKey:"viewFullscreen",onclick:function(){this.fullscreen.toggle()}},printChart:{textKey:"printChart",onclick:function(){this.print()}},separator:{separator:!0},downloadPNG:{textKey:"downloadPNG",onclick:function(){this.exportChart()}},downloadJPEG:{textKey:"downloadJPEG",onclick:function(){this.exportChart({type:"image/jpeg"})}},downloadPDF:{textKey:"downloadPDF",onclick:function(){this.exportChart({type:"application/pdf"})}},downloadSVG:{textKey:"downloadSVG", +onclick:function(){this.exportChart({type:"image/svg+xml"})}}}};h.post=function(a,b,f){var d=y("form",n({method:"post",action:a,enctype:"multipart/form-data"},f),{display:"none"},x.body);E(b,function(a,b){y("input",{type:"hidden",name:b,value:a},null,d)});d.submit();D(d)};h.isSafari&&h.win.matchMedia("print").addListener(function(a){h.printingChart&&(a.matches?h.printingChart.beforePrint():h.printingChart.afterPrint())});w(c.prototype,{sanitizeSVG:function(a,b){var f=a.indexOf("")+6,d=a.substr(f); +a=a.substr(0,f);b&&b.exporting&&b.exporting.allowHTML&&d&&(d=''+d.replace(/(<(?:img|br).*?(?=>))>/g,"$1 />")+"",a=a.replace("",d+""));a=a.replace(/zIndex="[^"]+"/g,"").replace(/symbolName="[^"]+"/g,"").replace(/jQuery[0-9]+="[^"]+"/g,"").replace(/url\(("|")(.*?)("|");?\)/g,"url($2)").replace(/url\([^#]+#/g,"url(#").replace(/]+(>|$)/g,"").replace(/[\s_]+/g,"-").replace(/[^a-z0-9\-]/g,"").replace(/^[\-]+/g,"").replace(/[\-]+/g,"-").substr(0,24).replace(/[\-]+$/g,""));if(!b||5>b.length)b="chart";return b},exportChart:function(a,b){b=this.getSVGForExport(a,b);a=n(this.options.exporting,a);h.post(a.url,{filename:a.filename? +a.filename.replace(/\//g,"-"):this.getFilename(),type:a.type,width:a.width||0,scale:a.scale,svg:b},a.formAttributes)},moveContainers:function(a){(this.fixedDiv?[this.fixedDiv,this.scrollingContainer]:[this.container]).forEach(function(b){a.appendChild(b)})},beforePrint:function(){var a=x.body,b=this.options.exporting.printMaxWidth,f={childNodes:a.childNodes,origDisplay:[],resetParams:void 0};this.isPrinting=!0;this.pointer.reset(null,0);B(this,"beforePrint");b&&this.chartWidth>b&&(f.resetParams=[this.options.chart.width, +void 0,!1],this.setSize(b,void 0,!1));[].forEach.call(f.childNodes,function(a,b){1===a.nodeType&&(f.origDisplay[b]=a.style.display,a.style.display="none")});this.moveContainers(a);this.printReverseInfo=f},afterPrint:function(){if(this.printReverseInfo){var a=this.printReverseInfo.childNodes,b=this.printReverseInfo.origDisplay,f=this.printReverseInfo.resetParams;this.moveContainers(this.renderTo);[].forEach.call(a,function(a,f){1===a.nodeType&&(a.style.display=b[f]||"")});this.isPrinting=!1;f&&this.setSize.apply(this, +f);delete this.printReverseInfo;delete h.printingChart;B(this,"afterPrint")}},print:function(){var a=this;a.isPrinting||(h.printingChart=a,h.isSafari||a.beforePrint(),setTimeout(function(){z.focus();z.print();h.isSafari||setTimeout(function(){a.afterPrint()},1E3)},1))},contextMenu:function(a,b,f,d,c,h,k){var g=this,C=g.options.navigation,l=g.chartWidth,A=g.chartHeight,r="cache-"+a,m=g[r],v=Math.max(c,h);if(!m){g.exportContextMenu=g[r]=m=y("div",{className:a},{position:"absolute",zIndex:1E3,padding:v+ +"px",pointerEvents:"auto"},g.fixedDiv||g.container);var n=y("ul",{className:"highcharts-menu"},{listStyle:"none",margin:0,padding:0},m);g.styledMode||u(n,w({MozBoxShadow:"3px 3px 10px #888",WebkitBoxShadow:"3px 3px 10px #888",boxShadow:"3px 3px 10px #888"},C.menuStyle));m.hideMenu=function(){u(m,{display:"none"});k&&k.setState(0);g.openMenu=!1;u(g.renderTo,{overflow:"hidden"});e.clearTimeout(m.hideTimer);B(g,"exportMenuHidden")};g.exportEvents.push(t(m,"mouseleave",function(){m.hideTimer=z.setTimeout(m.hideMenu, +500)}),t(m,"mouseenter",function(){e.clearTimeout(m.hideTimer)}),t(x,"mouseup",function(b){g.pointer.inClass(b.target,a)||m.hideMenu()}),t(m,"click",function(){g.openMenu&&m.hideMenu()}));b.forEach(function(a){"string"===typeof a&&(a=g.options.exporting.menuItemDefinitions[a]);if(J(a,!0)){if(a.separator)var b=y("hr",null,null,n);else b=y("li",{className:"highcharts-menu-item",onclick:function(b){b&&b.stopPropagation();m.hideMenu();a.onclick&&a.onclick.apply(g,arguments)},innerHTML:a.text||g.options.lang[a.textKey]}, +null,n),g.styledMode||(b.onmouseover=function(){u(this,C.menuItemHoverStyle)},b.onmouseout=function(){u(this,C.menuItemStyle)},u(b,w({cursor:"pointer"},C.menuItemStyle)));g.exportDivElements.push(b)}});g.exportDivElements.push(n,m);g.exportMenuWidth=m.offsetWidth;g.exportMenuHeight=m.offsetHeight}b={display:"block"};f+g.exportMenuWidth>l?b.right=l-f-c-v+"px":b.left=f-v+"px";d+h+g.exportMenuHeight>A&&"top"!==k.alignOptions.verticalAlign?b.bottom=A-d-v+"px":b.top=d+h-v+"px";u(m,b);u(g.renderTo,{overflow:""}); +g.openMenu=!0;B(g,"exportMenuShown")},addButton:function(a){var b=this,f=b.renderer,d=n(b.options.navigation.buttonOptions,a),c=d.onclick,e=d.menuItems,h=d.symbolSize||12;b.btnCount||(b.btnCount=0);b.exportDivElements||(b.exportDivElements=[],b.exportSVGElements=[]);if(!1!==d.enabled){var g=d.theme,k=g.states,l=k&&k.hover;k=k&&k.select;var A;b.styledMode||(g.fill=q(g.fill,"#ffffff"),g.stroke=q(g.stroke,"none"));delete g.states;c?A=function(a){a&&a.stopPropagation();c.call(b,a)}:e&&(A=function(a){a&& +a.stopPropagation();b.contextMenu(r.menuClassName,e,r.translateX,r.translateY,r.width,r.height,r);r.setState(2)});d.text&&d.symbol?g.paddingLeft=q(g.paddingLeft,25):d.text||w(g,{width:d.width,height:d.height,padding:0});b.styledMode||(g["stroke-linecap"]="round",g.fill=q(g.fill,"#ffffff"),g.stroke=q(g.stroke,"none"));var r=f.button(d.text,0,0,A,g,l,k).addClass(a.className).attr({title:q(b.options.lang[d._titleKey||d.titleKey],"")});r.menuClassName=a.menuClassName||"highcharts-menu-"+b.btnCount++; +if(d.symbol){var m=f.symbol(d.symbol,d.symbolX-h/2,d.symbolY-h/2,h,h,{width:h,height:h}).addClass("highcharts-button-symbol").attr({zIndex:1}).add(r);b.styledMode||m.attr({stroke:d.symbolStroke,fill:d.symbolFill,"stroke-width":d.symbolStrokeWidth||1})}r.add(b.exportingGroup).align(w(d,{width:r.width,x:q(d.x,b.buttonOffset)}),!0,"spacingBox");b.buttonOffset+=(r.width+d.buttonSpacing)*("right"===d.align?-1:1);b.exportSVGElements.push(r,m)}},destroyExport:function(a){var b=a?a.target:this;a=b.exportSVGElements; +var f=b.exportDivElements,d=b.exportEvents,c;a&&(a.forEach(function(a,d){a&&(a.onclick=a.ontouchstart=null,c="cache-"+a.menuClassName,b[c]&&delete b[c],b.exportSVGElements[d]=a.destroy())}),a.length=0);b.exportingGroup&&(b.exportingGroup.destroy(),delete b.exportingGroup);f&&(f.forEach(function(a,d){e.clearTimeout(a.hideTimer);K(a,"mouseleave");b.exportDivElements[d]=a.onmouseout=a.onmouseover=a.ontouchstart=a.onclick=null;D(a)}),f.length=0);d&&(d.forEach(function(a){a()}),d.length=0)}});p.prototype.inlineToAttributes= +"fill stroke strokeLinecap strokeLinejoin strokeWidth textAnchor x y".split(" ");p.prototype.inlineBlacklist=[/-/,/^(clipPath|cssText|d|height|width)$/,/^font$/,/[lL]ogical(Width|Height)$/,/perspective/,/TapHighlightColor/,/^transition/,/^length$/];p.prototype.unstyledElements=["clipPath","defs","desc"];c.prototype.inlineStyles=function(){function a(a){return a.replace(/([A-Z])/g,function(a,b){return"-"+b.toLowerCase()})}function b(c){function f(b,f){v=u=!1;if(h){for(q=h.length;q--&&!u;)u=h[q].test(f); +v=!u}"transform"===f&&"none"===b&&(v=!0);for(q=e.length;q--&&!v;)v=e[q].test(f)||"function"===typeof b;v||y[f]===b&&"svg"!==c.nodeName||g[c.nodeName][f]===b||(d&&-1===d.indexOf(f)?m+=a(f)+":"+b+";":b&&c.setAttribute(a(f),b))}var m="",v,u,q;if(1===c.nodeType&&-1===k.indexOf(c.nodeName)){var t=z.getComputedStyle(c,null);var y="svg"===c.nodeName?{}:z.getComputedStyle(c.parentNode,null);if(!g[c.nodeName]){l=p.getElementsByTagName("svg")[0];var w=p.createElementNS(c.namespaceURI,c.nodeName);l.appendChild(w); +g[c.nodeName]=n(z.getComputedStyle(w,null));"text"===c.nodeName&&delete g.text.fill;l.removeChild(w)}if(N||M)for(var x in t)f(t[x],x);else E(t,f);m&&(t=c.getAttribute("style"),c.setAttribute("style",(t?t+";":"")+m));"svg"===c.nodeName&&c.setAttribute("stroke-width","1px");"text"!==c.nodeName&&[].forEach.call(c.children||c.childNodes,b)}}var c=this.renderer,d=c.inlineToAttributes,e=c.inlineBlacklist,h=c.inlineWhitelist,k=c.unstyledElements,g={},l;c=x.createElement("iframe");u(c,{width:"1px",height:"1px", +visibility:"hidden"});x.body.appendChild(c);var p=c.contentWindow.document;p.open();p.write('');p.close();b(this.container.querySelector("svg"));l.parentNode.removeChild(l)};G.menu=function(a,b,c,d){return[["M",a,b+2.5],["L",a+c,b+2.5],["M",a,b+d/2+.5],["L",a+c,b+d/2+.5],["M",a,b+d-1.5],["L",a+c,b+d-1.5]]};G.menuball=function(a,b,c,d){a=[];d=d/3-2;return a=a.concat(this.circle(c-d,b,d,d),this.circle(c-d,b+d+4,d,d),this.circle(c-d,b+2*(d+4),d,d))};c.prototype.renderExporting= +function(){var a=this,b=a.options.exporting,c=b.buttons,d=a.isDirtyExporting||!a.exportSVGElements;a.buttonOffset=0;a.isDirtyExporting&&a.destroyExport();d&&!1!==b.enabled&&(a.exportEvents=[],a.exportingGroup=a.exportingGroup||a.renderer.g("exporting-group").attr({zIndex:3}).add(),E(c,function(b){a.addButton(b)}),a.isDirtyExporting=!1);t(a,"destroy",a.destroyExport)};t(c,"init",function(){var a=this;a.exporting={update:function(b,c){a.isDirtyExporting=!0;n(!0,a.options.exporting,b);q(c,!0)&&a.redraw()}}; +l.addUpdate(function(b,c){a.isDirtyExporting=!0;n(!0,a.options.navigation,b);q(c,!0)&&a.redraw()},a)});c.prototype.callbacks.push(function(a){a.renderExporting();t(a,"redraw",a.renderExporting)})});p(c,"masters/modules/exporting.src.js",[],function(){})}); +//# sourceMappingURL=exporting.js.map \ No newline at end of file diff --git a/highcharts/modules/exporting.js.map b/highcharts/modules/exporting.js.map new file mode 100644 index 0000000..533acef --- /dev/null +++ b/highcharts/modules/exporting.js.map @@ -0,0 +1 @@ +{"version":3,"file":"exporting.js.map","lineCount":42,"mappings":"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","sources":["exporting.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","Chart","H","U","addEvent","Fullscreen","chart","isOpen","container","renderTo","browserProps","requestFullscreen","fullscreenChange","exitFullscreen","mozRequestFullScreen","webkitRequestFullScreen","msRequestFullscreen","prototype","close","Fullscreen.prototype.close","fullscreen","ownerDocument","Document","unbindFullscreenEvent","setButtonText","open","Fullscreen.prototype.open","promise","alert","Fullscreen.prototype.setButtonText","_a","exportDivElements","exportingOptions","options","exporting","menuItems","buttons","contextButton","lang","menuItemDefinitions","viewFullscreen","length","indexOf","innerHTML","text","toggle","Fullscreen.prototype.toggle","chartNavigation","initUpdate","navigation","updates","update","redraw","forEach","updateConfig","call","context","addUpdate","push","chartNavigationMixin","O","SVGRenderer","doc","isTouchDevice","win","defaultOptions","css","createElement","discardElement","extend","find","fireEvent","isObject","merge","objectEach","pick","removeEvent","uniqueKey","userAgent","navigator","symbols","Renderer","isMSBrowser","test","isFirefoxBrowser","printChart","downloadPNG","downloadJPEG","downloadPDF","downloadSVG","contextButtonTitle","buttonOptions","theme","symbolSize","symbolX","symbolY","align","buttonSpacing","height","verticalAlign","width","menuStyle","border","background","padding","menuItemStyle","color","fontSize","transition","menuItemHoverStyle","symbolFill","symbolStroke","symbolStrokeWidth","type","url","printMaxWidth","scale","className","menuClassName","symbol","titleKey","textKey","onclick","print","separator","exportChart","post","H.post","data","formAttributes","form","method","action","enctype","display","body","val","name","value","submit","isSafari","matchMedia","addListener","mqlEvent","printingChart","matches","beforePrint","afterPrint","sanitizeSVG","svg","split","html","substr","allowHTML","replace","ieSanitizeSVG","getChartHTML","styledMode","inlineStyles","getSVG","chartOptions","seriesOptions","plotOptions","userOptions","time","sandbox","position","top","chartWidth","chartHeight","cssWidth","style","cssHeight","sourceWidth","parseInt","isGantt","sourceHeight","animation","forExport","renderer","enabled","series","serie","enableMouseTracking","showCheckbox","visible","isInternal","axes","axis","internalKey","chartCopy","callback","coll","collOptions","axisCopy","copy","extremes","getExtremes","userMin","userMax","min","max","setExtremes","destroy","getSVGForExport","chartExportingOptions","borderRadius","getFilename","s","title","filename","toLowerCase","moveContainers","moveTo","fixedDiv","scrollingContainer","div","appendChild","printReverseInfo","childNodes","origDisplay","resetParams","isPrinting","pointer","reset","setSize","node","i","nodeType","setTimeout","focus","contextMenu","items","x","y","button","navOptions","cacheName","menu","menuPadding","Math","exportContextMenu","zIndex","pointerEvents","innerMenu","listStyle","margin","MozBoxShadow","WebkitBoxShadow","boxShadow","hideMenu","menu.hideMenu","setState","openMenu","overflow","clearTimeout","hideTimer","exportEvents","e","inClass","target","item","element","stopPropagation","arguments","onmouseover","element.onmouseover","onmouseout","element.onmouseout","cursor","exportMenuWidth","offsetWidth","exportMenuHeight","offsetHeight","right","left","alignOptions","bottom","addButton","btnOptions","btnCount","exportSVGElements","attr","states","hover","select","fill","stroke","translateX","translateY","paddingLeft","addClass","_titleKey","add","exportingGroup","buttonOffset","destroyExport","elem","ontouchstart","unbind","inlineToAttributes","inlineBlacklist","unstyledElements","Chart.prototype.inlineStyles","hyphenate","prop","a","b","recurse","filterStyles","blacklisted","whitelisted","whitelist","blacklist","parentStyles","nodeName","defaultStyles","cssText","setAttribute","styles","getComputedStyle","parentNode","dummySVG","iframeDoc","getElementsByTagName","dummy","createElementNS","namespaceURI","removeChild","p","styleAttr","getAttribute","children","inlineWhitelist","iframe","visibility","contentWindow","document","write","querySelector","symbols.menu","arr","menuball","symbols.menuball","h","concat","circle","renderExporting","Chart.prototype.renderExporting","isDirty","isDirtyExporting","g","callbacks"]} \ No newline at end of file diff --git a/highcharts/modules/exporting.src.js b/highcharts/modules/exporting.src.js new file mode 100644 index 0000000..258f118 --- /dev/null +++ b/highcharts/modules/exporting.src.js @@ -0,0 +1,2400 @@ +/** + * @license Highcharts JS v8.2.0 (2020-08-20) + * + * Exporting module + * + * (c) 2010-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/exporting', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'Extensions/FullScreen.js', [_modules['Core/Chart/Chart.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (Chart, H, U) { + /* * + * (c) 2009-2020 Rafal Sebestjanski + * + * Full screen for Highcharts + * + * License: www.highcharts.com/license + */ + var addEvent = U.addEvent; + /** + * The module allows user to enable display chart in full screen mode. + * Used in StockTools too. + * Based on default solutions in browsers. + * + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Handles displaying chart's container in the fullscreen mode. + * + * **Note**: Fullscreen is not supported on iPhone due to iOS limitations. + * + * @class + * @name Highcharts.Fullscreen + * @hideconstructor + * @requires modules/full-screen + */ + var Fullscreen = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Fullscreen(chart) { + /** + * Chart managed by the fullscreen controller. + * @name Highcharts.Fullscreen#chart + * @type {Highcharts.Chart} + */ + this.chart = chart; + /** + * The flag is set to `true` when the chart is displayed in + * the fullscreen mode. + * + * @name Highcharts.Fullscreen#isOpen + * @type {boolean|undefined} + * @since 8.0.1 + */ + this.isOpen = false; + var container = chart.renderTo; + // Hold event and methods available only for a current browser. + if (!this.browserProps) { + if (typeof container.requestFullscreen === 'function') { + this.browserProps = { + fullscreenChange: 'fullscreenchange', + requestFullscreen: 'requestFullscreen', + exitFullscreen: 'exitFullscreen' + }; + } + else if (container.mozRequestFullScreen) { + this.browserProps = { + fullscreenChange: 'mozfullscreenchange', + requestFullscreen: 'mozRequestFullScreen', + exitFullscreen: 'mozCancelFullScreen' + }; + } + else if (container.webkitRequestFullScreen) { + this.browserProps = { + fullscreenChange: 'webkitfullscreenchange', + requestFullscreen: 'webkitRequestFullScreen', + exitFullscreen: 'webkitExitFullscreen' + }; + } + else if (container.msRequestFullscreen) { + this.browserProps = { + fullscreenChange: 'MSFullscreenChange', + requestFullscreen: 'msRequestFullscreen', + exitFullscreen: 'msExitFullscreen' + }; + } + } + } + /* * + * + * Functions + * + * */ + /** + * Stops displaying the chart in fullscreen mode. + * Exporting module required. + * + * @since 8.0.1 + * + * @function Highcharts.Fullscreen#close + * @return {void} + * @requires modules/full-screen + */ + Fullscreen.prototype.close = function () { + var fullscreen = this, + chart = fullscreen.chart; + // Don't fire exitFullscreen() when user exited using 'Escape' button. + if (fullscreen.isOpen && + fullscreen.browserProps && + chart.container.ownerDocument instanceof Document) { + chart.container.ownerDocument[fullscreen.browserProps.exitFullscreen](); + } + // Unbind event as it's necessary only before exiting from fullscreen. + if (fullscreen.unbindFullscreenEvent) { + fullscreen.unbindFullscreenEvent(); + } + fullscreen.isOpen = false; + fullscreen.setButtonText(); + }; + /** + * Displays the chart in fullscreen mode. + * When fired customly by user before exporting context button is created, + * button's text will not be replaced - it's on the user side. + * Exporting module required. + * + * @since 8.0.1 + * + * @function Highcharts.Fullscreen#open + * @return {void} + * @requires modules/full-screen + */ + Fullscreen.prototype.open = function () { + var fullscreen = this, + chart = fullscreen.chart; + // Handle exitFullscreen() method when user clicks 'Escape' button. + if (fullscreen.browserProps) { + fullscreen.unbindFullscreenEvent = addEvent(chart.container.ownerDocument, // chart's document + fullscreen.browserProps.fullscreenChange, function () { + // Handle lack of async of browser's fullScreenChange event. + if (fullscreen.isOpen) { + fullscreen.isOpen = false; + fullscreen.close(); + } + else { + fullscreen.isOpen = true; + fullscreen.setButtonText(); + } + }); + var promise = chart.renderTo[fullscreen.browserProps.requestFullscreen](); + if (promise) { + // No dot notation because of IE8 compatibility + promise['catch'](function () { + alert(// eslint-disable-line no-alert + 'Full screen is not supported inside a frame.'); + }); + } + addEvent(chart, 'destroy', fullscreen.unbindFullscreenEvent); + } + }; + /** + * Replaces the exporting context button's text when toogling the + * fullscreen mode. + * + * @private + * + * @since 8.0.1 + * + * @requires modules/full-screen + * @return {void} + */ + Fullscreen.prototype.setButtonText = function () { + var _a; + var chart = this.chart, + exportDivElements = chart.exportDivElements, + exportingOptions = chart.options.exporting, + menuItems = (_a = exportingOptions === null || exportingOptions === void 0 ? void 0 : exportingOptions.buttons) === null || _a === void 0 ? void 0 : _a.contextButton.menuItems, + lang = chart.options.lang; + if ((exportingOptions === null || exportingOptions === void 0 ? void 0 : exportingOptions.menuItemDefinitions) && (lang === null || lang === void 0 ? void 0 : lang.exitFullscreen) && + lang.viewFullscreen && + menuItems && + exportDivElements && + exportDivElements.length) { + exportDivElements[menuItems.indexOf('viewFullscreen')] + .innerHTML = !this.isOpen ? + (exportingOptions.menuItemDefinitions.viewFullscreen.text || + lang.viewFullscreen) : lang.exitFullscreen; + } + }; + /** + * Toggles displaying the chart in fullscreen mode. + * By default, when the exporting module is enabled, a context button with + * a drop down menu in the upper right corner accesses this function. + * Exporting module required. + * + * @since 8.0.1 + * + * @sample highcharts/members/chart-togglefullscreen/ + * Toggle fullscreen mode from a HTML button + * + * @function Highcharts.Fullscreen#toggle + * @requires modules/full-screen + */ + Fullscreen.prototype.toggle = function () { + var fullscreen = this; + if (!fullscreen.isOpen) { + fullscreen.open(); + } + else { + fullscreen.close(); + } + }; + return Fullscreen; + }()); + H.Fullscreen = Fullscreen; + // Initialize fullscreen + addEvent(Chart, 'beforeRender', function () { + /** + * @name Highcharts.Chart#fullscreen + * @type {Highcharts.Fullscreen} + * @requires modules/full-screen + */ + this.fullscreen = new H.Fullscreen(this); + }); + + return H.Fullscreen; + }); + _registerModule(_modules, 'Mixins/Navigation.js', [], function () { + /** + * + * (c) 2010-2018 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var chartNavigation = { + /** + * Initializes `chart.navigation` object which delegates `update()` methods + * to all other common classes (used in exporting and navigationBindings). + * + * @private + * @param {Highcharts.Chart} chart + * The chart instance. + * @return {void} + */ + initUpdate: function (chart) { + if (!chart.navigation) { + chart.navigation = { + updates: [], + update: function (options, + redraw) { + this.updates.forEach(function (updateConfig) { + updateConfig.update.call(updateConfig.context, + options, + redraw); + }); + } + }; + } + }, + /** + * Registers an `update()` method in the `chart.navigation` object. + * + * @private + * @param {Highcharts.ChartNavigationUpdateFunction} update + * The `update()` method that will be called in `chart.update()`. + * @param {Highcharts.Chart} chart + * The chart instance. `update()` will use that as a context + * (`this`). + * @return {void} + */ + addUpdate: function (update, chart) { + if (!chart.navigation) { + this.initUpdate(chart); + } + chart.navigation.updates.push({ + update: update, + context: chart + }); + } + }; + + return chartNavigation; + }); + _registerModule(_modules, 'Extensions/Exporting.js', [_modules['Core/Chart/Chart.js'], _modules['Mixins/Navigation.js'], _modules['Core/Globals.js'], _modules['Core/Options.js'], _modules['Core/Renderer/SVG/SVGRenderer.js'], _modules['Core/Utilities.js']], function (Chart, chartNavigationMixin, H, O, SVGRenderer, U) { + /* * + * + * Exporting module + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var doc = H.doc, + isTouchDevice = H.isTouchDevice, + win = H.win; + var defaultOptions = O.defaultOptions; + var addEvent = U.addEvent, + css = U.css, + createElement = U.createElement, + discardElement = U.discardElement, + extend = U.extend, + find = U.find, + fireEvent = U.fireEvent, + isObject = U.isObject, + merge = U.merge, + objectEach = U.objectEach, + pick = U.pick, + removeEvent = U.removeEvent, + uniqueKey = U.uniqueKey; + /** + * Gets fired after a chart is printed through the context menu item or the + * Chart.print method. + * + * @callback Highcharts.ExportingAfterPrintCallbackFunction + * + * @param {Highcharts.Chart} chart + * The chart on which the event occured. + * + * @param {global.Event} event + * The event that occured. + */ + /** + * Gets fired before a chart is printed through the context menu item or the + * Chart.print method. + * + * @callback Highcharts.ExportingBeforePrintCallbackFunction + * + * @param {Highcharts.Chart} chart + * The chart on which the event occured. + * + * @param {global.Event} event + * The event that occured. + */ + /** + * Function to call if the offline-exporting module fails to export a chart on + * the client side. + * + * @callback Highcharts.ExportingErrorCallbackFunction + * + * @param {Highcharts.ExportingOptions} options + * The exporting options. + * + * @param {global.Error} err + * The error from the module. + */ + /** + * Definition for a menu item in the context menu. + * + * @interface Highcharts.ExportingMenuObject + */ /** + * The text for the menu item. + * + * @name Highcharts.ExportingMenuObject#text + * @type {string|undefined} + */ /** + * If internationalization is required, the key to a language string. + * + * @name Highcharts.ExportingMenuObject#textKey + * @type {string|undefined} + */ /** + * The click handler for the menu item. + * + * @name Highcharts.ExportingMenuObject#onclick + * @type {Highcharts.EventCallbackFunction|undefined} + */ /** + * Indicates a separator line instead of an item. + * + * @name Highcharts.ExportingMenuObject#separator + * @type {boolean|undefined} + */ + /** + * Possible MIME types for exporting. + * + * @typedef {"image/png"|"image/jpeg"|"application/pdf"|"image/svg+xml"} Highcharts.ExportingMimeTypeValue + */ + // create shortcuts + var userAgent = win.navigator.userAgent, + symbols = H.Renderer.prototype.symbols, + isMSBrowser = /Edge\/|Trident\/|MSIE /.test(userAgent), + isFirefoxBrowser = /firefox/i.test(userAgent); + // Add language + extend(defaultOptions.lang + /** + * @optionparent lang + */ + , { + /** + * Exporting module only. The text for the menu item to view the chart + * in full screen. + * + * @since 8.0.1 + * + * @private + */ + viewFullscreen: 'View in full screen', + /** + * Exporting module only. The text for the menu item to exit the chart + * from full screen. + * + * @since 8.0.1 + * + * @private + */ + exitFullscreen: 'Exit from full screen', + /** + * Exporting module only. The text for the menu item to print the chart. + * + * @since 3.0.1 + * @requires modules/exporting + * + * @private + */ + printChart: 'Print chart', + /** + * Exporting module only. The text for the PNG download menu item. + * + * @since 2.0 + * @requires modules/exporting + * + * @private + */ + downloadPNG: 'Download PNG image', + /** + * Exporting module only. The text for the JPEG download menu item. + * + * @since 2.0 + * @requires modules/exporting + * + * @private + */ + downloadJPEG: 'Download JPEG image', + /** + * Exporting module only. The text for the PDF download menu item. + * + * @since 2.0 + * @requires modules/exporting + * + * @private + */ + downloadPDF: 'Download PDF document', + /** + * Exporting module only. The text for the SVG download menu item. + * + * @since 2.0 + * @requires modules/exporting + * + * @private + */ + downloadSVG: 'Download SVG vector image', + /** + * Exporting module menu. The tooltip title for the context menu holding + * print and export menu items. + * + * @since 3.0 + * @requires modules/exporting + * + * @private + */ + contextButtonTitle: 'Chart context menu' + }); + if (!defaultOptions.navigation) { + // Buttons and menus are collected in a separate config option set called + // 'navigation'. This can be extended later to add control buttons like + // zoom and pan right click menus. + /** + * A collection of options for buttons and menus appearing in the exporting + * module. + * + * @requires modules/exporting + * @optionparent navigation + */ + defaultOptions.navigation = {}; + } + merge(true, defaultOptions.navigation, { + /** + * @optionparent navigation.buttonOptions + * + * @private + */ + buttonOptions: { + theme: {}, + /** + * Whether to enable buttons. + * + * @sample highcharts/navigation/buttonoptions-enabled/ + * Exporting module loaded but buttons disabled + * + * @type {boolean} + * @default true + * @since 2.0 + * @apioption navigation.buttonOptions.enabled + */ + /** + * The pixel size of the symbol on the button. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + symbolSize: 14, + /** + * The x position of the center of the symbol inside the button. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + symbolX: 12.5, + /** + * The y position of the center of the symbol inside the button. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + symbolY: 10.5, + /** + * Alignment for the buttons. + * + * @sample highcharts/navigation/buttonoptions-align/ + * Center aligned + * + * @type {Highcharts.AlignValue} + * @since 2.0 + */ + align: 'right', + /** + * The pixel spacing between buttons. + * + * @since 2.0 + */ + buttonSpacing: 3, + /** + * Pixel height of the buttons. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + height: 22, + /** + * A text string to add to the individual button. + * + * @sample highcharts/exporting/buttons-text/ + * Full text button + * @sample highcharts/exporting/buttons-text-symbol/ + * Combined symbol and text + * + * @type {string} + * @default null + * @since 3.0 + * @apioption navigation.buttonOptions.text + */ + /** + * The vertical offset of the button's position relative to its + * `verticalAlign`. + * + * @sample highcharts/navigation/buttonoptions-verticalalign/ + * Buttons at lower right + * + * @type {number} + * @default 0 + * @since 2.0 + * @apioption navigation.buttonOptions.y + */ + /** + * The vertical alignment of the buttons. Can be one of `"top"`, + * `"middle"` or `"bottom"`. + * + * @sample highcharts/navigation/buttonoptions-verticalalign/ + * Buttons at lower right + * + * @type {Highcharts.VerticalAlignValue} + * @since 2.0 + */ + verticalAlign: 'top', + /** + * The pixel width of the button. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + width: 24 + } + }); + // Presentational attributes + merge(true, defaultOptions.navigation + /** + * A collection of options for buttons and menus appearing in the exporting + * module. + * + * @optionparent navigation + */ + , { + /** + * CSS styles for the popup menu appearing by default when the export + * icon is clicked. This menu is rendered in HTML. + * + * @see In styled mode, the menu is styled with the `.highcharts-menu` + * class. + * + * @sample highcharts/navigation/menustyle/ + * Light gray menu background + * + * @type {Highcharts.CSSObject} + * @default {"border": "1px solid #999999", "background": "#ffffff", "padding": "5px 0"} + * @since 2.0 + * + * @private + */ + menuStyle: { + /** @ignore-option */ + border: '1px solid #999999', + /** @ignore-option */ + background: '#ffffff', + /** @ignore-option */ + padding: '5px 0' + }, + /** + * CSS styles for the individual items within the popup menu appearing + * by default when the export icon is clicked. The menu items are + * rendered in HTML. Font size defaults to `11px` on desktop and `14px` + * on touch devices. + * + * @see In styled mode, the menu items are styled with the + * `.highcharts-menu-item` class. + * + * @sample {highcharts} highcharts/navigation/menuitemstyle/ + * Add a grey stripe to the left + * + * @type {Highcharts.CSSObject} + * @default {"padding": "0.5em 1em", "color": "#333333", "background": "none", "fontSize": "11px/14px", "transition": "background 250ms, color 250ms"} + * @since 2.0 + * + * @private + */ + menuItemStyle: { + /** @ignore-option */ + padding: '0.5em 1em', + /** @ignore-option */ + color: '#333333', + /** @ignore-option */ + background: 'none', + /** @ignore-option */ + fontSize: isTouchDevice ? '14px' : '11px', + /** @ignore-option */ + transition: 'background 250ms, color 250ms' + }, + /** + * CSS styles for the hover state of the individual items within the + * popup menu appearing by default when the export icon is clicked. The + * menu items are rendered in HTML. + * + * @see In styled mode, the menu items are styled with the + * `.highcharts-menu-item` class. + * + * @sample highcharts/navigation/menuitemhoverstyle/ + * Bold text on hover + * + * @type {Highcharts.CSSObject} + * @default {"background": "#335cad", "color": "#ffffff"} + * @since 2.0 + * + * @private + */ + menuItemHoverStyle: { + /** @ignore-option */ + background: '#335cad', + /** @ignore-option */ + color: '#ffffff' + }, + /** + * A collection of options for buttons appearing in the exporting + * module. + * + * In styled mode, the buttons are styled with the + * `.highcharts-contextbutton` and `.highcharts-button-symbol` classes. + * + * @requires modules/exporting + * + * @private + */ + buttonOptions: { + /** + * Fill color for the symbol within the button. + * + * @sample highcharts/navigation/buttonoptions-symbolfill/ + * Blue symbol stroke for one of the buttons + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.0 + */ + symbolFill: '#666666', + /** + * The color of the symbol's stroke or line. + * + * @sample highcharts/navigation/buttonoptions-symbolstroke/ + * Blue symbol stroke + * + * @type {Highcharts.ColorString} + * @since 2.0 + */ + symbolStroke: '#666666', + /** + * The pixel stroke width of the symbol on the button. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + symbolStrokeWidth: 3, + /** + * A configuration object for the button theme. The object accepts + * SVG properties like `stroke-width`, `stroke` and `fill`. + * Tri-state button styles are supported by the `states.hover` and + * `states.select` objects. + * + * @sample highcharts/navigation/buttonoptions-theme/ + * Theming the buttons + * + * @requires modules/exporting + * + * @since 3.0 + */ + theme: { + /** + * The default fill exists only to capture hover events. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #ffffff + * @apioption navigation.buttonOptions.theme.fill + */ + /** + * Default stroke for the buttons. + * @type {Highcharts.ColorString} + * @default none + * @apioption navigation.buttonOptions.theme.stroke + */ + /** + * Padding for the button. + */ + padding: 5 + } + } + }); + // Add the export related options + /** + * Options for the exporting module. For an overview on the matter, see + * [the docs](https://www.highcharts.com/docs/export-module/export-module-overview). + * + * @requires modules/exporting + * @optionparent exporting + */ + defaultOptions.exporting = { + /** + * Experimental setting to allow HTML inside the chart (added through + * the `useHTML` options), directly in the exported image. This allows + * you to preserve complicated HTML structures like tables or bi-directional + * text in exported charts. + * + * Disclaimer: The HTML is rendered in a `foreignObject` tag in the + * generated SVG. The official export server is based on PhantomJS, + * which supports this, but other SVG clients, like Batik, does not + * support it. This also applies to downloaded SVG that you want to + * open in a desktop client. + * + * @type {boolean} + * @default false + * @since 4.1.8 + * @apioption exporting.allowHTML + */ + /** + * Additional chart options to be merged into the chart before exporting to + * an image format. This does not apply to printing the chart via the export + * menu. + * + * For example, a common use case is to add data labels to improve + * readability of the exported chart, or to add a printer-friendly color + * scheme to exported PDFs. + * + * @sample {highcharts} highcharts/exporting/chartoptions-data-labels/ + * Added data labels + * @sample {highstock} highcharts/exporting/chartoptions-data-labels/ + * Added data labels + * + * @type {Highcharts.Options} + * @apioption exporting.chartOptions + */ + /** + * Whether to enable the exporting module. Disabling the module will + * hide the context button, but API methods will still be available. + * + * @sample {highcharts} highcharts/exporting/enabled-false/ + * Exporting module is loaded but disabled + * @sample {highstock} highcharts/exporting/enabled-false/ + * Exporting module is loaded but disabled + * + * @type {boolean} + * @default true + * @since 2.0 + * @apioption exporting.enabled + */ + /** + * Function to call if the offline-exporting module fails to export + * a chart on the client side, and [fallbackToExportServer]( + * #exporting.fallbackToExportServer) is disabled. If left undefined, an + * exception is thrown instead. Receives two parameters, the exporting + * options, and the error from the module. + * + * @see [fallbackToExportServer](#exporting.fallbackToExportServer) + * + * @type {Highcharts.ExportingErrorCallbackFunction} + * @since 5.0.0 + * @requires modules/exporting + * @requires modules/offline-exporting + * @apioption exporting.error + */ + /** + * Whether or not to fall back to the export server if the offline-exporting + * module is unable to export the chart on the client side. This happens for + * certain browsers, and certain features (e.g. + * [allowHTML](#exporting.allowHTML)), depending on the image type exporting + * to. For very complex charts, it is possible that export can fail in + * browsers that don't support Blob objects, due to data URL length limits. + * It is recommended to define the [exporting.error](#exporting.error) + * handler if disabling fallback, in order to notify users in case export + * fails. + * + * @type {boolean} + * @default true + * @since 4.1.8 + * @requires modules/exporting + * @requires modules/offline-exporting + * @apioption exporting.fallbackToExportServer + */ + /** + * The filename, without extension, to use for the exported chart. + * + * @sample {highcharts} highcharts/exporting/filename/ + * Custom file name + * @sample {highstock} highcharts/exporting/filename/ + * Custom file name + * + * @type {string} + * @default chart + * @since 2.0 + * @apioption exporting.filename + */ + /** + * An object containing additional key value data for the POST form that + * sends the SVG to the export server. For example, a `target` can be set to + * make sure the generated image is received in another frame, or a custom + * `enctype` or `encoding` can be set. + * + * @type {Highcharts.HTMLAttributes} + * @since 3.0.8 + * @apioption exporting.formAttributes + */ + /** + * Path where Highcharts will look for export module dependencies to + * load on demand if they don't already exist on `window`. Should currently + * point to location of [CanVG](https://github.com/canvg/canvg) library, + * [RGBColor.js](https://github.com/canvg/canvg), + * [jsPDF](https://github.com/yWorks/jsPDF) and + * [svg2pdf.js](https://github.com/yWorks/svg2pdf.js), required for client + * side export in certain browsers. + * + * @type {string} + * @default https://code.highcharts.com/{version}/lib + * @since 5.0.0 + * @apioption exporting.libURL + */ + /** + * Analogous to [sourceWidth](#exporting.sourceWidth). + * + * @type {number} + * @since 3.0 + * @apioption exporting.sourceHeight + */ + /** + * The width of the original chart when exported, unless an explicit + * [chart.width](#chart.width) is set, or a pixel width is set on the + * container. The width exported raster image is then multiplied by + * [scale](#exporting.scale). + * + * @sample {highcharts} highcharts/exporting/sourcewidth/ + * Source size demo + * @sample {highstock} highcharts/exporting/sourcewidth/ + * Source size demo + * @sample {highmaps} maps/exporting/sourcewidth/ + * Source size demo + * + * @type {number} + * @since 3.0 + * @apioption exporting.sourceWidth + */ + /** + * The pixel width of charts exported to PNG or JPG. As of Highcharts + * 3.0, the default pixel width is a function of the [chart.width]( + * #chart.width) or [exporting.sourceWidth](#exporting.sourceWidth) and the + * [exporting.scale](#exporting.scale). + * + * @sample {highcharts} highcharts/exporting/width/ + * Export to 200px wide images + * @sample {highstock} highcharts/exporting/width/ + * Export to 200px wide images + * + * @type {number} + * @since 2.0 + * @apioption exporting.width + */ + /** + * Default MIME type for exporting if `chart.exportChart()` is called + * without specifying a `type` option. Possible values are `image/png`, + * `image/jpeg`, `application/pdf` and `image/svg+xml`. + * + * @type {Highcharts.ExportingMimeTypeValue} + * @since 2.0 + */ + type: 'image/png', + /** + * The URL for the server module converting the SVG string to an image + * format. By default this points to Highchart's free web service. + * + * @since 2.0 + */ + url: 'https://export.highcharts.com/', + /** + * When printing the chart from the menu item in the burger menu, if + * the on-screen chart exceeds this width, it is resized. After printing + * or cancelled, it is restored. The default width makes the chart + * fit into typical paper format. Note that this does not affect the + * chart when printing the web page as a whole. + * + * @since 4.2.5 + */ + printMaxWidth: 780, + /** + * Defines the scale or zoom factor for the exported image compared + * to the on-screen display. While for instance a 600px wide chart + * may look good on a website, it will look bad in print. The default + * scale of 2 makes this chart export to a 1200px PNG or JPG. + * + * @see [chart.width](#chart.width) + * @see [exporting.sourceWidth](#exporting.sourceWidth) + * + * @sample {highcharts} highcharts/exporting/scale/ + * Scale demonstrated + * @sample {highstock} highcharts/exporting/scale/ + * Scale demonstrated + * @sample {highmaps} maps/exporting/scale/ + * Scale demonstrated + * + * @since 3.0 + */ + scale: 2, + /** + * Options for the export related buttons, print and export. In addition + * to the default buttons listed here, custom buttons can be added. + * See [navigation.buttonOptions](#navigation.buttonOptions) for general + * options. + * + * @type {Highcharts.Dictionary<*>} + * @requires modules/exporting + */ + buttons: { + /** + * Options for the export button. + * + * In styled mode, export button styles can be applied with the + * `.highcharts-contextbutton` class. + * + * @declare Highcharts.ExportingButtonsOptionsObject + * @extends navigation.buttonOptions + * @requires modules/exporting + */ + contextButton: { + /** + * A click handler callback to use on the button directly instead of + * the popup menu. + * + * @sample highcharts/exporting/buttons-contextbutton-onclick/ + * Skip the menu and export the chart directly + * + * @type {Function} + * @since 2.0 + * @apioption exporting.buttons.contextButton.onclick + */ + /** + * See [navigation.buttonOptions.symbolFill]( + * #navigation.buttonOptions.symbolFill). + * + * @type {Highcharts.ColorString} + * @default #666666 + * @since 2.0 + * @apioption exporting.buttons.contextButton.symbolFill + */ + /** + * The horizontal position of the button relative to the `align` + * option. + * + * @type {number} + * @default -10 + * @since 2.0 + * @apioption exporting.buttons.contextButton.x + */ + /** + * The class name of the context button. + */ + className: 'highcharts-contextbutton', + /** + * The class name of the menu appearing from the button. + */ + menuClassName: 'highcharts-contextmenu', + /** + * The symbol for the button. Points to a definition function in + * the `Highcharts.Renderer.symbols` collection. The default + * `exportIcon` function is part of the exporting module. Possible + * values are "circle", "square", "diamond", "triangle", + * "triangle-down", "menu", "menuball" or custom shape. + * + * @sample highcharts/exporting/buttons-contextbutton-symbol/ + * Use a circle for symbol + * @sample highcharts/exporting/buttons-contextbutton-symbol-custom/ + * Custom shape as symbol + * + * @type {Highcharts.SymbolKeyValue|"exportIcon"|"menu"|"menuball"|string} + * @since 2.0 + */ + symbol: 'menu', + /** + * The key to a [lang](#lang) option setting that is used for the + * button's title tooltip. When the key is `contextButtonTitle`, it + * refers to [lang.contextButtonTitle](#lang.contextButtonTitle) + * that defaults to "Chart context menu". + * + * @since 6.1.4 + */ + titleKey: 'contextButtonTitle', + /** + * This option is deprecated, use + * [titleKey](#exporting.buttons.contextButton.titleKey) instead. + * + * @deprecated + * @type {string} + * @apioption exporting.buttons.contextButton._titleKey + */ + /** + * A collection of strings pointing to config options for the menu + * items. The config options are defined in the + * `menuItemDefinitions` option. + * + * By default, there is the "View in full screen" and "Print" menu + * items, plus one menu item for each of the available export types. + * + * @sample {highcharts} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * @sample {highstock} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * @sample {highmaps} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * + * @type {Array} + * @default ["viewFullscreen", "printChart", "separator", "downloadPNG", "downloadJPEG", "downloadPDF", "downloadSVG"] + * @since 2.0 + */ + menuItems: [ + 'viewFullscreen', + 'printChart', + 'separator', + 'downloadPNG', + 'downloadJPEG', + 'downloadPDF', + 'downloadSVG' + ] + } + }, + /** + * An object consisting of definitions for the menu items in the context + * menu. Each key value pair has a `key` that is referenced in the + * [menuItems](#exporting.buttons.contextButton.menuItems) setting, + * and a `value`, which is an object with the following properties: + * + * - **onclick:** The click handler for the menu item + * + * - **text:** The text for the menu item + * + * - **textKey:** If internationalization is required, the key to a language + * string + * + * Custom text for the "exitFullScreen" can be set only in lang options + * (it is not a separate button). + * + * @sample {highcharts} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * @sample {highstock} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * @sample {highmaps} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * + * + * @type {Highcharts.Dictionary} + * @default {"viewFullscreen": {}, "printChart": {}, "separator": {}, "downloadPNG": {}, "downloadJPEG": {}, "downloadPDF": {}, "downloadSVG": {}} + * @since 5.0.13 + */ + menuItemDefinitions: { + /** + * @ignore + */ + viewFullscreen: { + textKey: 'viewFullscreen', + onclick: function () { + this.fullscreen.toggle(); + } + }, + /** + * @ignore + */ + printChart: { + textKey: 'printChart', + onclick: function () { + this.print(); + } + }, + /** + * @ignore + */ + separator: { + separator: true + }, + /** + * @ignore + */ + downloadPNG: { + textKey: 'downloadPNG', + onclick: function () { + this.exportChart(); + } + }, + /** + * @ignore + */ + downloadJPEG: { + textKey: 'downloadJPEG', + onclick: function () { + this.exportChart({ + type: 'image/jpeg' + }); + } + }, + /** + * @ignore + */ + downloadPDF: { + textKey: 'downloadPDF', + onclick: function () { + this.exportChart({ + type: 'application/pdf' + }); + } + }, + /** + * @ignore + */ + downloadSVG: { + textKey: 'downloadSVG', + onclick: function () { + this.exportChart({ + type: 'image/svg+xml' + }); + } + } + } + }; + /** + * Fires after a chart is printed through the context menu item or the + * `Chart.print` method. + * + * @sample highcharts/chart/events-beforeprint-afterprint/ + * Rescale the chart to print + * + * @type {Highcharts.ExportingAfterPrintCallbackFunction} + * @since 4.1.0 + * @context Highcharts.Chart + * @requires modules/exporting + * @apioption chart.events.afterPrint + */ + /** + * Fires before a chart is printed through the context menu item or + * the `Chart.print` method. + * + * @sample highcharts/chart/events-beforeprint-afterprint/ + * Rescale the chart to print + * + * @type {Highcharts.ExportingBeforePrintCallbackFunction} + * @since 4.1.0 + * @context Highcharts.Chart + * @requires modules/exporting + * @apioption chart.events.beforePrint + */ + /** + * The post utility + * + * @private + * @function Highcharts.post + * @param {string} url + * Post URL + * @param {object} data + * Post data + * @param {Highcharts.Dictionary} [formAttributes] + * Additional attributes for the post request + * @return {void} + */ + H.post = function (url, data, formAttributes) { + // create the form + var form = createElement('form', + merge({ + method: 'post', + action: url, + enctype: 'multipart/form-data' + }, + formAttributes), { + display: 'none' + }, + doc.body); + // add the data + objectEach(data, function (val, name) { + createElement('input', { + type: 'hidden', + name: name, + value: val + }, null, form); + }); + // submit + form.submit(); + // clean up + discardElement(form); + }; + if (H.isSafari) { + H.win.matchMedia('print').addListener(function (mqlEvent) { + if (!H.printingChart) { + return void 0; + } + if (mqlEvent.matches) { + H.printingChart.beforePrint(); + } + else { + H.printingChart.afterPrint(); + } + }); + } + extend(Chart.prototype, /** @lends Highcharts.Chart.prototype */ { + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Exporting module only. A collection of fixes on the produced SVG to + * account for expando properties, browser bugs, VML problems and other. + * Returns a cleaned SVG. + * + * @private + * @function Highcharts.Chart#sanitizeSVG + * @param {string} svg + * SVG code to sanitize + * @param {Highcharts.Options} options + * Chart options to apply + * @return {string} + * Sanitized SVG code + * @requires modules/exporting + */ + sanitizeSVG: function (svg, options) { + var split = svg.indexOf('') + 6, + html = svg.substr(split); + // Remove any HTML added to the container after the SVG (#894, #9087) + svg = svg.substr(0, split); + // Move HTML into a foreignObject + if (options && options.exporting && options.exporting.allowHTML) { + if (html) { + html = '' + + '' + + // Some tags needs to be closed in xhtml (#13726) + html.replace(/(<(?:img|br).*?(?=\>))>/g, '$1 />') + + '' + + ''; + svg = svg.replace('', html + ''); + } + } + svg = svg + .replace(/zIndex="[^"]+"/g, '') + .replace(/symbolName="[^"]+"/g, '') + .replace(/jQuery[0-9]+="[^"]+"/g, '') + .replace(/url\(("|")(.*?)("|")\;?\)/g, 'url($2)') + .replace(/url\([^#]+#/g, 'url(#') + .replace(/]+(>|$)/g, '') // strip HTML tags + .replace(/[\s_]+/g, '-') + .replace(/[^a-z0-9\-]/g, '') // preserve only latin + .replace(/^[\-]+/g, '') // dashes in the start + .replace(/[\-]+/g, '-') // dashes in a row + .substr(0, 24) + .replace(/[\-]+$/g, ''); // dashes in the end; + } + if (!filename || filename.length < 5) { + filename = 'chart'; + } + return filename; + }, + /** + * Exporting module required. Submit an SVG version of the chart to a server + * along with some parameters for conversion. + * + * @sample highcharts/members/chart-exportchart/ + * Export with no options + * @sample highcharts/members/chart-exportchart-filename/ + * PDF type and custom filename + * @sample highcharts/members/chart-exportchart-custom-background/ + * Different chart background in export + * @sample stock/members/chart-exportchart/ + * Export with Highstock + * + * @function Highcharts.Chart#exportChart + * + * @param {Highcharts.ExportingOptions} exportingOptions + * Exporting options in addition to those defined in + * [exporting](https://api.highcharts.com/highcharts/exporting). + * + * @param {Highcharts.Options} chartOptions + * Additional chart options for the exported chart. For example a + * different background color can be added here, or `dataLabels` for + * export only. + * + * @return {void} + * + * @requires modules/exporting + */ + exportChart: function (exportingOptions, chartOptions) { + var svg = this.getSVGForExport(exportingOptions, + chartOptions); + // merge the options + exportingOptions = merge(this.options.exporting, exportingOptions); + // do the post + H.post(exportingOptions.url, { + filename: exportingOptions.filename ? exportingOptions.filename.replace(/\//g, '-') : this.getFilename(), + type: exportingOptions.type, + // IE8 fails to post undefined correctly, so use 0 + width: exportingOptions.width || 0, + scale: exportingOptions.scale, + svg: svg + }, exportingOptions.formAttributes); + }, + /** + * Move the chart container(s) to another div. + * + * @function Highcharts#moveContainers + * + * @private + * + * @param {Highcharts.HTMLDOMElement} moveTo + * Move target + * @return {void} + */ + moveContainers: function (moveTo) { + var chart = this; + (chart.fixedDiv ? // When scrollablePlotArea is active (#9533) + [chart.fixedDiv, chart.scrollingContainer] : + [chart.container]).forEach(function (div) { + moveTo.appendChild(div); + }); + }, + /** + * Prepare chart and document before printing a chart. + * + * @function Highcharts#beforePrint + * + * @private + * + * @return {void} + * + * @fires Highcharts.Chart#event:beforePrint + */ + beforePrint: function () { + var chart = this, + body = doc.body, + printMaxWidth = chart.options.exporting.printMaxWidth, + printReverseInfo = { + childNodes: body.childNodes, + origDisplay: [], + resetParams: void 0 + }; + var handleMaxWidth; + chart.isPrinting = true; + chart.pointer.reset(null, 0); + fireEvent(chart, 'beforePrint'); + // Handle printMaxWidth + handleMaxWidth = printMaxWidth && chart.chartWidth > printMaxWidth; + if (handleMaxWidth) { + printReverseInfo.resetParams = [ + chart.options.chart.width, + void 0, + false + ]; + chart.setSize(printMaxWidth, void 0, false); + } + // hide all body content + [].forEach.call(printReverseInfo.childNodes, function (node, i) { + if (node.nodeType === 1) { + printReverseInfo.origDisplay[i] = node.style.display; + node.style.display = 'none'; + } + }); + // pull out the chart + chart.moveContainers(body); + // Storage details for undo action after printing + chart.printReverseInfo = printReverseInfo; + }, + /** + * Clena up after printing a chart. + * + * @function Highcharts#afterPrint + * + * @private + * + * @param {Highcharts.Chart} chart + * Chart that was (or suppose to be) printed + * @return {void} + * + * @fires Highcharts.Chart#event:afterPrint + */ + afterPrint: function () { + var chart = this; + if (!chart.printReverseInfo) { + return void 0; + } + var childNodes = chart.printReverseInfo.childNodes, + origDisplay = chart.printReverseInfo.origDisplay, + resetParams = chart.printReverseInfo.resetParams; + // put the chart back in + chart.moveContainers(chart.renderTo); + // restore all body content + [].forEach.call(childNodes, function (node, i) { + if (node.nodeType === 1) { + node.style.display = (origDisplay[i] || ''); + } + }); + chart.isPrinting = false; + // Reset printMaxWidth + if (resetParams) { + chart.setSize.apply(chart, resetParams); + } + delete chart.printReverseInfo; + delete H.printingChart; + fireEvent(chart, 'afterPrint'); + }, + /** + * Exporting module required. Clears away other elements in the page and + * prints the chart as it is displayed. By default, when the exporting + * module is enabled, a context button with a drop down menu in the upper + * right corner accesses this function. + * + * @sample highcharts/members/chart-print/ + * Print from a HTML button + * + * @function Highcharts.Chart#print + * + * @return {void} + * + * @fires Highcharts.Chart#event:beforePrint + * @fires Highcharts.Chart#event:afterPrint + * + * @requires modules/exporting + */ + print: function () { + var chart = this; + if (chart.isPrinting) { // block the button while in printing mode + return; + } + H.printingChart = chart; + if (!H.isSafari) { + chart.beforePrint(); + } + // Give the browser time to draw WebGL content, an issue that randomly + // appears (at least) in Chrome ~67 on the Mac (#8708). + setTimeout(function () { + win.focus(); // #1510 + win.print(); + // allow the browser to prepare before reverting + if (!H.isSafari) { + setTimeout(function () { + chart.afterPrint(); + }, 1000); + } + }, 1); + }, + /** + * Display a popup menu for choosing the export type. + * + * @private + * @function Highcharts.Chart#contextMenu + * @param {string} className + * An identifier for the menu. + * @param {Array} items + * A collection with text and onclicks for the items. + * @param {number} x + * The x position of the opener button + * @param {number} y + * The y position of the opener button + * @param {number} width + * The width of the opener button + * @param {number} height + * The height of the opener button + * @return {void} + * @requires modules/exporting + */ + contextMenu: function (className, items, x, y, width, height, button) { + var chart = this, + navOptions = chart.options.navigation, + chartWidth = chart.chartWidth, + chartHeight = chart.chartHeight, + cacheName = 'cache-' + className, + menu = chart[cacheName], + menuPadding = Math.max(width, + height), // for mouse leave detection + innerMenu, + menuStyle; + // create the menu only the first time + if (!menu) { + // create a HTML element above the SVG + chart.exportContextMenu = chart[cacheName] = menu = + createElement('div', { + className: className + }, { + position: 'absolute', + zIndex: 1000, + padding: menuPadding + 'px', + pointerEvents: 'auto' + }, chart.fixedDiv || chart.container); + innerMenu = createElement('ul', { className: 'highcharts-menu' }, { + listStyle: 'none', + margin: 0, + padding: 0 + }, menu); + // Presentational CSS + if (!chart.styledMode) { + css(innerMenu, extend({ + MozBoxShadow: '3px 3px 10px #888', + WebkitBoxShadow: '3px 3px 10px #888', + boxShadow: '3px 3px 10px #888' + }, navOptions.menuStyle)); + } + // hide on mouse out + menu.hideMenu = function () { + css(menu, { display: 'none' }); + if (button) { + button.setState(0); + } + chart.openMenu = false; + css(chart.renderTo, { overflow: 'hidden' }); // #10361 + U.clearTimeout(menu.hideTimer); + fireEvent(chart, 'exportMenuHidden'); + }; + // Hide the menu some time after mouse leave (#1357) + chart.exportEvents.push(addEvent(menu, 'mouseleave', function () { + menu.hideTimer = win.setTimeout(menu.hideMenu, 500); + }), addEvent(menu, 'mouseenter', function () { + U.clearTimeout(menu.hideTimer); + }), + // Hide it on clicking or touching outside the menu (#2258, + // #2335, #2407) + addEvent(doc, 'mouseup', function (e) { + if (!chart.pointer.inClass(e.target, className)) { + menu.hideMenu(); + } + }), addEvent(menu, 'click', function () { + if (chart.openMenu) { + menu.hideMenu(); + } + })); + // create the items + items.forEach(function (item) { + if (typeof item === 'string') { + item = chart.options.exporting + .menuItemDefinitions[item]; + } + if (isObject(item, true)) { + var element; + if (item.separator) { + element = createElement('hr', null, null, innerMenu); + } + else { + element = createElement('li', { + className: 'highcharts-menu-item', + onclick: function (e) { + if (e) { // IE7 + e.stopPropagation(); + } + menu.hideMenu(); + if (item.onclick) { + item.onclick + .apply(chart, arguments); + } + }, + innerHTML: (item.text || + chart.options.lang[item.textKey]) + }, null, innerMenu); + if (!chart.styledMode) { + element.onmouseover = function () { + css(this, navOptions.menuItemHoverStyle); + }; + element.onmouseout = function () { + css(this, navOptions.menuItemStyle); + }; + css(element, extend({ + cursor: 'pointer' + }, navOptions.menuItemStyle)); + } + } + // Keep references to menu divs to be able to destroy them + chart.exportDivElements.push(element); + } + }); + // Keep references to menu and innerMenu div to be able to destroy + // them + chart.exportDivElements.push(innerMenu, menu); + chart.exportMenuWidth = menu.offsetWidth; + chart.exportMenuHeight = menu.offsetHeight; + } + menuStyle = { display: 'block' }; + // if outside right, right align it + if (x + chart.exportMenuWidth > chartWidth) { + menuStyle.right = (chartWidth - x - width - menuPadding) + 'px'; + } + else { + menuStyle.left = (x - menuPadding) + 'px'; + } + // if outside bottom, bottom align it + if (y + height + chart.exportMenuHeight > chartHeight && + button.alignOptions.verticalAlign !== 'top') { + menuStyle.bottom = (chartHeight - y - menuPadding) + 'px'; + } + else { + menuStyle.top = (y + height - menuPadding) + 'px'; + } + css(menu, menuStyle); + css(chart.renderTo, { overflow: '' }); // #10361 + chart.openMenu = true; + fireEvent(chart, 'exportMenuShown'); + }, + /** + * Add the export button to the chart, with options. + * + * @private + * @function Highcharts.Chart#addButton + * @param {Highcharts.NavigationButtonOptions} options + * @return {void} + * @requires modules/exporting + */ + addButton: function (options) { + var chart = this, + renderer = chart.renderer, + btnOptions = merge(chart.options.navigation.buttonOptions, + options), + onclick = btnOptions.onclick, + menuItems = btnOptions.menuItems, + symbol, + button, + symbolSize = btnOptions.symbolSize || 12; + if (!chart.btnCount) { + chart.btnCount = 0; + } + // Keeps references to the button elements + if (!chart.exportDivElements) { + chart.exportDivElements = []; + chart.exportSVGElements = []; + } + if (btnOptions.enabled === false) { + return; + } + var attr = btnOptions.theme, + states = attr.states, + hover = states && states.hover, + select = states && states.select, + callback; + if (!chart.styledMode) { + attr.fill = pick(attr.fill, '#ffffff'); + attr.stroke = pick(attr.stroke, 'none'); + } + delete attr.states; + if (onclick) { + callback = function (e) { + if (e) { + e.stopPropagation(); + } + onclick.call(chart, e); + }; + } + else if (menuItems) { + callback = function (e) { + // consistent with onclick call (#3495) + if (e) { + e.stopPropagation(); + } + chart.contextMenu(button.menuClassName, menuItems, button.translateX, button.translateY, button.width, button.height, button); + button.setState(2); + }; + } + if (btnOptions.text && btnOptions.symbol) { + attr.paddingLeft = pick(attr.paddingLeft, 25); + } + else if (!btnOptions.text) { + extend(attr, { + width: btnOptions.width, + height: btnOptions.height, + padding: 0 + }); + } + if (!chart.styledMode) { + attr['stroke-linecap'] = 'round'; + attr.fill = pick(attr.fill, '#ffffff'); + attr.stroke = pick(attr.stroke, 'none'); + } + button = renderer + .button(btnOptions.text, 0, 0, callback, attr, hover, select) + .addClass(options.className) + .attr({ + title: pick(chart.options.lang[btnOptions._titleKey || btnOptions.titleKey], '') + }); + button.menuClassName = (options.menuClassName || + 'highcharts-menu-' + chart.btnCount++); + if (btnOptions.symbol) { + symbol = renderer + .symbol(btnOptions.symbol, btnOptions.symbolX - (symbolSize / 2), btnOptions.symbolY - (symbolSize / 2), symbolSize, symbolSize + // If symbol is an image, scale it (#7957) + , { + width: symbolSize, + height: symbolSize + }) + .addClass('highcharts-button-symbol') + .attr({ + zIndex: 1 + }) + .add(button); + if (!chart.styledMode) { + symbol.attr({ + stroke: btnOptions.symbolStroke, + fill: btnOptions.symbolFill, + 'stroke-width': btnOptions.symbolStrokeWidth || 1 + }); + } + } + button + .add(chart.exportingGroup) + .align(extend(btnOptions, { + width: button.width, + x: pick(btnOptions.x, chart.buttonOffset) // #1654 + }), true, 'spacingBox'); + chart.buttonOffset += ((button.width + btnOptions.buttonSpacing) * + (btnOptions.align === 'right' ? -1 : 1)); + chart.exportSVGElements.push(button, symbol); + }, + /** + * Destroy the export buttons. + * @private + * @function Highcharts.Chart#destroyExport + * @param {global.Event} [e] + * @return {void} + * @requires modules/exporting + */ + destroyExport: function (e) { + var chart = e ? e.target : this, + exportSVGElements = chart.exportSVGElements, + exportDivElements = chart.exportDivElements, + exportEvents = chart.exportEvents, + cacheName; + // Destroy the extra buttons added + if (exportSVGElements) { + exportSVGElements.forEach(function (elem, i) { + // Destroy and null the svg elements + if (elem) { // #1822 + elem.onclick = elem.ontouchstart = null; + cacheName = 'cache-' + elem.menuClassName; + if (chart[cacheName]) { + delete chart[cacheName]; + } + chart.exportSVGElements[i] = elem.destroy(); + } + }); + exportSVGElements.length = 0; + } + // Destroy the exporting group + if (chart.exportingGroup) { + chart.exportingGroup.destroy(); + delete chart.exportingGroup; + } + // Destroy the divs for the menu + if (exportDivElements) { + exportDivElements.forEach(function (elem, i) { + // Remove the event handler + U.clearTimeout(elem.hideTimer); // #5427 + removeEvent(elem, 'mouseleave'); + // Remove inline events + chart.exportDivElements[i] = + elem.onmouseout = + elem.onmouseover = + elem.ontouchstart = + elem.onclick = null; + // Destroy the div by moving to garbage bin + discardElement(elem); + }); + exportDivElements.length = 0; + } + if (exportEvents) { + exportEvents.forEach(function (unbind) { + unbind(); + }); + exportEvents.length = 0; + } + } + /* eslint-enable no-invalid-this, valid-jsdoc */ + }); + // These ones are translated to attributes rather than styles + SVGRenderer.prototype.inlineToAttributes = [ + 'fill', + 'stroke', + 'strokeLinecap', + 'strokeLinejoin', + 'strokeWidth', + 'textAnchor', + 'x', + 'y' + ]; + // These CSS properties are not inlined. Remember camelCase. + SVGRenderer.prototype.inlineBlacklist = [ + /-/, + /^(clipPath|cssText|d|height|width)$/, + /^font$/, + /[lL]ogical(Width|Height)$/, + /perspective/, + /TapHighlightColor/, + /^transition/, + /^length$/ // #7700 + // /^text (border|color|cursor|height|webkitBorder)/ + ]; + SVGRenderer.prototype.unstyledElements = [ + 'clipPath', + 'defs', + 'desc' + ]; + /** + * Analyze inherited styles from stylesheets and add them inline + * + * @private + * @function Highcharts.Chart#inlineStyles + * @return {void} + * + * @todo: What are the border styles for text about? In general, text has a lot + * of properties. + * @todo: Make it work with IE9 and IE10. + * + * @requires modules/exporting + */ + Chart.prototype.inlineStyles = function () { + var renderer = this.renderer, + inlineToAttributes = renderer.inlineToAttributes, + blacklist = renderer.inlineBlacklist, + whitelist = renderer.inlineWhitelist, // For IE + unstyledElements = renderer.unstyledElements, + defaultStyles = {}, + dummySVG, + iframe, + iframeDoc; + // Create an iframe where we read default styles without pollution from this + // body + iframe = doc.createElement('iframe'); + css(iframe, { + width: '1px', + height: '1px', + visibility: 'hidden' + }); + doc.body.appendChild(iframe); + iframeDoc = iframe.contentWindow.document; + iframeDoc.open(); + iframeDoc.write(''); + iframeDoc.close(); + /** + * Make hyphenated property names out of camelCase + * @private + * @param {string} prop + * Property name in camelCase + * @return {string} + * Hyphenated property name + */ + function hyphenate(prop) { + return prop.replace(/([A-Z])/g, function (a, b) { + return '-' + b.toLowerCase(); + }); + } + /** + * Call this on all elements and recurse to children + * @private + * @param {Highcharts.HTMLDOMElement} node + * Element child + * @return {void} + */ + function recurse(node) { + var styles, + parentStyles, + cssText = '', + dummy, + styleAttr, + blacklisted, + whitelisted, + i; + /** + * Check computed styles and whether they are in the white/blacklist for + * styles or atttributes. + * @private + * @param {string} val + * Style value + * @param {string} prop + * Style property name + * @return {void} + */ + function filterStyles(val, prop) { + // Check against whitelist & blacklist + blacklisted = whitelisted = false; + if (whitelist) { + // Styled mode in IE has a whitelist instead. + // Exclude all props not in this list. + i = whitelist.length; + while (i-- && !whitelisted) { + whitelisted = whitelist[i].test(prop); + } + blacklisted = !whitelisted; + } + // Explicitly remove empty transforms + if (prop === 'transform' && val === 'none') { + blacklisted = true; + } + i = blacklist.length; + while (i-- && !blacklisted) { + blacklisted = (blacklist[i].test(prop) || + typeof val === 'function'); + } + if (!blacklisted) { + // If parent node has the same style, it gets inherited, no need + // to inline it. Top-level props should be diffed against parent + // (#7687). + if ((parentStyles[prop] !== val || node.nodeName === 'svg') && + defaultStyles[node.nodeName][prop] !== val) { + // Attributes + if (!inlineToAttributes || + inlineToAttributes.indexOf(prop) !== -1) { + if (val) { + node.setAttribute(hyphenate(prop), val); + } + // Styles + } + else { + cssText += hyphenate(prop) + ':' + val + ';'; + } + } + } + } + if (node.nodeType === 1 && + unstyledElements.indexOf(node.nodeName) === -1) { + styles = win.getComputedStyle(node, null); + parentStyles = node.nodeName === 'svg' ? + {} : + win.getComputedStyle(node.parentNode, null); + // Get default styles from the browser so that we don't have to add + // these + if (!defaultStyles[node.nodeName]) { + /* + if (!dummySVG) { + dummySVG = doc.createElementNS(H.SVG_NS, 'svg'); + dummySVG.setAttribute('version', '1.1'); + doc.body.appendChild(dummySVG); + } + */ + dummySVG = iframeDoc.getElementsByTagName('svg')[0]; + dummy = iframeDoc.createElementNS(node.namespaceURI, node.nodeName); + dummySVG.appendChild(dummy); + // Copy, so we can remove the node + defaultStyles[node.nodeName] = merge(win.getComputedStyle(dummy, null)); + // Remove default fill, otherwise text disappears when exported + if (node.nodeName === 'text') { + delete defaultStyles.text.fill; + } + dummySVG.removeChild(dummy); + } + // Loop through all styles and add them inline if they are ok + if (isFirefoxBrowser || isMSBrowser) { + // Some browsers put lots of styles on the prototype + for (var p in styles) { // eslint-disable-line guard-for-in + filterStyles(styles[p], p); + } + } + else { + objectEach(styles, filterStyles); + } + // Apply styles + if (cssText) { + styleAttr = node.getAttribute('style'); + node.setAttribute('style', (styleAttr ? styleAttr + ';' : '') + cssText); + } + // Set default stroke width (needed at least for IE) + if (node.nodeName === 'svg') { + node.setAttribute('stroke-width', '1px'); + } + if (node.nodeName === 'text') { + return; + } + // Recurse + [].forEach.call(node.children || node.childNodes, recurse); + } + } + /** + * Remove the dummy objects used to get defaults + * @private + * @return {void} + */ + function tearDown() { + dummySVG.parentNode.removeChild(dummySVG); + } + recurse(this.container.querySelector('svg')); + tearDown(); + }; + symbols.menu = function (x, y, width, height) { + var arr = [ + ['M', + x, + y + 2.5], + ['L', + x + width, + y + 2.5], + ['M', + x, + y + height / 2 + 0.5], + ['L', + x + width, + y + height / 2 + 0.5], + ['M', + x, + y + height - 1.5], + ['L', + x + width, + y + height - 1.5] + ]; + return arr; + }; + symbols.menuball = function (x, y, width, height) { + var path = [], + h = (height / 3) - 2; + path = path.concat(this.circle(width - h, y, h, h), this.circle(width - h, y + h + 4, h, h), this.circle(width - h, y + 2 * (h + 4), h, h)); + return path; + }; + /** + * Add the buttons on chart load + * @private + * @function Highcharts.Chart#renderExporting + * @return {void} + * @requires modules/exporting + */ + Chart.prototype.renderExporting = function () { + var chart = this, + exportingOptions = chart.options.exporting, + buttons = exportingOptions.buttons, + isDirty = chart.isDirtyExporting || !chart.exportSVGElements; + chart.buttonOffset = 0; + if (chart.isDirtyExporting) { + chart.destroyExport(); + } + if (isDirty && exportingOptions.enabled !== false) { + chart.exportEvents = []; + chart.exportingGroup = chart.exportingGroup || + chart.renderer.g('exporting-group').attr({ + zIndex: 3 // #4955, // #8392 + }).add(); + objectEach(buttons, function (button) { + chart.addButton(button); + }); + chart.isDirtyExporting = false; + } + // Destroy the export elements at chart destroy + addEvent(chart, 'destroy', chart.destroyExport); + }; + /* eslint-disable no-invalid-this */ + // Add update methods to handle chart.update and chart.exporting.update and + // chart.navigation.update. These must be added to the chart instance rather + // than the Chart prototype in order to use the chart instance inside the update + // function. + addEvent(Chart, 'init', function () { + var chart = this; + /** + * @private + * @param {"exporting"|"navigation"} prop + * Property name in option root + * @param {Highcharts.ExportingOptions|Highcharts.NavigationOptions} options + * Options to update + * @param {boolean} [redraw=true] + * Whether to redraw + * @return {void} + */ + function update(prop, options, redraw) { + chart.isDirtyExporting = true; + merge(true, chart.options[prop], options); + if (pick(redraw, true)) { + chart.redraw(); + } + } + chart.exporting = { + update: function (options, redraw) { + update('exporting', options, redraw); + } + }; + // Register update() method for navigation. Can not be set the same way as + // for exporting, because navigation options are shared with bindings which + // has separate update() logic. + chartNavigationMixin.addUpdate(function (options, redraw) { + update('navigation', options, redraw); + }, chart); + }); + /* eslint-enable no-invalid-this */ + Chart.prototype.callbacks.push(function (chart) { + chart.renderExporting(); + addEvent(chart, 'redraw', chart.renderExporting); + // Uncomment this to see a button directly below the chart, for quick + // testing of export + /* + var button, + viewImage, + viewSource; + if (!chart.renderer.forExport) { + viewImage = function () { + var div = doc.createElement('div'); + div.innerHTML = chart.getSVGForExport(); + chart.renderTo.parentNode.appendChild(div); + }; + + viewSource = function () { + var pre = doc.createElement('pre'); + pre.innerHTML = chart.getSVGForExport() + .replace(//g, '>'); + chart.renderTo.parentNode.appendChild(pre); + }; + + viewImage(); + + // View SVG Image + button = doc.createElement('button'); + button.innerHTML = 'View SVG Image'; + chart.renderTo.parentNode.appendChild(button); + button.onclick = viewImage; + + // View SVG Source + button = doc.createElement('button'); + button.innerHTML = 'View SVG Source'; + chart.renderTo.parentNode.appendChild(button); + button.onclick = viewSource; + } + //*/ + }); + + }); + _registerModule(_modules, 'masters/modules/exporting.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/full-screen.js b/highcharts/modules/full-screen.js new file mode 100644 index 0000000..2c0f026 --- /dev/null +++ b/highcharts/modules/full-screen.js @@ -0,0 +1,17 @@ +/* + Highstock JS v8.2.0 (2020-08-20) + + Advanced Highstock tools + + (c) 2010-2019 Highsoft AS + Author: Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/full-screen",["highcharts"],function(c){a(c);a.Highcharts=c;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function c(a,g,c,d){a.hasOwnProperty(g)||(a[g]=d.apply(null,c))}a=a?a._modules:{};c(a,"Extensions/FullScreen.js",[a["Core/Chart/Chart.js"],a["Core/Globals.js"],a["Core/Utilities.js"]],function(a,c,f){var d=f.addEvent; +f=function(){function a(b){this.chart=b;this.isOpen=!1;b=b.renderTo;this.browserProps||("function"===typeof b.requestFullscreen?this.browserProps={fullscreenChange:"fullscreenchange",requestFullscreen:"requestFullscreen",exitFullscreen:"exitFullscreen"}:b.mozRequestFullScreen?this.browserProps={fullscreenChange:"mozfullscreenchange",requestFullscreen:"mozRequestFullScreen",exitFullscreen:"mozCancelFullScreen"}:b.webkitRequestFullScreen?this.browserProps={fullscreenChange:"webkitfullscreenchange", +requestFullscreen:"webkitRequestFullScreen",exitFullscreen:"webkitExitFullscreen"}:b.msRequestFullscreen&&(this.browserProps={fullscreenChange:"MSFullscreenChange",requestFullscreen:"msRequestFullscreen",exitFullscreen:"msExitFullscreen"}))}a.prototype.close=function(){var b=this.chart;if(this.isOpen&&this.browserProps&&b.container.ownerDocument instanceof Document)b.container.ownerDocument[this.browserProps.exitFullscreen]();this.unbindFullscreenEvent&&this.unbindFullscreenEvent();this.isOpen=!1; +this.setButtonText()};a.prototype.open=function(){var b=this,a=b.chart;if(b.browserProps){b.unbindFullscreenEvent=d(a.container.ownerDocument,b.browserProps.fullscreenChange,function(){b.isOpen?(b.isOpen=!1,b.close()):(b.isOpen=!0,b.setButtonText())});var c=a.renderTo[b.browserProps.requestFullscreen]();if(c)c["catch"](function(){alert("Full screen is not supported inside a frame.")});d(a,"destroy",b.unbindFullscreenEvent)}};a.prototype.setButtonText=function(){var b,a=this.chart,c=a.exportDivElements, +e=a.options.exporting,d=null===(b=null===e||void 0===e?void 0:e.buttons)||void 0===b?void 0:b.contextButton.menuItems;b=a.options.lang;(null===e||void 0===e?0:e.menuItemDefinitions)&&(null===b||void 0===b?0:b.exitFullscreen)&&b.viewFullscreen&&d&&c&&c.length&&(c[d.indexOf("viewFullscreen")].innerHTML=this.isOpen?b.exitFullscreen:e.menuItemDefinitions.viewFullscreen.text||b.viewFullscreen)};a.prototype.toggle=function(){this.isOpen?this.close():this.open()};return a}();c.Fullscreen=f;d(a,"beforeRender", +function(){this.fullscreen=new c.Fullscreen(this)});return c.Fullscreen});c(a,"masters/modules/full-screen.src.js",[],function(){})}); +//# sourceMappingURL=full-screen.js.map \ No newline at end of file diff --git a/highcharts/modules/full-screen.js.map b/highcharts/modules/full-screen.js.map new file mode 100644 index 0000000..0e333c9 --- /dev/null +++ b/highcharts/modules/full-screen.js.map @@ -0,0 +1 @@ +{"version":3,"file":"full-screen.js.map","lineCount":16,"mappings":"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","sources":["full-screen.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","Chart","H","U","addEvent","Fullscreen","chart","isOpen","container","renderTo","browserProps","requestFullscreen","fullscreenChange","exitFullscreen","mozRequestFullScreen","webkitRequestFullScreen","msRequestFullscreen","prototype","close","Fullscreen.prototype.close","fullscreen","ownerDocument","Document","unbindFullscreenEvent","setButtonText","open","Fullscreen.prototype.open","promise","alert","Fullscreen.prototype.setButtonText","_a","exportDivElements","exportingOptions","options","exporting","menuItems","buttons","contextButton","lang","menuItemDefinitions","viewFullscreen","length","indexOf","innerHTML","text","toggle","Fullscreen.prototype.toggle"]} \ No newline at end of file diff --git a/highcharts/modules/full-screen.src.js b/highcharts/modules/full-screen.src.js new file mode 100644 index 0000000..5bb79bc --- /dev/null +++ b/highcharts/modules/full-screen.src.js @@ -0,0 +1,255 @@ +/** + * @license Highstock JS v8.2.0 (2020-08-20) + * + * Advanced Highstock tools + * + * (c) 2010-2019 Highsoft AS + * Author: Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/full-screen', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'Extensions/FullScreen.js', [_modules['Core/Chart/Chart.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (Chart, H, U) { + /* * + * (c) 2009-2020 Rafal Sebestjanski + * + * Full screen for Highcharts + * + * License: www.highcharts.com/license + */ + var addEvent = U.addEvent; + /** + * The module allows user to enable display chart in full screen mode. + * Used in StockTools too. + * Based on default solutions in browsers. + * + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Handles displaying chart's container in the fullscreen mode. + * + * **Note**: Fullscreen is not supported on iPhone due to iOS limitations. + * + * @class + * @name Highcharts.Fullscreen + * @hideconstructor + * @requires modules/full-screen + */ + var Fullscreen = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Fullscreen(chart) { + /** + * Chart managed by the fullscreen controller. + * @name Highcharts.Fullscreen#chart + * @type {Highcharts.Chart} + */ + this.chart = chart; + /** + * The flag is set to `true` when the chart is displayed in + * the fullscreen mode. + * + * @name Highcharts.Fullscreen#isOpen + * @type {boolean|undefined} + * @since 8.0.1 + */ + this.isOpen = false; + var container = chart.renderTo; + // Hold event and methods available only for a current browser. + if (!this.browserProps) { + if (typeof container.requestFullscreen === 'function') { + this.browserProps = { + fullscreenChange: 'fullscreenchange', + requestFullscreen: 'requestFullscreen', + exitFullscreen: 'exitFullscreen' + }; + } + else if (container.mozRequestFullScreen) { + this.browserProps = { + fullscreenChange: 'mozfullscreenchange', + requestFullscreen: 'mozRequestFullScreen', + exitFullscreen: 'mozCancelFullScreen' + }; + } + else if (container.webkitRequestFullScreen) { + this.browserProps = { + fullscreenChange: 'webkitfullscreenchange', + requestFullscreen: 'webkitRequestFullScreen', + exitFullscreen: 'webkitExitFullscreen' + }; + } + else if (container.msRequestFullscreen) { + this.browserProps = { + fullscreenChange: 'MSFullscreenChange', + requestFullscreen: 'msRequestFullscreen', + exitFullscreen: 'msExitFullscreen' + }; + } + } + } + /* * + * + * Functions + * + * */ + /** + * Stops displaying the chart in fullscreen mode. + * Exporting module required. + * + * @since 8.0.1 + * + * @function Highcharts.Fullscreen#close + * @return {void} + * @requires modules/full-screen + */ + Fullscreen.prototype.close = function () { + var fullscreen = this, + chart = fullscreen.chart; + // Don't fire exitFullscreen() when user exited using 'Escape' button. + if (fullscreen.isOpen && + fullscreen.browserProps && + chart.container.ownerDocument instanceof Document) { + chart.container.ownerDocument[fullscreen.browserProps.exitFullscreen](); + } + // Unbind event as it's necessary only before exiting from fullscreen. + if (fullscreen.unbindFullscreenEvent) { + fullscreen.unbindFullscreenEvent(); + } + fullscreen.isOpen = false; + fullscreen.setButtonText(); + }; + /** + * Displays the chart in fullscreen mode. + * When fired customly by user before exporting context button is created, + * button's text will not be replaced - it's on the user side. + * Exporting module required. + * + * @since 8.0.1 + * + * @function Highcharts.Fullscreen#open + * @return {void} + * @requires modules/full-screen + */ + Fullscreen.prototype.open = function () { + var fullscreen = this, + chart = fullscreen.chart; + // Handle exitFullscreen() method when user clicks 'Escape' button. + if (fullscreen.browserProps) { + fullscreen.unbindFullscreenEvent = addEvent(chart.container.ownerDocument, // chart's document + fullscreen.browserProps.fullscreenChange, function () { + // Handle lack of async of browser's fullScreenChange event. + if (fullscreen.isOpen) { + fullscreen.isOpen = false; + fullscreen.close(); + } + else { + fullscreen.isOpen = true; + fullscreen.setButtonText(); + } + }); + var promise = chart.renderTo[fullscreen.browserProps.requestFullscreen](); + if (promise) { + // No dot notation because of IE8 compatibility + promise['catch'](function () { + alert(// eslint-disable-line no-alert + 'Full screen is not supported inside a frame.'); + }); + } + addEvent(chart, 'destroy', fullscreen.unbindFullscreenEvent); + } + }; + /** + * Replaces the exporting context button's text when toogling the + * fullscreen mode. + * + * @private + * + * @since 8.0.1 + * + * @requires modules/full-screen + * @return {void} + */ + Fullscreen.prototype.setButtonText = function () { + var _a; + var chart = this.chart, + exportDivElements = chart.exportDivElements, + exportingOptions = chart.options.exporting, + menuItems = (_a = exportingOptions === null || exportingOptions === void 0 ? void 0 : exportingOptions.buttons) === null || _a === void 0 ? void 0 : _a.contextButton.menuItems, + lang = chart.options.lang; + if ((exportingOptions === null || exportingOptions === void 0 ? void 0 : exportingOptions.menuItemDefinitions) && (lang === null || lang === void 0 ? void 0 : lang.exitFullscreen) && + lang.viewFullscreen && + menuItems && + exportDivElements && + exportDivElements.length) { + exportDivElements[menuItems.indexOf('viewFullscreen')] + .innerHTML = !this.isOpen ? + (exportingOptions.menuItemDefinitions.viewFullscreen.text || + lang.viewFullscreen) : lang.exitFullscreen; + } + }; + /** + * Toggles displaying the chart in fullscreen mode. + * By default, when the exporting module is enabled, a context button with + * a drop down menu in the upper right corner accesses this function. + * Exporting module required. + * + * @since 8.0.1 + * + * @sample highcharts/members/chart-togglefullscreen/ + * Toggle fullscreen mode from a HTML button + * + * @function Highcharts.Fullscreen#toggle + * @requires modules/full-screen + */ + Fullscreen.prototype.toggle = function () { + var fullscreen = this; + if (!fullscreen.isOpen) { + fullscreen.open(); + } + else { + fullscreen.close(); + } + }; + return Fullscreen; + }()); + H.Fullscreen = Fullscreen; + // Initialize fullscreen + addEvent(Chart, 'beforeRender', function () { + /** + * @name Highcharts.Chart#fullscreen + * @type {Highcharts.Fullscreen} + * @requires modules/full-screen + */ + this.fullscreen = new H.Fullscreen(this); + }); + + return H.Fullscreen; + }); + _registerModule(_modules, 'masters/modules/full-screen.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/funnel.js b/highcharts/modules/funnel.js new file mode 100644 index 0000000..882fd81 --- /dev/null +++ b/highcharts/modules/funnel.js @@ -0,0 +1,18 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Highcharts funnel module + + (c) 2010-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/funnel",["highcharts"],function(e){b(e);b.Highcharts=e;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function e(b,l,n,e){b.hasOwnProperty(l)||(b[l]=e.apply(null,n))}var x=b?b._modules:{};e(x,"Series/FunnelSeries.js",[x["Core/Chart/Chart.js"],x["Core/Globals.js"],x["Core/Utilities.js"]],function(e,l,n){var x=l.noop, +C=l.seriesType,I=l.seriesTypes;l=n.addEvent;var J=n.fireEvent,K=n.isArray,H=n.pick;C("funnel","pie",{animation:!1,center:["50%","50%"],width:"90%",neckWidth:"30%",height:"100%",neckHeight:"25%",reversed:!1,size:!0,dataLabels:{connectorWidth:1,verticalAlign:"middle"},states:{select:{color:"#cccccc",borderColor:"#000000"}}},{animate:x,translate:function(){function a(a,c){return/%$/.test(a)?c*parseInt(a,10)/100:parseInt(a,10)}var r=0,c=this,g=c.chart,f=c.options,k=f.reversed,d=f.ignoreHiddenPoint,b= +g.plotWidth;g=g.plotHeight;var e=0,l=f.center,h=a(l[0],b),m=a(l[1],g),n=a(f.width,b),u,v=a(f.height,g),z=a(f.neckWidth,b),G=a(f.neckHeight,g),A=m-v/2+v-G;b=c.data;var D,E,C="left"===f.dataLabels.position?1:0,B,p,F,w,q,y,t;c.getWidthAt=function(a){var c=m-v/2;return a>A||v===G?z:z+(n-z)*(1-(a-c)/(v-G))};c.getX=function(a,d,b){return h+(d?-1:1)*(c.getWidthAt(k?2*m-a:a)/2+b.labelDistance)};c.center=[h,m,v];c.centerX=h;b.forEach(function(a){d&&!1===a.visible||(r+=a.y)});b.forEach(function(a){t=null;E= +r?a.y/r:0;p=m-v/2+e*v;q=p+E*v;u=c.getWidthAt(p);B=h-u/2;F=B+u;u=c.getWidthAt(q);w=h-u/2;y=w+u;p>A?(B=w=h-z/2,F=y=h+z/2):q>A&&(t=q,u=c.getWidthAt(A),w=h-u/2,y=w+u,q=A);k&&(p=2*m-p,q=2*m-q,null!==t&&(t=2*m-t));D=[["M",B,p],["L",F,p],["L",y,q]];null!==t&&D.push(["L",y,t],["L",w,t]);D.push(["L",w,q],["Z"]);a.shapeType="path";a.shapeArgs={d:D};a.percentage=100*E;a.plotX=h;a.plotY=(p+(t||q))/2;a.tooltipPos=[h,a.plotY];a.dlBox={x:w,y:p,topWidth:F-B,bottomWidth:y-w,height:Math.abs(H(t,q)-p),width:NaN};a.slice= +x;a.half=C;d&&!1===a.visible||(e+=E)});J(c,"afterTranslate")},sortByAngle:function(a){a.sort(function(a,c){return a.plotY-c.plotY})},drawDataLabels:function(){var a=this.data,b=this.options.dataLabels.distance,c,g=a.length;for(this.center[2]-=2*b;g--;){var f=a[g];var k=(c=f.half)?1:-1;var d=f.plotY;f.labelDistance=H(f.options.dataLabels&&f.options.dataLabels.distance,b);this.maxLabelDistance=Math.max(f.labelDistance,this.maxLabelDistance||0);var e=this.getX(d,c,f);f.labelPosition={natural:{x:0,y:d}, +"final":{},alignment:c?"right":"left",connectorPosition:{breakAt:{x:e+(f.labelDistance-5)*k,y:d},touchingSliceAt:{x:e+f.labelDistance*k,y:d}}}}I[this.options.dataLabels.inside?"column":"pie"].prototype.drawDataLabels.call(this)},alignDataLabel:function(a,e,c,g,f){var k=a.series;g=k.options.reversed;var d=a.dlBox||a.shapeArgs,l=c.align,r=c.verticalAlign,n=((k.options||{}).dataLabels||{}).inside,h=k.center[1];k=k.getWidthAt((g?2*h-a.plotY:a.plotY)-d.height/2+e.height);k="middle"===r?(d.topWidth-d.bottomWidth)/ +4:(k-d.bottomWidth)/2;h=d.y;var m=d.x;"middle"===r?h=d.y-d.height/2+e.height/2:"top"===r&&(h=d.y-d.height+e.height+c.padding);if("top"===r&&!g||"bottom"===r&&g||"middle"===r)"right"===l?m=d.x-c.padding+k:"left"===l&&(m=d.x+c.padding-k);g={x:m,y:g?h-d.height:h,width:d.bottomWidth,height:d.height};c.verticalAlign="bottom";n&&!a.visible||b.Series.prototype.alignDataLabel.call(this,a,e,c,g,f);n&&(!a.visible&&a.dataLabel&&(a.dataLabel.placed=!1),a.contrastColor&&e.css({color:a.contrastColor}))}});l(e, +"afterHideAllOverlappingLabels",function(){this.series.forEach(function(a){var b=a.options&&a.options.dataLabels;K(b)&&(b=b[0]);a.is("pie")&&a.placeDataLabels&&b&&!b.inside&&a.placeDataLabels()})});C("pyramid","funnel",{neckWidth:"0%",neckHeight:"0%",reversed:!0});""});e(x,"masters/modules/funnel.src.js",[],function(){})}); +//# sourceMappingURL=funnel.js.map \ No newline at end of file diff --git a/highcharts/modules/funnel.js.map b/highcharts/modules/funnel.js.map new file mode 100644 index 0000000..3149451 --- /dev/null +++ b/highcharts/modules/funnel.js.map @@ -0,0 +1 @@ +{"version":3,"file":"funnel.js.map","lineCount":17,"mappings":"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","sources":["funnel.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","Chart","H","U","noop","seriesType","seriesTypes","addEvent","fireEvent","isArray","pick","animation","center","width","neckWidth","height","neckHeight","reversed","size","dataLabels","connectorWidth","verticalAlign","states","select","color","borderColor","animate","translate","getLength","length","relativeTo","test","parseInt","sum","series","chart","options","ignoreHiddenPoint","plotWidth","plotHeight","cumulative","centerX","centerY","tempWidth","neckY","data","fraction","half","position","x1","y1","x2","x3","y3","x4","y5","getWidthAt","series.getWidthAt","y","top","getX","series.getX","point","labelDistance","forEach","visible","push","shapeType","shapeArgs","d","percentage","plotX","plotY","tooltipPos","dlBox","x","topWidth","bottomWidth","Math","abs","NaN","slice","sortByAngle","points","sort","a","b","drawDataLabels","distance","leftSide","i","sign","maxLabelDistance","max","labelPosition","natural","alignment","connectorPosition","breakAt","touchingSliceAt","inside","prototype","call","alignDataLabel","dataLabel","alignTo","isNew","align","widthAtLabel","pointPlotY","offset","padding","Series","placed","contrastColor","css","dataLabelsOptions","is","placeDataLabels"]} \ No newline at end of file diff --git a/highcharts/modules/funnel.src.js b/highcharts/modules/funnel.src.js new file mode 100644 index 0000000..f743069 --- /dev/null +++ b/highcharts/modules/funnel.src.js @@ -0,0 +1,636 @@ +/** + * @license Highcharts JS v8.2.0 (2020-08-20) + * + * Highcharts funnel module + * + * (c) 2010-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/funnel', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'Series/FunnelSeries.js', [_modules['Core/Chart/Chart.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (Chart, H, U) { + /* * + * + * Highcharts funnel module + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* eslint indent: 0 */ + var noop = H.noop, + seriesType = H.seriesType, + seriesTypes = H.seriesTypes; + var addEvent = U.addEvent, + fireEvent = U.fireEvent, + isArray = U.isArray, + pick = U.pick; + /** + * @private + * @class + * @name Highcharts.seriesTypes.funnel + * + * @augments Highcharts.Series + */ + seriesType('funnel', 'pie', + /** + * Funnel charts are a type of chart often used to visualize stages in a + * sales project, where the top are the initial stages with the most + * clients. It requires that the modules/funnel.js file is loaded. + * + * @sample highcharts/demo/funnel/ + * Funnel demo + * + * @extends plotOptions.pie + * @excluding innerSize,size,dataSorting + * @product highcharts + * @requires modules/funnel + * @optionparent plotOptions.funnel + */ + { + /** + * Initial animation is by default disabled for the funnel chart. + */ + animation: false, + /** + * The center of the series. By default, it is centered in the middle + * of the plot area, so it fills the plot area height. + * + * @type {Array} + * @default ["50%", "50%"] + * @since 3.0 + */ + center: ['50%', '50%'], + /** + * The width of the funnel compared to the width of the plot area, + * or the pixel width if it is a number. + * + * @type {number|string} + * @since 3.0 + */ + width: '90%', + /** + * The width of the neck, the lower part of the funnel. A number defines + * pixel width, a percentage string defines a percentage of the plot + * area width. + * + * @sample {highcharts} highcharts/demo/funnel/ + * Funnel demo + * + * @type {number|string} + * @since 3.0 + */ + neckWidth: '30%', + /** + * The height of the funnel or pyramid. If it is a number it defines + * the pixel height, if it is a percentage string it is the percentage + * of the plot area height. + * + * @sample {highcharts} highcharts/demo/funnel/ + * Funnel demo + * + * @type {number|string} + * @since 3.0 + */ + height: '100%', + /** + * The height of the neck, the lower part of the funnel. A number + * defines pixel width, a percentage string defines a percentage of the + * plot area height. + * + * @type {number|string} + */ + neckHeight: '25%', + /** + * A reversed funnel has the widest area down. A reversed funnel with + * no neck width and neck height is a pyramid. + * + * @since 3.0.10 + */ + reversed: false, + /** + * To avoid adapting the data label size in Pie.drawDataLabels. + * @ignore-option + */ + size: true, + dataLabels: { + connectorWidth: 1, + verticalAlign: 'middle' + }, + /** + * Options for the series states. + */ + states: { + /** + * @excluding halo, marker, lineWidth, lineWidthPlus + * @apioption plotOptions.funnel.states.hover + */ + /** + * Options for a selected funnel item. + * + * @excluding halo, marker, lineWidth, lineWidthPlus + */ + select: { + /** + * A specific color for the selected point. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + color: '#cccccc', + /** + * A specific border color for the selected point. + * + * @type {Highcharts.ColorString} + */ + borderColor: '#000000' + } + } + }, + // Properties + { + animate: noop, + // Overrides the pie translate method + translate: function () { + var sum = 0, + series = this, + chart = series.chart, + options = series.options, + reversed = options.reversed, + ignoreHiddenPoint = options.ignoreHiddenPoint, + plotWidth = chart.plotWidth, + plotHeight = chart.plotHeight, + cumulative = 0, // start at top + center = options.center, + centerX = getLength(center[0], + plotWidth), + centerY = getLength(center[1], + plotHeight), + width = getLength(options.width, + plotWidth), + tempWidth, + height = getLength(options.height, + plotHeight), + neckWidth = getLength(options.neckWidth, + plotWidth), + neckHeight = getLength(options.neckHeight, + plotHeight), + neckY = (centerY - height / 2) + height - neckHeight, + data = series.data, + path, + fraction, + half = (options.dataLabels.position === 'left' ? + 1 : + 0), + x1, + y1, + x2, + x3, + y3, + x4, + y5; + /** + * Get positions - either an integer or a percentage string must be + * given. + * @private + * @param {number|string|undefined} length + * Length + * @param {number} relativeTo + * Relative factor + * @return {number} + * Relative position + */ + function getLength(length, relativeTo) { + return (/%$/).test(length) ? + relativeTo * parseInt(length, 10) / 100 : + parseInt(length, 10); + } + series.getWidthAt = function (y) { + var top = (centerY - height / 2); + return (y > neckY || height === neckHeight) ? + neckWidth : + neckWidth + (width - neckWidth) * + (1 - (y - top) / (height - neckHeight)); + }; + series.getX = function (y, half, point) { + return centerX + (half ? -1 : 1) * + ((series.getWidthAt(reversed ? 2 * centerY - y : y) / 2) + + point.labelDistance); + }; + // Expose + series.center = [centerX, centerY, height]; + series.centerX = centerX; + /* + Individual point coordinate naming: + + x1,y1 _________________ x2,y1 + \ / + \ / + \ / + \ / + \ / + x3,y3 _________ x4,y3 + + Additional for the base of the neck: + + | | + | | + | | + x3,y5 _________ x4,y5 + + */ + // get the total sum + data.forEach(function (point) { + if (!ignoreHiddenPoint || point.visible !== false) { + sum += point.y; + } + }); + data.forEach(function (point) { + // set start and end positions + y5 = null; + fraction = sum ? point.y / sum : 0; + y1 = centerY - height / 2 + cumulative * height; + y3 = y1 + fraction * height; + tempWidth = series.getWidthAt(y1); + x1 = centerX - tempWidth / 2; + x2 = x1 + tempWidth; + tempWidth = series.getWidthAt(y3); + x3 = centerX - tempWidth / 2; + x4 = x3 + tempWidth; + // the entire point is within the neck + if (y1 > neckY) { + x1 = x3 = centerX - neckWidth / 2; + x2 = x4 = centerX + neckWidth / 2; + // the base of the neck + } + else if (y3 > neckY) { + y5 = y3; + tempWidth = series.getWidthAt(neckY); + x3 = centerX - tempWidth / 2; + x4 = x3 + tempWidth; + y3 = neckY; + } + if (reversed) { + y1 = 2 * centerY - y1; + y3 = 2 * centerY - y3; + if (y5 !== null) { + y5 = 2 * centerY - y5; + } + } + // save the path + path = [ + ['M', x1, y1], + ['L', x2, y1], + ['L', x4, y3] + ]; + if (y5 !== null) { + path.push(['L', x4, y5], ['L', x3, y5]); + } + path.push(['L', x3, y3], ['Z']); + // prepare for using shared dr + point.shapeType = 'path'; + point.shapeArgs = { d: path }; + // for tooltips and data labels + point.percentage = fraction * 100; + point.plotX = centerX; + point.plotY = (y1 + (y5 || y3)) / 2; + // Placement of tooltips and data labels + point.tooltipPos = [ + centerX, + point.plotY + ]; + point.dlBox = { + x: x3, + y: y1, + topWidth: x2 - x1, + bottomWidth: x4 - x3, + height: Math.abs(pick(y5, y3) - y1), + width: NaN + }; + // Slice is a noop on funnel points + point.slice = noop; + // Mimicking pie data label placement logic + point.half = half; + if (!ignoreHiddenPoint || point.visible !== false) { + cumulative += fraction; + } + }); + fireEvent(series, 'afterTranslate'); + }, + // Funnel items don't have angles (#2289) + sortByAngle: function (points) { + points.sort(function (a, b) { + return a.plotY - b.plotY; + }); + }, + // Extend the pie data label method + drawDataLabels: function () { + var series = this, + data = series.data, + labelDistance = series.options.dataLabels.distance, + leftSide, + sign, + point, + i = data.length, + x, + y; + // In the original pie label anticollision logic, the slots are + // distributed from one labelDistance above to one labelDistance + // below the pie. In funnels we don't want this. + series.center[2] -= 2 * labelDistance; + // Set the label position array for each point. + while (i--) { + point = data[i]; + leftSide = point.half; + sign = leftSide ? 1 : -1; + y = point.plotY; + point.labelDistance = pick(point.options.dataLabels && + point.options.dataLabels.distance, labelDistance); + series.maxLabelDistance = Math.max(point.labelDistance, series.maxLabelDistance || 0); + x = series.getX(y, leftSide, point); + // set the anchor point for data labels + point.labelPosition = { + // initial position of the data label - it's utilized for + // finding the final position for the label + natural: { + x: 0, + y: y + }, + 'final': { + // used for generating connector path - + // initialized later in drawDataLabels function + // x: undefined, + // y: undefined + }, + // left - funnel on the left side of the data label + // right - funnel on the right side of the data label + alignment: leftSide ? 'right' : 'left', + connectorPosition: { + breakAt: { + x: x + (point.labelDistance - 5) * sign, + y: y + }, + touchingSliceAt: { + x: x + point.labelDistance * sign, + y: y + } + } + }; + } + seriesTypes[series.options.dataLabels.inside ? 'column' : 'pie'].prototype.drawDataLabels.call(this); + }, + alignDataLabel: function (point, dataLabel, options, alignTo, isNew) { + var series = point.series, + reversed = series.options.reversed, + dlBox = point.dlBox || point.shapeArgs, + align = options.align, + verticalAlign = options.verticalAlign, + inside = ((series.options || {}).dataLabels || {}).inside, + centerY = series.center[1], + pointPlotY = (reversed ? + 2 * centerY - point.plotY : + point.plotY), + widthAtLabel = series.getWidthAt(pointPlotY - dlBox.height / 2 + + dataLabel.height), + offset = verticalAlign === 'middle' ? + (dlBox.topWidth - dlBox.bottomWidth) / 4 : + (widthAtLabel - dlBox.bottomWidth) / 2, + y = dlBox.y, + x = dlBox.x; + if (verticalAlign === 'middle') { + y = dlBox.y - dlBox.height / 2 + dataLabel.height / 2; + } + else if (verticalAlign === 'top') { + y = dlBox.y - dlBox.height + dataLabel.height + + options.padding; + } + if (verticalAlign === 'top' && !reversed || + verticalAlign === 'bottom' && reversed || + verticalAlign === 'middle') { + if (align === 'right') { + x = dlBox.x - options.padding + offset; + } + else if (align === 'left') { + x = dlBox.x + options.padding - offset; + } + } + alignTo = { + x: x, + y: reversed ? y - dlBox.height : y, + width: dlBox.bottomWidth, + height: dlBox.height + }; + options.verticalAlign = 'bottom'; + // Call the parent method + if (!inside || point.visible) { + Highcharts.Series.prototype.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew); + } + if (inside) { + if (!point.visible && point.dataLabel) { + // Avoid animation from top + point.dataLabel.placed = false; + } + // If label is inside and we have contrast, set it: + if (point.contrastColor) { + dataLabel.css({ + color: point.contrastColor + }); + } + } + } + }); + /* eslint-disable no-invalid-this */ + addEvent(Chart, 'afterHideAllOverlappingLabels', function () { + this.series.forEach(function (series) { + var dataLabelsOptions = series.options && series.options.dataLabels; + if (isArray(dataLabelsOptions)) { + dataLabelsOptions = dataLabelsOptions[0]; + } + if (series.is('pie') && + series.placeDataLabels && + dataLabelsOptions && + !dataLabelsOptions.inside) { + series.placeDataLabels(); + } + }); + }); + /** + * A `funnel` series. If the [type](#series.funnel.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.funnel + * @excluding dataParser, dataURL, stack, xAxis, yAxis, dataSorting, + * boostBlending, boostThreshold + * @product highcharts + * @requires modules/funnel + * @apioption series.funnel + */ + /** + * An array of data points for the series. For the `funnel` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values + * will be interpreted as `y` options. Example: + * + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' [turboThreshold](#series.funnel.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * y: 3, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 1, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array} + * @extends series.pie.data + * @excluding sliced + * @product highcharts + * @apioption series.funnel.data + */ + /** + * Pyramid series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.pyramid + * + * @augments Highcharts.Series + */ + seriesType('pyramid', 'funnel', + /** + * A pyramid series is a special type of funnel, without neck and reversed + * by default. + * + * @sample highcharts/demo/pyramid/ + * Pyramid chart + * + * @extends plotOptions.funnel + * @product highcharts + * @requires modules/funnel + * @optionparent plotOptions.pyramid + */ + { + /** + * The pyramid neck width is zero by default, as opposed to the funnel, + * which shares the same layout logic. + * + * @since 3.0.10 + */ + neckWidth: '0%', + /** + * The pyramid neck width is zero by default, as opposed to the funnel, + * which shares the same layout logic. + * + * @since 3.0.10 + */ + neckHeight: '0%', + /** + * The pyramid is reversed by default, as opposed to the funnel, which + * shares the layout engine, and is not reversed. + * + * @since 3.0.10 + */ + reversed: true + }); + /** + * A `pyramid` series. If the [type](#series.pyramid.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.pyramid + * @excluding dataParser, dataURL, stack, xAxis, yAxis, dataSorting, + * boostThreshold, boostBlending + * @product highcharts + * @requires modules/funnel + * @apioption series.pyramid + */ + /** + * An array of data points for the series. For the `pyramid` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.pyramid.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array} + * @extends series.pie.data + * @excluding sliced + * @product highcharts + * @apioption series.pyramid.data + */ + ''; // adds doclets above into transpiled file + + }); + _registerModule(_modules, 'masters/modules/funnel.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/funnel3d.js b/highcharts/modules/funnel3d.js new file mode 100644 index 0000000..ab1f9e2 --- /dev/null +++ b/highcharts/modules/funnel3d.js @@ -0,0 +1,26 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Highcharts funnel module + + (c) 2010-2019 Kacper Madej + + License: www.highcharts.com/license +*/ +(function(d){"object"===typeof module&&module.exports?(d["default"]=d,module.exports=d):"function"===typeof define&&define.amd?define("highcharts/modules/funnel3d",["highcharts","highcharts/highcharts-3d","highcharts/modules/cylinder"],function(y){d(y);d.Highcharts=y;return d}):d("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(d){function y(d,m,k,h){d.hasOwnProperty(m)||(d[m]=h.apply(null,k))}d=d?d._modules:{};y(d,"Series/Funnel3DSeries.js",[d["Core/Globals.js"],d["Extensions/Math3D.js"], +d["Core/Color.js"],d["Core/Utilities.js"]],function(d,m,k,h){var y=m.perspective,l=k.parse,J=h.error,E=h.extend,p=h.merge,C=h.pick,B=h.relativeLength;k=h.seriesType;var H=d.charts,K=d.seriesTypes;m=d.Renderer.prototype;var L=m.cuboidPath;k("funnel3d","column",{center:["50%","50%"],width:"90%",neckWidth:"30%",height:"100%",neckHeight:"25%",reversed:!1,gradientForSides:!0,animation:!1,edgeWidth:0,colorByPoint:!0,showInLegend:!1,dataLabels:{align:"right",crop:!1,inside:!1,overflow:"allow"}},{bindAxes:function(){d.Series.prototype.bindAxes.apply(this, +arguments);E(this.xAxis.options,{gridLineWidth:0,lineWidth:0,title:null,tickPositions:[]});E(this.yAxis.options,{gridLineWidth:0,title:null,labels:{enabled:!1}})},translate3dShapes:d.noop,translate:function(){d.Series.prototype.translate.apply(this,arguments);var a=0,b=this.chart,c=this.options,g=c.reversed,u=c.ignoreHiddenPoint,e=b.plotWidth,F=b.plotHeight,f=0,I=c.center,w=B(I[0],e),t=B(I[1],F),p=B(c.width,e),q,v,n=B(c.height,F),m=B(c.neckWidth,e),h=B(c.neckHeight,F),k=t-n/2+n-h;e=this.data;var z, +l,x,A,G,D,r;this.getWidthAt=v=function(b){var a=t-n/2;return b>k||n===h?m:m+(p-m)*(1-(b-a)/(n-h))};this.center=[w,t,n];this.centerX=w;e.forEach(function(b){u&&!1===b.visible||(a+=b.y)});e.forEach(function(e){G=null;z=a?e.y/a:0;x=t-n/2+f*n;A=x+z*n;q=v(x);D=A-x;r={gradientForSides:C(e.options.gradientForSides,c.gradientForSides),x:w,y:x,height:D,width:q,z:1,top:{width:q}};q=v(A);r.bottom={fraction:z,width:q};x>=k?r.isCylinder=!0:A>k&&(G=A,q=v(k),A=k,r.bottom.width=q,r.middle={fraction:D?(k-x)/D:0,width:q}); +g&&(r.y=x=t+n/2-(f+z)*n,r.middle&&(r.middle.fraction=1-(D?r.middle.fraction:0)),q=r.width,r.width=r.bottom.width,r.bottom.width=q);e.shapeArgs=E(e.shapeArgs,r);e.percentage=100*z;e.plotX=w;e.plotY=g?t+n/2-(f+z/2)*n:(x+(G||A))/2;l=y([{x:w,y:e.plotY,z:g?-(p-v(e.plotY))/2:-v(e.plotY)/2}],b,!0)[0];e.tooltipPos=[l.x,l.y];e.dlBoxRaw={x:w,width:v(e.plotY),y:x,bottom:r.height,fullWidth:p};u&&!1===e.visible||(f+=z)})},alignDataLabel:function(a,b,c){var g=a.dlBoxRaw,u=this.chart.inverted,e=a.plotY>C(this.translatedThreshold, +this.yAxis.len),d=C(c.inside,!!this.options.stacking),f={x:g.x,y:g.y,height:0};c.align=C(c.align,!u||d?"center":e?"right":"left");c.verticalAlign=C(c.verticalAlign,u||d?"middle":e?"top":"bottom");"top"!==c.verticalAlign&&(f.y+=g.bottom/("bottom"===c.verticalAlign?1:2));f.width=this.getWidthAt(f.y);this.options.reversed&&(f.width=g.fullWidth-f.width);d?f.x-=f.width/2:"left"===c.align?(c.align="right",f.x-=1.5*f.width):"right"===c.align?(c.align="left",f.x+=f.width/2):f.x-=f.width/2;a.dlBox=f;K.column.prototype.alignDataLabel.apply(this, +arguments)}},{shapeType:"funnel3d",hasNewShapeType:d.seriesTypes.column.prototype.pointClass.prototype.hasNewShapeType});k=p(m.elements3d.cuboid,{parts:"top bottom frontUpper backUpper frontLower backLower rightUpper rightLower".split(" "),mainParts:["top","bottom"],sideGroups:["upperGroup","lowerGroup"],sideParts:{upperGroup:["frontUpper","backUpper","rightUpper"],lowerGroup:["frontLower","backLower","rightLower"]},pathType:"funnel3d",opacitySetter:function(a){var b=this,c=b.parts,g=d.charts[b.renderer.chartIndex], +u="group-opacity-"+a+"-"+g.index;b.parts=b.mainParts;b.singleSetterForParts("opacity",a);b.parts=c;g.renderer.filterId||(g.renderer.definition({tagName:"filter",id:u,children:[{tagName:"feComponentTransfer",children:[{tagName:"feFuncA",type:"table",tableValues:"0 "+a}]}]}),b.sideGroups.forEach(function(a){b[a].attr({filter:"url(#"+u+")"})}),b.renderer.styledMode&&(g.renderer.definition({tagName:"style",textContent:".highcharts-"+u+" {filter:url(#"+u+")}"}),b.sideGroups.forEach(function(b){b.addClass("highcharts-"+ +u)})));return b},fillSetter:function(a){var b=this,c=l(a),g=c.rgba[3],d={top:l(a).brighten(.1).get(),bottom:l(a).brighten(-.2).get()};1>g?(c.rgba[3]=1,c=c.get("rgb"),b.attr({opacity:g})):c=a;c.linearGradient||c.radialGradient||!b.gradientForSides||(c={linearGradient:{x1:0,x2:1,y1:1,y2:1},stops:[[0,l(a).brighten(-.2).get()],[.5,a],[1,l(a).brighten(-.2).get()]]});c.linearGradient?b.sideGroups.forEach(function(a){var e=b[a].gradientBox,f=c.linearGradient,g=p(c,{linearGradient:{x1:e.x+f.x1*e.width,y1:e.y+ +f.y1*e.height,x2:e.x+f.x2*e.width,y2:e.y+f.y2*e.height}});b.sideParts[a].forEach(function(b){d[b]=g})}):(p(!0,d,{frontUpper:c,backUpper:c,rightUpper:c,frontLower:c,backLower:c,rightLower:c}),c.radialGradient&&b.sideGroups.forEach(function(a){var c=b[a].gradientBox,e=c.x+c.width/2,g=c.y+c.height/2,d=Math.min(c.width,c.height);b.sideParts[a].forEach(function(a){b[a].setRadialReference([e,g,d])})}));b.singleSetterForParts("fill",null,d);b.color=b.fill=a;c.linearGradient&&[b.frontLower,b.frontUpper].forEach(function(a){(a= +(a=a.element)&&b.renderer.gradients[a.gradient])&&"userSpaceOnUse"!==a.attr("gradientUnits")&&a.attr({gradientUnits:"userSpaceOnUse"})});return b},adjustForGradient:function(){var a=this,b;a.sideGroups.forEach(function(c){var g={x:Number.MAX_VALUE,y:Number.MAX_VALUE},d={x:-Number.MAX_VALUE,y:-Number.MAX_VALUE};a.sideParts[c].forEach(function(c){b=a[c].getBBox(!0);g={x:Math.min(g.x,b.x),y:Math.min(g.y,b.y)};d={x:Math.max(d.x,b.x+b.width),y:Math.max(d.y,b.y+b.height)}});a[c].gradientBox={x:g.x,width:d.x- +g.x,y:g.y,height:d.y-g.y}})},zIndexSetter:function(){this.finishedOnAdd&&this.adjustForGradient();return this.renderer.Element.prototype.zIndexSetter.apply(this,arguments)},onAdd:function(){this.adjustForGradient();this.finishedOnAdd=!0}});m.elements3d.funnel3d=k;m.funnel3d=function(a){var b=this.element3d("funnel3d",a),c=this.styledMode,d={"stroke-width":1,stroke:"none"};b.upperGroup=this.g("funnel3d-upper-group").attr({zIndex:b.frontUpper.zIndex}).add(b);[b.frontUpper,b.backUpper,b.rightUpper].forEach(function(a){c|| +a.attr(d);a.add(b.upperGroup)});b.lowerGroup=this.g("funnel3d-lower-group").attr({zIndex:b.frontLower.zIndex}).add(b);[b.frontLower,b.backLower,b.rightLower].forEach(function(a){c||a.attr(d);a.add(b.lowerGroup)});b.gradientForSides=a.gradientForSides;return b};m.funnel3dPath=function(a){this.getCylinderEnd||J("A required Highcharts module is missing: cylinder.js",!0,H[this.chartIndex]);var b=H[this.chartIndex],c=a.alphaCorrection=90-Math.abs(b.options.chart.options3d.alpha%180-90),d=L.call(this,p(a, +{depth:a.width,width:(a.width+a.bottom.width)/2})),m=d.isTop,e=!d.isFront,k=!!a.middle,f=this.getCylinderEnd(b,p(a,{x:a.x-a.width/2,z:a.z-a.width/2,alphaCorrection:c})),h=a.bottom.width,w=p(a,{width:h,x:a.x-h/2,z:a.z-h/2,alphaCorrection:c}),t=this.getCylinderEnd(b,w,!0),l=h,q=w,v=t,n=t;k&&(l=a.middle.width,q=p(a,{y:a.y+a.middle.fraction*a.height,width:l,x:a.x-l/2,z:a.z-l/2}),v=this.getCylinderEnd(b,q,!1),n=this.getCylinderEnd(b,q,!1));d={top:f,bottom:t,frontUpper:this.getCylinderFront(f,v),zIndexes:{group:d.zIndexes.group, +top:0!==m?0:3,bottom:1!==m?0:3,frontUpper:e?2:1,backUpper:e?1:2,rightUpper:e?2:1}};d.backUpper=this.getCylinderBack(f,v);f=1!==Math.min(l,a.width)/Math.max(l,a.width);d.rightUpper=this.getCylinderFront(this.getCylinderEnd(b,p(a,{x:a.x-a.width/2,z:a.z-a.width/2,alphaCorrection:f?-c:0}),!1),this.getCylinderEnd(b,p(q,{alphaCorrection:f?-c:0}),!k));k&&(f=1!==Math.min(l,h)/Math.max(l,h),p(!0,d,{frontLower:this.getCylinderFront(n,t),backLower:this.getCylinderBack(n,t),rightLower:this.getCylinderFront(this.getCylinderEnd(b, +p(w,{alphaCorrection:f?-c:0}),!0),this.getCylinderEnd(b,p(q,{alphaCorrection:f?-c:0}),!1)),zIndexes:{frontLower:e?2:1,backLower:e?1:2,rightLower:e?1:2}}));return d}});y(d,"masters/modules/funnel3d.src.js",[],function(){})}); +//# sourceMappingURL=funnel3d.js.map \ No newline at end of file diff --git a/highcharts/modules/funnel3d.js.map b/highcharts/modules/funnel3d.js.map new file mode 100644 index 0000000..44098f8 --- /dev/null +++ b/highcharts/modules/funnel3d.js.map @@ -0,0 +1 @@ +{"version":3,"file":"funnel3d.js.map","lineCount":25,"mappings":"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","sources":["funnel3d.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","Math3D","Color","U","perspective","color","parse","error","extend","merge","pick","relativeLength","seriesType","charts","seriesTypes","RendererProto","Renderer","prototype","cuboidPath","center","width","neckWidth","height","neckHeight","reversed","gradientForSides","animation","edgeWidth","colorByPoint","showInLegend","dataLabels","align","crop","inside","overflow","bindAxes","Series","arguments","xAxis","options","gridLineWidth","lineWidth","title","tickPositions","yAxis","labels","enabled","translate3dShapes","noop","translate","sum","chart","series","ignoreHiddenPoint","plotWidth","plotHeight","cumulative","centerX","centerY","tempWidth","getWidthAt","neckY","data","fraction","tooltipPos","y1","y3","y5","h","shapeArgs","y","top","forEach","point","visible","x","z","bottom","isCylinder","middle","percentage","plotX","plotY","dlBoxRaw","fullWidth","alignDataLabel","dataLabel","inverted","below","translatedThreshold","len","stacking","dlBox","verticalAlign","column","shapeType","hasNewShapeType","pointClass","funnel3dMethods","elements3d","cuboid","parts","mainParts","sideGroups","sideParts","upperGroup","lowerGroup","pathType","opacitySetter","opacity","funnel3d","renderer","chartIndex","filterId","index","singleSetterForParts","definition","tagName","id","children","type","tableValues","groupName","attr","filter","styledMode","textContent","group","addClass","fillSetter","fill","fillColor","alpha","rgba","partsWithColor","brighten","get","linearGradient","radialGradient","x1","x2","y2","stops","sideGroupName","box","gradientBox","gradient","alteredGradient","partName","frontUpper","backUpper","rightUpper","frontLower","backLower","rightLower","gradBox","diameter","Math","min","setRadialReference","part","grad","elem","element","gradients","gradientUnits","adjustForGradient","bbox","topLeftEdge","Number","MAX_VALUE","bottomRightEdge","getBBox","max","zIndexSetter","finishedOnAdd","Element","onAdd","RendererProto.funnel3d","element3d","strokeAttrs","stroke","g","zIndex","add","upperElem","lowerElem","funnel3dPath","RendererProto.funnel3dPath","getCylinderEnd","alphaCorrection","abs","options3d","cuboidData","call","depth","isTopFirst","isTop","isFrontFirst","isFront","hasMiddle","bottomWidth","bottomArgs","middleWidth","middleTopArgs","middleTop","middleBottom","ret","getCylinderFront","zIndexes","getCylinderBack","useAlphaCorrection"]} \ No newline at end of file diff --git a/highcharts/modules/funnel3d.src.js b/highcharts/modules/funnel3d.src.js new file mode 100644 index 0000000..22dd4b4 --- /dev/null +++ b/highcharts/modules/funnel3d.src.js @@ -0,0 +1,809 @@ +/** + * @license Highcharts JS v8.2.0 (2020-08-20) + * + * Highcharts funnel module + * + * (c) 2010-2019 Kacper Madej + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/funnel3d', ['highcharts', 'highcharts/highcharts-3d', 'highcharts/modules/cylinder'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'Series/Funnel3DSeries.js', [_modules['Core/Globals.js'], _modules['Extensions/Math3D.js'], _modules['Core/Color.js'], _modules['Core/Utilities.js']], function (H, Math3D, Color, U) { + /* * + * + * Highcharts funnel3d series module + * + * (c) 2010-2020 Highsoft AS + * + * Author: Kacper Madej + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var perspective = Math3D.perspective; + var color = Color.parse; + var error = U.error, + extend = U.extend, + merge = U.merge, + pick = U.pick, + relativeLength = U.relativeLength, + seriesType = U.seriesType; + var charts = H.charts, + seriesTypes = H.seriesTypes, + // Use H.Renderer instead of SVGRenderer for VML support. + RendererProto = H.Renderer.prototype, + // + cuboidPath = RendererProto.cuboidPath, + funnel3dMethods; + /** + * The funnel3d series type. + * + * @constructor seriesTypes.funnel3d + * @augments seriesTypes.column + * @requires highcharts-3d + * @requires modules/cylinder + * @requires modules/funnel3d + */ + seriesType('funnel3d', 'column', + /** + * A funnel3d is a 3d version of funnel series type. Funnel charts are + * a type of chart often used to visualize stages in a sales project, + * where the top are the initial stages with the most clients. + * + * It requires that the `highcharts-3d.js`, `cylinder.js` and + * `funnel3d.js` module are loaded. + * + * @sample highcharts/demo/funnel3d/ + * Funnel3d + * + * @extends plotOptions.column + * @excluding allAreas, boostThreshold, colorAxis, compare, compareBase, + * dataSorting, boostBlending + * @product highcharts + * @since 7.1.0 + * @requires highcharts-3d + * @requires modules/cylinder + * @requires modules/funnel3d + * @optionparent plotOptions.funnel3d + */ + { + /** @ignore-option */ + center: ['50%', '50%'], + /** + * The max width of the series compared to the width of the plot area, + * or the pixel width if it is a number. + * + * @type {number|string} + * @sample {highcharts} highcharts/demo/funnel3d/ Funnel3d demo + * @product highcharts + */ + width: '90%', + /** + * The width of the neck, the lower part of the funnel. A number defines + * pixel width, a percentage string defines a percentage of the plot + * area width. + * + * @type {number|string} + * @sample {highcharts} highcharts/demo/funnel3d/ Funnel3d demo + * @product highcharts + */ + neckWidth: '30%', + /** + * The height of the series. If it is a number it defines + * the pixel height, if it is a percentage string it is the percentage + * of the plot area height. + * + * @type {number|string} + * @sample {highcharts} highcharts/demo/funnel3d/ Funnel3d demo + * @product highcharts + */ + height: '100%', + /** + * The height of the neck, the lower part of the funnel. A number + * defines pixel width, a percentage string defines a percentage + * of the plot area height. + * + * @type {number|string} + * @sample {highcharts} highcharts/demo/funnel3d/ Funnel3d demo + * @product highcharts + */ + neckHeight: '25%', + /** + * A reversed funnel has the widest area down. A reversed funnel with + * no neck width and neck height is a pyramid. + * + * @product highcharts + */ + reversed: false, + /** + * By deafult sides fill is set to a gradient through this option being + * set to `true`. Set to `false` to get solid color for the sides. + * + * @product highcharts + */ + gradientForSides: true, + animation: false, + edgeWidth: 0, + colorByPoint: true, + showInLegend: false, + dataLabels: { + align: 'right', + crop: false, + inside: false, + overflow: 'allow' + } + }, { + // Override default axis options with series required options for axes + bindAxes: function () { + H.Series.prototype.bindAxes.apply(this, arguments); + extend(this.xAxis.options, { + gridLineWidth: 0, + lineWidth: 0, + title: null, + tickPositions: [] + }); + extend(this.yAxis.options, { + gridLineWidth: 0, + title: null, + labels: { + enabled: false + } + }); + }, + translate3dShapes: H.noop, + translate: function () { + H.Series.prototype.translate.apply(this, arguments); + var sum = 0, + series = this, + chart = series.chart, + options = series.options, + reversed = options.reversed, + ignoreHiddenPoint = options.ignoreHiddenPoint, + plotWidth = chart.plotWidth, + plotHeight = chart.plotHeight, + cumulative = 0, // start at top + center = options.center, + centerX = relativeLength(center[0], + plotWidth), + centerY = relativeLength(center[1], + plotHeight), + width = relativeLength(options.width, + plotWidth), + tempWidth, + getWidthAt, + height = relativeLength(options.height, + plotHeight), + neckWidth = relativeLength(options.neckWidth, + plotWidth), + neckHeight = relativeLength(options.neckHeight, + plotHeight), + neckY = (centerY - height / 2) + height - neckHeight, + data = series.data, + fraction, + tooltipPos, + // + y1, + y3, + y5, + // + h, + shapeArgs; + // Return the width at a specific y coordinate + series.getWidthAt = getWidthAt = function (y) { + var top = (centerY - height / 2); + return (y > neckY || height === neckHeight) ? + neckWidth : + neckWidth + (width - neckWidth) * + (1 - (y - top) / (height - neckHeight)); + }; + // Expose + series.center = [centerX, centerY, height]; + series.centerX = centerX; + /* + * Individual point coordinate naming: + * + * _________centerX,y1________ + * \ / + * \ / + * \ / + * \ / + * \ / + * ___centerX,y3___ + * + * Additional for the base of the neck: + * + * | | + * | | + * | | + * ___centerX,y5___ + */ + // get the total sum + data.forEach(function (point) { + if (!ignoreHiddenPoint || point.visible !== false) { + sum += point.y; + } + }); + data.forEach(function (point) { + // set start and end positions + y5 = null; + fraction = sum ? point.y / sum : 0; + y1 = centerY - height / 2 + cumulative * height; + y3 = y1 + fraction * height; + tempWidth = getWidthAt(y1); + h = y3 - y1; + shapeArgs = { + // for fill setter + gradientForSides: pick(point.options.gradientForSides, options.gradientForSides), + x: centerX, + y: y1, + height: h, + width: tempWidth, + z: 1, + top: { + width: tempWidth + } + }; + tempWidth = getWidthAt(y3); + shapeArgs.bottom = { + fraction: fraction, + width: tempWidth + }; + // the entire point is within the neck + if (y1 >= neckY) { + shapeArgs.isCylinder = true; + } + else if (y3 > neckY) { + // the base of the neck + y5 = y3; + tempWidth = getWidthAt(neckY); + y3 = neckY; + shapeArgs.bottom.width = tempWidth; + shapeArgs.middle = { + fraction: h ? (neckY - y1) / h : 0, + width: tempWidth + }; + } + if (reversed) { + shapeArgs.y = y1 = centerY + height / 2 - + (cumulative + fraction) * height; + if (shapeArgs.middle) { + shapeArgs.middle.fraction = 1 - + (h ? shapeArgs.middle.fraction : 0); + } + tempWidth = shapeArgs.width; + shapeArgs.width = shapeArgs.bottom.width; + shapeArgs.bottom.width = tempWidth; + } + point.shapeArgs = extend(point.shapeArgs, shapeArgs); + // for tooltips and data labels context + point.percentage = fraction * 100; + point.plotX = centerX; + if (reversed) { + point.plotY = centerY + height / 2 - + (cumulative + fraction / 2) * height; + } + else { + point.plotY = (y1 + (y5 || y3)) / 2; + } + // Placement of tooltips and data labels in 3D + tooltipPos = perspective([{ + x: centerX, + y: point.plotY, + z: reversed ? + -(width - getWidthAt(point.plotY)) / 2 : + -(getWidthAt(point.plotY)) / 2 + }], chart, true)[0]; + point.tooltipPos = [tooltipPos.x, tooltipPos.y]; + // base to be used when alignment options are known + point.dlBoxRaw = { + x: centerX, + width: getWidthAt(point.plotY), + y: y1, + bottom: shapeArgs.height, + fullWidth: width + }; + if (!ignoreHiddenPoint || point.visible !== false) { + cumulative += fraction; + } + }); + }, + alignDataLabel: function (point, dataLabel, options) { + var series = this, + dlBoxRaw = point.dlBoxRaw, + inverted = series.chart.inverted, + below = point.plotY > pick(series.translatedThreshold, + series.yAxis.len), + inside = pick(options.inside, !!series.options.stacking), + dlBox = { + x: dlBoxRaw.x, + y: dlBoxRaw.y, + height: 0 + }; + options.align = pick(options.align, !inverted || inside ? 'center' : below ? 'right' : 'left'); + options.verticalAlign = pick(options.verticalAlign, inverted || inside ? 'middle' : below ? 'top' : 'bottom'); + if (options.verticalAlign !== 'top') { + dlBox.y += dlBoxRaw.bottom / + (options.verticalAlign === 'bottom' ? 1 : 2); + } + dlBox.width = series.getWidthAt(dlBox.y); + if (series.options.reversed) { + dlBox.width = dlBoxRaw.fullWidth - dlBox.width; + } + if (inside) { + dlBox.x -= dlBox.width / 2; + } + else { + // swap for inside + if (options.align === 'left') { + options.align = 'right'; + dlBox.x -= dlBox.width * 1.5; + } + else if (options.align === 'right') { + options.align = 'left'; + dlBox.x += dlBox.width / 2; + } + else { + dlBox.x -= dlBox.width / 2; + } + } + point.dlBox = dlBox; + seriesTypes.column.prototype.alignDataLabel.apply(series, arguments); + } + }, /** @lends seriesTypes.funnel3d.prototype.pointClass.prototype */ { + shapeType: 'funnel3d', + hasNewShapeType: H + .seriesTypes.column.prototype + .pointClass.prototype + .hasNewShapeType + }); + /** + * A `funnel3d` series. If the [type](#series.funnel3d.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @sample {highcharts} highcharts/demo/funnel3d/ + * Funnel3d demo + * + * @since 7.1.0 + * @extends series.funnel,plotOptions.funnel3d + * @excluding allAreas,boostThreshold,colorAxis,compare,compareBase + * @product highcharts + * @requires highcharts-3d + * @requires modules/cylinder + * @requires modules/funnel3d + * @apioption series.funnel3d + */ + /** + * An array of data points for the series. For the `funnel3d` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values + * will be interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from `pointStart` + * and `pointInterval` given in the series options. If the axis has + * categories, these will be used. Example: + * + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' [turboThreshold](#series.funnel3d.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * y: 2, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 4, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|*>} + * @extends series.column.data + * @product highcharts + * @apioption series.funnel3d.data + */ + /** + * By deafult sides fill is set to a gradient through this option being + * set to `true`. Set to `false` to get solid color for the sides. + * + * @type {boolean} + * @product highcharts + * @apioption series.funnel3d.data.gradientForSides + */ + funnel3dMethods = merge(RendererProto.elements3d.cuboid, { + parts: [ + 'top', 'bottom', + 'frontUpper', 'backUpper', + 'frontLower', 'backLower', + 'rightUpper', 'rightLower' + ], + mainParts: ['top', 'bottom'], + sideGroups: [ + 'upperGroup', 'lowerGroup' + ], + sideParts: { + upperGroup: ['frontUpper', 'backUpper', 'rightUpper'], + lowerGroup: ['frontLower', 'backLower', 'rightLower'] + }, + pathType: 'funnel3d', + // override opacity and color setters to control opacity + opacitySetter: function (opacity) { + var funnel3d = this, + parts = funnel3d.parts, + chart = H.charts[funnel3d.renderer.chartIndex], + filterId = 'group-opacity-' + opacity + '-' + chart.index; + // use default for top and bottom + funnel3d.parts = funnel3d.mainParts; + funnel3d.singleSetterForParts('opacity', opacity); + // restore + funnel3d.parts = parts; + if (!chart.renderer.filterId) { + chart.renderer.definition({ + tagName: 'filter', + id: filterId, + children: [{ + tagName: 'feComponentTransfer', + children: [{ + tagName: 'feFuncA', + type: 'table', + tableValues: '0 ' + opacity + }] + }] + }); + funnel3d.sideGroups.forEach(function (groupName) { + funnel3d[groupName].attr({ + filter: 'url(#' + filterId + ')' + }); + }); + // styled mode + if (funnel3d.renderer.styledMode) { + chart.renderer.definition({ + tagName: 'style', + textContent: '.highcharts-' + filterId + + ' {filter:url(#' + filterId + ')}' + }); + funnel3d.sideGroups.forEach(function (group) { + group.addClass('highcharts-' + filterId); + }); + } + } + return funnel3d; + }, + fillSetter: function (fill) { + // extract alpha channel to use the opacitySetter + var funnel3d = this, + fillColor = color(fill), + alpha = fillColor.rgba[3], + partsWithColor = { + // standard color for top and bottom + top: color(fill).brighten(0.1).get(), + bottom: color(fill).brighten(-0.2).get() + }; + if (alpha < 1) { + fillColor.rgba[3] = 1; + fillColor = fillColor.get('rgb'); + // set opacity through the opacitySetter + funnel3d.attr({ + opacity: alpha + }); + } + else { + // use default for full opacity + fillColor = fill; + } + // add gradient for sides + if (!fillColor.linearGradient && + !fillColor.radialGradient && + funnel3d.gradientForSides) { + fillColor = { + linearGradient: { x1: 0, x2: 1, y1: 1, y2: 1 }, + stops: [ + [0, color(fill).brighten(-0.2).get()], + [0.5, fill], + [1, color(fill).brighten(-0.2).get()] + ] + }; + } + // gradient support + if (fillColor.linearGradient) { + // color in steps, as each gradient will generate a key + funnel3d.sideGroups.forEach(function (sideGroupName) { + var box = funnel3d[sideGroupName].gradientBox, + gradient = fillColor.linearGradient, + alteredGradient = merge(fillColor, { + linearGradient: { + x1: box.x + gradient.x1 * box.width, + y1: box.y + gradient.y1 * box.height, + x2: box.x + gradient.x2 * box.width, + y2: box.y + gradient.y2 * box.height + } + }); + funnel3d.sideParts[sideGroupName].forEach(function (partName) { + partsWithColor[partName] = alteredGradient; + }); + }); + } + else { + merge(true, partsWithColor, { + frontUpper: fillColor, + backUpper: fillColor, + rightUpper: fillColor, + frontLower: fillColor, + backLower: fillColor, + rightLower: fillColor + }); + if (fillColor.radialGradient) { + funnel3d.sideGroups.forEach(function (sideGroupName) { + var gradBox = funnel3d[sideGroupName].gradientBox, + centerX = gradBox.x + gradBox.width / 2, + centerY = gradBox.y + gradBox.height / 2, + diameter = Math.min(gradBox.width, + gradBox.height); + funnel3d.sideParts[sideGroupName].forEach(function (partName) { + funnel3d[partName].setRadialReference([ + centerX, centerY, diameter + ]); + }); + }); + } + } + funnel3d.singleSetterForParts('fill', null, partsWithColor); + // fill for animation getter (#6776) + funnel3d.color = funnel3d.fill = fill; + // change gradientUnits to userSpaceOnUse for linearGradient + if (fillColor.linearGradient) { + [funnel3d.frontLower, funnel3d.frontUpper].forEach(function (part) { + var elem = part.element, + grad = elem && funnel3d.renderer.gradients[elem.gradient]; + if (grad && grad.attr('gradientUnits') !== 'userSpaceOnUse') { + grad.attr({ + gradientUnits: 'userSpaceOnUse' + }); + } + }); + } + return funnel3d; + }, + adjustForGradient: function () { + var funnel3d = this, + bbox; + funnel3d.sideGroups.forEach(function (sideGroupName) { + // use common extremes for groups for matching gradients + var topLeftEdge = { + x: Number.MAX_VALUE, + y: Number.MAX_VALUE + }, + bottomRightEdge = { + x: -Number.MAX_VALUE, + y: -Number.MAX_VALUE + }; + // get extremes + funnel3d.sideParts[sideGroupName].forEach(function (partName) { + var part = funnel3d[partName]; + bbox = part.getBBox(true); + topLeftEdge = { + x: Math.min(topLeftEdge.x, bbox.x), + y: Math.min(topLeftEdge.y, bbox.y) + }; + bottomRightEdge = { + x: Math.max(bottomRightEdge.x, bbox.x + bbox.width), + y: Math.max(bottomRightEdge.y, bbox.y + bbox.height) + }; + }); + // store for color fillSetter + funnel3d[sideGroupName].gradientBox = { + x: topLeftEdge.x, + width: bottomRightEdge.x - topLeftEdge.x, + y: topLeftEdge.y, + height: bottomRightEdge.y - topLeftEdge.y + }; + }); + }, + zIndexSetter: function () { + // this.added won't work, because zIndex is set after the prop is set, + // but before the graphic is really added + if (this.finishedOnAdd) { + this.adjustForGradient(); + } + // run default + return this.renderer.Element.prototype.zIndexSetter.apply(this, arguments); + }, + onAdd: function () { + this.adjustForGradient(); + this.finishedOnAdd = true; + } + }); + RendererProto.elements3d.funnel3d = funnel3dMethods; + RendererProto.funnel3d = function (shapeArgs) { + var renderer = this, + funnel3d = renderer.element3d('funnel3d', + shapeArgs), + styledMode = renderer.styledMode, + // hide stroke for Firefox + strokeAttrs = { + 'stroke-width': 1, + stroke: 'none' + }; + // create groups for sides for oppacity setter + funnel3d.upperGroup = renderer.g('funnel3d-upper-group').attr({ + zIndex: funnel3d.frontUpper.zIndex + }).add(funnel3d); + [ + funnel3d.frontUpper, + funnel3d.backUpper, + funnel3d.rightUpper + ].forEach(function (upperElem) { + if (!styledMode) { + upperElem.attr(strokeAttrs); + } + upperElem.add(funnel3d.upperGroup); + }); + funnel3d.lowerGroup = renderer.g('funnel3d-lower-group').attr({ + zIndex: funnel3d.frontLower.zIndex + }).add(funnel3d); + [ + funnel3d.frontLower, + funnel3d.backLower, + funnel3d.rightLower + ].forEach(function (lowerElem) { + if (!styledMode) { + lowerElem.attr(strokeAttrs); + } + lowerElem.add(funnel3d.lowerGroup); + }); + funnel3d.gradientForSides = shapeArgs.gradientForSides; + return funnel3d; + }; + // eslint-disable-next-line valid-jsdoc + /** + * Generates paths and zIndexes. + * @private + */ + RendererProto.funnel3dPath = function (shapeArgs) { + // Check getCylinderEnd for better error message if + // the cylinder module is missing + if (!this.getCylinderEnd) { + error('A required Highcharts module is missing: cylinder.js', true, charts[this.chartIndex]); + } + var renderer = this, + chart = charts[renderer.chartIndex], + // adjust angles for visible edges + // based on alpha, selected through visual tests + alphaCorrection = shapeArgs.alphaCorrection = 90 - + Math.abs((chart.options.chart.options3d.alpha % 180) - 90), + // set zIndexes of parts based on cubiod logic, for consistency + cuboidData = cuboidPath.call(renderer, + merge(shapeArgs, { + depth: shapeArgs.width, + width: (shapeArgs.width + shapeArgs.bottom.width) / 2 + })), + isTopFirst = cuboidData.isTop, + isFrontFirst = !cuboidData.isFront, + hasMiddle = !!shapeArgs.middle, + // + top = renderer.getCylinderEnd(chart, + merge(shapeArgs, { + x: shapeArgs.x - shapeArgs.width / 2, + z: shapeArgs.z - shapeArgs.width / 2, + alphaCorrection: alphaCorrection + })), + bottomWidth = shapeArgs.bottom.width, + bottomArgs = merge(shapeArgs, { + width: bottomWidth, + x: shapeArgs.x - bottomWidth / 2, + z: shapeArgs.z - bottomWidth / 2, + alphaCorrection: alphaCorrection + }), + bottom = renderer.getCylinderEnd(chart, + bottomArgs, + true), + // + middleWidth = bottomWidth, + middleTopArgs = bottomArgs, + middleTop = bottom, + middleBottom = bottom, + ret, + // masking for cylinders or a missing part of a side shape + useAlphaCorrection; + if (hasMiddle) { + middleWidth = shapeArgs.middle.width; + middleTopArgs = merge(shapeArgs, { + y: shapeArgs.y + shapeArgs.middle.fraction * shapeArgs.height, + width: middleWidth, + x: shapeArgs.x - middleWidth / 2, + z: shapeArgs.z - middleWidth / 2 + }); + middleTop = renderer.getCylinderEnd(chart, middleTopArgs, false); + middleBottom = renderer.getCylinderEnd(chart, middleTopArgs, false); + } + ret = { + top: top, + bottom: bottom, + frontUpper: renderer.getCylinderFront(top, middleTop), + zIndexes: { + group: cuboidData.zIndexes.group, + top: isTopFirst !== 0 ? 0 : 3, + bottom: isTopFirst !== 1 ? 0 : 3, + frontUpper: isFrontFirst ? 2 : 1, + backUpper: isFrontFirst ? 1 : 2, + rightUpper: isFrontFirst ? 2 : 1 + } + }; + ret.backUpper = renderer.getCylinderBack(top, middleTop); + useAlphaCorrection = (Math.min(middleWidth, shapeArgs.width) / + Math.max(middleWidth, shapeArgs.width)) !== 1; + ret.rightUpper = renderer.getCylinderFront(renderer.getCylinderEnd(chart, merge(shapeArgs, { + x: shapeArgs.x - shapeArgs.width / 2, + z: shapeArgs.z - shapeArgs.width / 2, + alphaCorrection: useAlphaCorrection ? -alphaCorrection : 0 + }), false), renderer.getCylinderEnd(chart, merge(middleTopArgs, { + alphaCorrection: useAlphaCorrection ? -alphaCorrection : 0 + }), !hasMiddle)); + if (hasMiddle) { + useAlphaCorrection = (Math.min(middleWidth, bottomWidth) / + Math.max(middleWidth, bottomWidth)) !== 1; + merge(true, ret, { + frontLower: renderer.getCylinderFront(middleBottom, bottom), + backLower: renderer.getCylinderBack(middleBottom, bottom), + rightLower: renderer.getCylinderFront(renderer.getCylinderEnd(chart, merge(bottomArgs, { + alphaCorrection: useAlphaCorrection ? + -alphaCorrection : 0 + }), true), renderer.getCylinderEnd(chart, merge(middleTopArgs, { + alphaCorrection: useAlphaCorrection ? + -alphaCorrection : 0 + }), false)), + zIndexes: { + frontLower: isFrontFirst ? 2 : 1, + backLower: isFrontFirst ? 1 : 2, + rightLower: isFrontFirst ? 1 : 2 + } + }); + } + return ret; + }; + + }); + _registerModule(_modules, 'masters/modules/funnel3d.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/gantt.js b/highcharts/modules/gantt.js new file mode 100644 index 0000000..18a149c --- /dev/null +++ b/highcharts/modules/gantt.js @@ -0,0 +1,198 @@ +/* + Highcharts Gantt JS v8.2.0 (2020-08-20) + + Gantt series + + (c) 2016-2019 Lars A. V. Cabrera + + License: www.highcharts.com/license +*/ +(function(e){"object"===typeof module&&module.exports?(e["default"]=e,module.exports=e):"function"===typeof define&&define.amd?define("highcharts/modules/gantt",["highcharts"],function(J){e(J);e.Highcharts=J;return e}):e("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(e){function J(e,n,v,x){e.hasOwnProperty(n)||(e[n]=x.apply(null,v))}e=e?e._modules:{};J(e,"Gantt/Tree.js",[e["Core/Utilities.js"]],function(e){var n=e.extend,v=e.isNumber,x=e.pick,w=function(n,u){var l=n.reduce(function(b, +m){var q=x(m.parent,"");"undefined"===typeof b[q]&&(b[q]=[]);b[q].push(m);return b},{});Object.keys(l).forEach(function(b,m){var q=l[b];""!==b&&-1===u.indexOf(b)&&(q.forEach(function(b){m[""].push(b)}),delete m[b])});return l},y=function(e,u,l,b,m,q){var z=0,F=0,G=q&&q.after,k=q&&q.before;u={data:b,depth:l-1,id:e,level:l,parent:u};var f,a;"function"===typeof k&&k(u,q);k=(m[e]||[]).map(function(h){var d=y(h.id,e,l+1,h,m,q),r=h.start;h=!0===h.milestone?r:h.end;f=!v(f)||ra?h:a;z=z+ +1+d.descendants;F=Math.max(d.height+1,F);return d});b&&(b.start=x(b.start,f),b.end=x(b.end,a));n(u,{children:k,descendants:z,height:F});"function"===typeof G&&G(u,q);return u};return{getListOfParents:w,getNode:y,getTree:function(e,u){var l=e.map(function(b){return b.id});e=w(e,l);return y("",null,1,null,e,u)}}});J(e,"Core/Axis/TreeGridTick.js",[e["Core/Utilities.js"]],function(e){var n=e.addEvent,v=e.defined,x=e.isObject,w=e.isNumber,y=e.pick,C=e.wrap,u;(function(l){function b(){this.treeGrid||(this.treeGrid= +new G(this))}function m(k,f){k=k.treeGrid;var a=!k.labelIcon,h=f.renderer,d=f.xy,r=f.options,c=r.width,A=r.height,t=d.x-c/2-r.padding;d=d.y-A/2;var I=f.collapsed?90:180,D=f.show&&w(d),B=k.labelIcon;B||(k.labelIcon=B=h.path(h.symbols[r.type](r.x,r.y,c,A)).addClass("highcharts-label-icon").add(f.group));D||B.attr({y:-9999});h.styledMode||B.attr({"stroke-width":1,fill:y(f.color,"#666666")}).css({cursor:"pointer",stroke:r.lineColor,strokeWidth:r.lineWidth});B[a?"attr":"animate"]({translateX:t,translateY:d, +rotation:I})}function q(k,f,a,h,d,r,c,A,t){var I=y(this.options&&this.options.labels,r);r=this.pos;var D=this.axis,B="treegrid"===D.options.type;k=k.apply(this,[f,a,h,d,I,c,A,t]);B&&(f=I&&x(I.symbol,!0)?I.symbol:{},I=I&&w(I.indentation)?I.indentation:0,r=(r=(D=D.treeGrid.mapOfPosToGridNode)&&D[r])&&r.depth||1,k.x+=f.width+2*f.padding+(r-1)*I);return k}function z(k){var f=this,a=f.pos,h=f.axis,d=f.label,r=h.treeGrid.mapOfPosToGridNode,c=h.options,A=y(f.options&&f.options.labels,c&&c.labels),t=A&&x(A.symbol, +!0)?A.symbol:{},I=(r=r&&r[a])&&r.depth;c="treegrid"===c.type;var D=-1k&&!a.startOnTick&&(d[0]=k),f> +b&&f-E=f?(m-f)%k:k-(f-m)%k;return b.inclusive?m<=a:m=b)break;else f.to=b)break;else if(m.isInBreak(a,b)){k-=b-a.from;break}}return k};m.prototype.findBreakAt=function(b,m){return y(m,function(k){return k.fromt;)g-=A;for(;ga.to||c>a.from&&ta.from&&ta.from&&t>a.to&&tf&&a>=this.basePointRange&&(f=a),c=void 0;d--;)c&&!1!==c.visible||(c=h[d+1]),a=h[d],!1!==c.visible&& +!1!==a.visible&&(c.x-a.x>f&&(c=(a.x+c.x)/2,h.splice(d+1,0,{isNull:!0,x:c}),r.stacking&&this.options.stacking&&(c=r.stacking.stacks[this.stackKey][c]=new x(r,r.options.stackLabels,!1,c,this.stack),c.total=0)),c=a);return this.getGraphPath(h)};w(z,"init",function(){this.brokenAxis||(this.brokenAxis=new q(this))});w(z,"afterInit",function(){"undefined"!==typeof this.brokenAxis&&this.brokenAxis.setBreaks(this.options.breaks,!1)});w(z,"afterSetTickPositions",function(){var f=this.brokenAxis;if(f&&f.hasBreaks){var a= +this.tickPositions,h=this.tickPositions.info,d=[],r;for(r=0;r=g&&(p-=.5);return{from:p,to:a,showPoints:!1}}function d(a,g,p){var c=[],d=[],t={},h={},f=-1,r="boolean"===typeof g?g:!1;a=v.getTree(a,{after:function(a){a=h[a.pos];var g=0,c=0;a.children.forEach(function(a){c+=(a.descendants||0)+1;g=Math.max((a.height||0)+1,g)});a.descendants=c;a.height=g;a.collapsed&&d.push(a)},before:function(a){var g=q(a.data, +!0)?a.data:{},p=z(g.name)?g.name:"",d=t[a.parent];d=q(d,!0)?h[d.pos]:null;var H=function(a){return a.name===p},b;r&&q(d,!0)&&(b=l(d.children,H))?(H=b.pos,b.nodes.push(a)):H=f++;h[H]||(h[H]=b={depth:d?d.depth+1:0,name:p,nodes:[a],children:[],pos:H},-1!==H&&c.push(p),q(d,!0)&&d.children.push(b));z(a.id)&&(t[a.id]=a);b&&!0===g.collapsed&&(b.collapsed=!0);a.pos=H}});h=function(a,g){var c=function(a,p,d){var h=p+(-1===p?0:g-1),t=(h-p)/2,H=p+t;a.nodes.forEach(function(a){var g=a.data;q(g,!0)&&(g.y=p+(g.seriesIndex|| +0),delete g.seriesIndex);a.pos=H});d[H]=a;a.pos=H;a.tickmarkOffset=t+.5;a.collapseStart=h+.5;a.children.forEach(function(a){c(a,h+1,d);h=(a.collapseEnd||0)-.5});a.collapseEnd=h+.5;return d};return c(a["-1"],-1,{})}(h,p);return{categories:c,mapOfIdToNode:t,mapOfPosToGridNode:h,collapsedNodes:d,tree:a}}function f(a){a.target.axes.filter(function(a){return"treegrid"===a.options.type}).forEach(function(g){var p=g.options||{},c=p.labels,h=p.uniqueNames,t=0,f=p.max;if(!g.treeGrid.mapOfPosToGridNode||g.series.some(function(a){return!a.hasRendered|| +a.isDirtyData||a.isDirty})){p=g.series.reduce(function(a,g){g.visible&&((g.options.data||[]).forEach(function(g){q(g,!0)&&(g.seriesIndex=t,a.push(g))}),!0===h&&t++);return a},[]);if(f&&p.length=c)||a.brokenAxis&&a.brokenAxis.isInAnyBreak(c)||g.push(c);return g},[])};a.prototype.isCollapsed=function(a){var g=this.axis,c=g.options.breaks||[],d=h(a,g.max);return c.some(function(a){return a.from===d.from&&a.to===d.to})};a.prototype.toggleCollapse=function(a){return this.isCollapsed(a)?this.expand(a):this.collapse(a)};return a}();a.Additions=B})(f||(f={}));e.prototype.utils={getNode:v.getNode};f.compose(e);return f});J(e,"Extensions/CurrentDateIndication.js",[e["Core/Globals.js"],e["Core/Options.js"], +e["Core/Utilities.js"],e["Core/Axis/PlotLineOrBand.js"]],function(e,n,v,x){var w=n.dateFormat;n=v.addEvent;var y=v.merge;v=v.wrap;var C={currentDateIndicator:!0,color:"#ccd6eb",width:2,label:{format:"%a, %b %d %Y, %H:%M",formatter:function(e,l){return w(l,e)},rotation:0,style:{fontSize:"10px"}}};n(e.Axis,"afterSetOptions",function(){var e=this.options,l=e.currentDateIndicator;l&&(l="object"===typeof l?y(C,l):y(C),l.value=new Date,e.plotLines||(e.plotLines=[]),e.plotLines.push(l))});n(x,"render",function(){this.label&& +this.label.attr({text:this.getLabelText(this.options.label)})});v(x.prototype,"getLabelText",function(e,l){var b=this.options;return b.currentDateIndicator&&b.label&&"function"===typeof b.label.formatter?(b.value=new Date,b.label.formatter.call(this,b.value,b.label.format)):e.call(this,l)})});J(e,"Extensions/StaticScale.js",[e["Core/Globals.js"],e["Core/Utilities.js"]],function(e,n){var v=n.addEvent,x=n.defined,w=n.isNumber,y=n.pick;n=e.Chart;v(e.Axis,"afterSetOptions",function(){var e=this.chart.options&& +this.chart.options.chart;!this.horiz&&w(this.options.staticScale)&&(!e.height||e.scrollablePlotArea&&e.scrollablePlotArea.minHeight)&&(this.staticScale=this.options.staticScale)});n.prototype.adjustHeight=function(){"adjustHeight"!==this.redrawTrigger&&((this.axes||[]).forEach(function(e){var n=e.chart,l=!!n.initiatedScale&&n.options.animation,b=e.options.staticScale;if(e.staticScale&&x(e.min)){var m=y(e.brokenAxis&&e.brokenAxis.unitLength,e.max+e.tickInterval-e.min)*b;m=Math.max(m,b);b=m-n.plotHeight; +1<=Math.abs(b)&&(n.plotHeight=m,n.redrawTrigger="adjustHeight",n.setSize(void 0,n.chartHeight+b,l));e.series.forEach(function(b){(b=b.sharedClipKey&&n[b.sharedClipKey])&&b.attr({height:n.plotHeight})})}}),this.initiatedScale=!0);this.redrawTrigger=null};v(n,"render",n.prototype.adjustHeight)});J(e,"Extensions/ArrowSymbols.js",[e["Core/Renderer/SVG/SVGRenderer.js"]],function(e){e.prototype.symbols.arrow=function(e,v,x,w){return[["M",e,v+w/2],["L",e+x,v],["L",e,v+w/2],["L",e+x,v+w]]};e.prototype.symbols["arrow-half"]= +function(n,v,x,w){return e.prototype.symbols.arrow(n,v,x/2,w)};e.prototype.symbols["triangle-left"]=function(e,v,x,w){return[["M",e+x,v],["L",e,v+w/2],["L",e+x,v+w],["Z"]]};e.prototype.symbols["arrow-filled"]=e.prototype.symbols["triangle-left"];e.prototype.symbols["triangle-left-half"]=function(n,v,x,w){return e.prototype.symbols["triangle-left"](n,v,x/2,w)};e.prototype.symbols["arrow-filled-half"]=e.prototype.symbols["triangle-left-half"]});J(e,"Gantt/Connection.js",[e["Core/Globals.js"],e["Core/Options.js"], +e["Core/Series/Point.js"],e["Core/Utilities.js"]],function(e,n,v,x){function w(b){var m=b.shapeArgs;return m?{xMin:m.x,xMax:m.x+m.width,yMin:m.y,yMax:m.y+m.height}:(m=b.graphic&&b.graphic.getBBox())?{xMin:b.plotX-m.width/2,xMax:b.plotX+m.width/2,yMin:b.plotY-m.height/2,yMax:b.plotY+m.height/2}:null}"";var y=x.defined,C=x.error,u=x.extend,l=x.merge,b=x.objectEach,m=e.deg2rad,q=Math.max,z=Math.min;u(n.defaultOptions,{connectors:{type:"straight",lineWidth:1,marker:{enabled:!1,align:"center",verticalAlign:"middle", +inside:!1,lineWidth:1},startMarker:{symbol:"diamond"},endMarker:{symbol:"arrow-filled"}}});n=function(){function e(b,k,f){this.toPoint=this.pathfinder=this.graphics=this.fromPoint=this.chart=void 0;this.init(b,k,f)}e.prototype.init=function(b,k,f){this.fromPoint=b;this.toPoint=k;this.options=f;this.chart=b.series.chart;this.pathfinder=this.chart.pathfinder};e.prototype.renderPath=function(b,k,f){var a=this.chart,h=a.styledMode,d=a.pathfinder,r=!a.options.chart.forExport&&!1!==f,c=this.graphics&&this.graphics.path; +d.group||(d.group=a.renderer.g().addClass("highcharts-pathfinder-group").attr({zIndex:-1}).add(a.seriesGroup));d.group.translate(a.plotLeft,a.plotTop);c&&c.renderer||(c=a.renderer.path().add(d.group),h||c.attr({opacity:0}));c.attr(k);b={d:b};h||(b.opacity=1);c[r?"animate":"attr"](b,f);this.graphics=this.graphics||{};this.graphics.path=c};e.prototype.addMarker=function(b,k,f){var a=this.fromPoint.series.chart,h=a.pathfinder;a=a.renderer;var d="start"===b?this.fromPoint:this.toPoint,r=d.getPathfinderAnchorPoint(k); +if(k.enabled&&((f="start"===b?f[1]:f[f.length-2])&&"M"===f[0]||"L"===f[0])){f={x:f[1],y:f[2]};f=d.getRadiansToVector(f,r);r=d.getMarkerVector(f,k.radius,r);f=-f/m;if(k.width&&k.height){var c=k.width;var A=k.height}else c=A=2*k.radius;this.graphics=this.graphics||{};r={x:r.x-c/2,y:r.y-A/2,width:c,height:A,rotation:f,rotationOriginX:r.x,rotationOriginY:r.y};this.graphics[b]?this.graphics[b].animate(r):(this.graphics[b]=a.symbol(k.symbol).addClass("highcharts-point-connecting-path-"+b+"-marker").attr(r).add(h.group), +a.styledMode||this.graphics[b].attr({fill:k.color||this.fromPoint.color,stroke:k.lineColor,"stroke-width":k.lineWidth,opacity:0}).animate({opacity:1},d.series.options.animation))}};e.prototype.getPath=function(b){var k=this.pathfinder,f=this.chart,a=k.algorithms[b.type],h=k.chartObstacles;if("function"!==typeof a)return C('"'+b.type+'" is not a Pathfinder algorithm.'),{path:[],obstacles:[]};a.requiresObstacles&&!h&&(h=k.chartObstacles=k.getChartObstacles(b),f.options.connectors.algorithmMargin=b.algorithmMargin, +k.chartObstacleMetrics=k.getObstacleMetrics(h));return a(this.fromPoint.getPathfinderAnchorPoint(b.startMarker),this.toPoint.getPathfinderAnchorPoint(b.endMarker),l({chartObstacles:h,lineObstacles:k.lineObstacles||[],obstacleMetrics:k.chartObstacleMetrics,hardBounds:{xMin:0,xMax:f.plotWidth,yMin:0,yMax:f.plotHeight},obstacleOptions:{margin:b.algorithmMargin},startDirectionX:k.getAlgorithmStartDirection(b.startMarker)},b))};e.prototype.render=function(){var b=this.fromPoint,k=b.series,f=k.chart,a= +f.pathfinder,h=l(f.options.connectors,k.options.connectors,b.options.connectors,this.options),d={};f.styledMode||(d.stroke=h.lineColor||b.color,d["stroke-width"]=h.lineWidth,h.dashStyle&&(d.dashstyle=h.dashStyle));d["class"]="highcharts-point-connecting-path highcharts-color-"+b.colorIndex;h=l(d,h);y(h.marker.radius)||(h.marker.radius=z(q(Math.ceil((h.algorithmMargin||8)/2)-1,1),5));b=this.getPath(h);f=b.path;b.obstacles&&(a.lineObstacles=a.lineObstacles||[],a.lineObstacles=a.lineObstacles.concat(b.obstacles)); +this.renderPath(f,d,k.options.animation);this.addMarker("start",l(h.marker,h.startMarker),f);this.addMarker("end",l(h.marker,h.endMarker),f)};e.prototype.destroy=function(){this.graphics&&(b(this.graphics,function(b){b.destroy()}),delete this.graphics)};return e}();e.Connection=n;u(v.prototype,{getPathfinderAnchorPoint:function(b){var m=w(this);switch(b.align){case "right":var k="xMax";break;case "left":k="xMin"}switch(b.verticalAlign){case "top":var f="yMin";break;case "bottom":f="yMax"}return{x:k? +m[k]:(m.xMin+m.xMax)/2,y:f?m[f]:(m.yMin+m.yMax)/2}},getRadiansToVector:function(b,m){var k;y(m)||(k=w(this))&&(m={x:(k.xMin+k.xMax)/2,y:(k.yMin+k.yMax)/2});return Math.atan2(m.y-b.y,b.x-m.x)},getMarkerVector:function(b,m,k){var f=2*Math.PI,a=w(this),h=a.xMax-a.xMin,d=a.yMax-a.yMin,r=Math.atan2(d,h),c=!1;h/=2;var A=d/2,t=a.xMin+h;a=a.yMin+A;for(var e=t,D=a,B={},E=1,g=1;b<-Math.PI;)b+=f;for(;b>Math.PI;)b-=f;f=Math.tan(b);b>-r&&b<=r?(g=-1,c=!0):b>r&&b<=Math.PI-r?g=-1:b>Math.PI-r||b<=-(Math.PI-r)?(E= +-1,c=!0):E=-1;c?(e+=E*h,D+=g*h*f):(e+=d/(2*f)*E,D+=g*A);k.x!==t&&(e=k.x);k.y!==a&&(D=k.y);B.x=e+m*Math.cos(b);B.y=D-m*Math.sin(b);return B}});return n});J(e,"Gantt/PathfinderAlgorithms.js",[e["Core/Utilities.js"]],function(e){function n(b,e,l){l=l||0;var m=b.length-1;e-=1e-7;for(var q,k;l<=m;)if(q=m+l>>1,k=e-b[q].xMin,0k)m=q-1;else return q;return 0=e.x)q=b[m],q=e.x<=q.xMax&&e.x>=q.xMin&&e.y<=q.yMax&&e.y>= +q.yMin;if(q)return m}return-1}function x(b){var e=[];if(b.length){e.push(["M",b[0].start.x,b[0].start.y]);for(var m=0;mb(d[h]-a[h+"Max"]);return m(d, +h,a,h+(c?"Max":"Min"),c?1:-1)}var k=[],f=C(l.startDirectionX,b(q.x-e.x)>b(q.y-e.y))?"x":"y",a=l.chartObstacles,h=v(a,e);l=v(a,q);if(-1=e[f]===l[f]>=r[f]&&(f="y"===f?"x":"y",q=e[f]d?u(n(B,h.x),B.length-1):0;B[p]&&(0d&&B[p].xMax>=b.x);){if(B[p].xMin<=h.x&&B[p].xMax>=b.x&&B[p].yMin<=t.y&&B[p].yMax>=f.y)return c?{y:a.y,x:a.x=p[t+"Max"];p=a[t+"Min"]<=p[t+"Min"];var k=a[t+"Max"]>=f[t+"Max"];f=a[t+"Min"]<=f[t+"Min"];var A=b(a[t+"Min"]-g[t]),H=b(a[t+"Max"]-g[t]);c=10>b(A-H)?g[t]b(q.y-e.y)),h=a?"x":"y",d=[],r=!1,c=z.obstacleMetrics,A=u(e.x,q.x)-c.maxWidth-10,t=l(e.x,q.x)+c.maxWidth+10,I=u(e.y,q.y)-c.maxHeight-10,D=l(e.y,q.y)+c.maxHeight+10,B=z.chartObstacles;var E=n(B,A);c=n(B,t);B=B.slice(E,c+1);if(-1<(c=v(B,q))){var g=f(B[c],q,e);d.push({end:q,start:g});q=g}for(;-1<(c=v(B,q));)E=0>q[h]-e[h],g={x:q.x,y:q.y},g[h]=B[c][E?h+"Max":h+"Min"]+(E?1:-1),d.push({end:q,start:g}),q=g;e=k(e,q,a);e=e.concat(d.reverse());return{path:x(e),obstacles:e}},{requiresObstacles:!0}), +straight:function(b,e){return{path:[["M",b.x,b.y],["L",e.x,e.y]],obstacles:[{start:b,end:e}]}},simpleConnect:e}});J(e,"Gantt/Pathfinder.js",[e["Gantt/Connection.js"],e["Core/Chart/Chart.js"],e["Core/Globals.js"],e["Core/Options.js"],e["Core/Series/Point.js"],e["Core/Utilities.js"],e["Gantt/PathfinderAlgorithms.js"]],function(e,n,v,x,w,y,C){function u(a){var c=a.shapeArgs;return c?{xMin:c.x,xMax:c.x+c.width,yMin:c.y,yMax:c.y+c.height}:(c=a.graphic&&a.graphic.getBBox())?{xMin:a.plotX-c.width/2,xMax:a.plotX+ +c.width/2,yMin:a.plotY-c.height/2,yMax:a.plotY+c.height/2}:null}function l(d){for(var c=d.length,b=0,t,f,e=[],r=function(a,g,c){c=k(c,10);var d=a.yMax+c>g.yMin-c&&a.yMin-cg.xMin-c&&a.xMin-cg.xMax?a.xMin-g.xMax:g.xMin-a.xMax:Infinity,t=b?a.yMin>g.yMax?a.yMin-g.yMax:g.yMin-a.yMax:Infinity;return b&&d?c?r(a,g,Math.floor(c/2)):Infinity:h(p,t)};bf&&e.push(f);e.push(80);return a(Math.floor(e.sort(function(a,g){return a- +g})[Math.floor(e.length/10)]/2-1),1)}function b(a){if(a.options.pathfinder||a.series.reduce(function(a,d){d.options&&G(!0,d.options.connectors=d.options.connectors||{},d.options.pathfinder);return a||d.options&&d.options.pathfinder},!1))G(!0,a.options.connectors=a.options.connectors||{},a.options.pathfinder),z('WARNING: Pathfinder options have been renamed. Use "chart.connectors" or "series.connectors" instead.')}"";var m=y.addEvent,q=y.defined,z=y.error,F=y.extend,G=y.merge,k=y.pick,f=y.splat,a= +Math.max,h=Math.min;F(x.defaultOptions,{connectors:{type:"straight",lineWidth:1,marker:{enabled:!1,align:"center",verticalAlign:"middle",inside:!1,lineWidth:1},startMarker:{symbol:"diamond"},endMarker:{symbol:"arrow-filled"}}});var d=function(){function a(a){this.lineObstacles=this.group=this.connections=this.chartObstacleMetrics=this.chartObstacles=this.chart=void 0;this.init(a)}a.prototype.init=function(a){this.chart=a;this.connections=[];m(a,"redraw",function(){this.pathfinder.update()})};a.prototype.update= +function(a){var c=this.chart,d=this,b=d.connections;d.connections=[];c.series.forEach(function(a){a.visible&&!a.options.isInternal&&a.points.forEach(function(a){var g,b=a.options&&a.options.connect&&f(a.options.connect);a.visible&&!1!==a.isInside&&b&&b.forEach(function(b){g=c.get("string"===typeof b?b:b.to);g instanceof w&&g.series.visible&&g.visible&&!1!==g.isInside&&d.connections.push(new e(a,g,"string"===typeof b?{}:b))})})});for(var h=0,r,k,g=b.length,p=d.connections.length;hMath.PI;)a-=b;b=Math.tan(a);a>-r&&a<=r?(n=-1,g=!0):a>r&&a<=Math.PI-r?n=-1:a>Math.PI-r||a<=-(Math.PI-r)?(A=-1,g=!0):A=-1;g?(m+=A*f,l+=n*f*b):(m+=e/(2*b)*A,l+=n*p);d.x!==k&&(m=d.x);d.y!==h&&(l=d.y);q.x=m+c*Math.cos(a);q.y=l-c*Math.sin(a);return q}});n.prototype.callbacks.push(function(a){!1!==a.options.connectors.enabled&&(b(a),this.pathfinder= +new d(this),this.pathfinder.update(!0))});return d});J(e,"Series/XRangeSeries.js",[e["Core/Axis/Axis.js"],e["Core/Globals.js"],e["Core/Color.js"],e["Core/Series/Point.js"],e["Core/Utilities.js"]],function(e,n,v,x,w){var y=v.parse;v=w.addEvent;var C=w.clamp,u=w.correctFloat,l=w.defined,b=w.find,m=w.isNumber,q=w.isObject,z=w.merge,F=w.pick;w=w.seriesType;var G=n.seriesTypes.column,k=n.seriesTypes,f=n.Series;w("xrange","column",{colorByPoint:!0,dataLabels:{formatter:function(){var a=this.point.partialFill; +q(a)&&(a=a.amount);if(m(a)&&0{point.x} - {point.x2}
    ',pointFormat:'\u25cf {series.name}: {point.yCategory}
    '},borderRadius:3,pointRange:0},{type:"xrange",parallelArrays:["x","x2","y"],requireSorting:!1,animate:k.line.prototype.animate,cropShoulder:1,getExtremesFromAll:!0,autoIncrement:n.noop,buildKDTree:n.noop,init:function(){k.column.prototype.init.apply(this, +arguments);this.options.stacking=void 0},getColumnMetrics:function(){function a(){b.series.forEach(function(a){var c=a.xAxis;a.xAxis=a.yAxis;a.yAxis=c})}var b=this.chart;a();var d=G.prototype.getColumnMetrics.call(this);a();return d},cropData:function(a,b,d,e){b=f.prototype.cropData.call(this,this.x2Data,b,d,e);b.xData=a.slice(b.start,b.end);return b},findPointIndex:function(a){var h=this.cropped,d=this.cropStart,f=this.points,c=a.id;if(c)var e=(e=b(f,function(a){return a.id===c}))?e.index:void 0; +"undefined"===typeof e&&(e=(e=b(f,function(c){return c.x===a.x&&c.x2===a.x2&&!c.touched}))?e.index:void 0);h&&m(e)&&m(d)&&e>=d&&(e-=d);return e},translatePoint:function(a){var b=this.xAxis,d=this.yAxis,f=this.columnMetrics,c=this.options,e=c.minPointLength||0,t=a.plotX,k=F(a.x2,a.x+(a.len||0)),D=b.translate(k,0,0,0,1);k=Math.abs(D-t);var B=this.chart.inverted,E=F(c.borderWidth,1)%2/2,g=f.offset,p=Math.round(f.width);e&&(e-=k,0>e&&(e=0),t-=e/2,D+=e/2);t=Math.max(t,-10);D=C(D,-10,b.len+10);l(a.options.pointWidth)&& +(g-=(Math.ceil(a.options.pointWidth)-p)/2,p=Math.ceil(a.options.pointWidth));c.pointPlacement&&m(a.plotY)&&d.categories&&(a.plotY=d.translate(a.y,0,1,0,1,c.pointPlacement));a.shapeArgs={x:Math.floor(Math.min(t,D))+E,y:Math.floor(a.plotY+g)+E,width:Math.round(Math.abs(D-t)),height:p,r:this.options.borderRadius};c=a.shapeArgs.x;e=c+a.shapeArgs.width;0>c||e>b.len?(c=C(c,0,b.len),e=C(e,0,b.len),D=e-c,a.dlBox=z(a.shapeArgs,{x:c,width:e-c,centerX:D?D/2:null})):a.dlBox=null;c=a.tooltipPos;e=B?1:0;D=B?0: +1;f=this.columnMetrics?this.columnMetrics.offset:-f.width/2;c[e]=C(c[e]+k/2*(b.reversed?-1:1)*(B?-1:1),0,b.len-1);c[D]=C(c[D]+(B?-1:1)*f,0,d.len-1);if(f=a.partialFill)q(f)&&(f=f.amount),m(f)||(f=0),d=a.shapeArgs,a.partShapeArgs={x:d.x,y:d.y,width:d.width,height:d.height,r:this.options.borderRadius},t=Math.max(Math.round(k*f+a.plotX-t),0),a.clipRectArgs={x:b.reversed?d.x+k-t:d.x,y:d.y,width:t,height:d.height}},translate:function(){G.prototype.translate.apply(this,arguments);this.points.forEach(function(a){this.translatePoint(a)}, +this)},drawPoint:function(a,b){var d=this.options,f=this.chart.renderer,c=a.graphic,h=a.shapeType,e=a.shapeArgs,k=a.partShapeArgs,m=a.clipRectArgs,l=a.partialFill,E=d.stacking&&!d.borderRadius,g=a.state,p=d.states[g||"normal"]||{},H="undefined"===typeof g?"attr":b;g=this.pointAttribs(a,g);p=F(this.chart.options.chart.animation,p.animation);if(a.isNull||!1===a.visible)c&&(a.graphic=c.destroy());else{if(c)c.rect[b](e);else a.graphic=c=f.g("point").addClass(a.getClassName()).add(a.group||this.group), +c.rect=f[h](z(e)).addClass(a.getClassName()).addClass("highcharts-partfill-original").add(c);k&&(c.partRect?(c.partRect[b](z(k)),c.partialClipRect[b](z(m))):(c.partialClipRect=f.clipRect(m.x,m.y,m.width,m.height),c.partRect=f[h](k).addClass("highcharts-partfill-overlay").add(c).clip(c.partialClipRect)));this.chart.styledMode||(c.rect[b](g,p).shadow(d.shadow,null,E),k&&(q(l)||(l={}),q(d.partialFill)&&(l=z(l,d.partialFill)),a=l.fill||y(g.fill).brighten(-.3).get()||y(a.color||this.color).brighten(-.3).get(), +g.fill=a,c.partRect[H](g,p).shadow(d.shadow,null,E)))}},drawPoints:function(){var a=this,b=a.getAnimationVerb();a.points.forEach(function(d){a.drawPoint(d,b)})},getAnimationVerb:function(){return this.chart.pointCount<(this.options.animationLimit||250)?"animate":"attr"}},{resolveColor:function(){var a=this.series;if(a.options.colorByPoint&&!this.options.color){var b=a.options.colors||a.chart.options.colors;var d=this.y%(b?b.length:a.chart.options.chart.colorCount);b=b&&b[d];a.chart.styledMode||(this.color= +b);this.options.colorIndex||(this.colorIndex=d)}else this.color||(this.color=a.color)},init:function(){x.prototype.init.apply(this,arguments);this.y||(this.y=0);return this},setState:function(){x.prototype.setState.apply(this,arguments);this.series.drawPoint(this,this.series.getAnimationVerb())},getLabelConfig:function(){var a=x.prototype.getLabelConfig.call(this),b=this.series.yAxis.categories;a.x2=this.x2;a.yCategory=this.yCategory=b&&b[this.y];return a},tooltipDateKeys:["x","x2"],isValid:function(){return"number"=== +typeof this.x&&"number"===typeof this.x2}});v(e,"afterGetSeriesExtremes",function(){var a=this.series,b;if(this.isXAxis){var d=F(this.dataMax,-Number.MAX_VALUE);a.forEach(function(a){a.x2Data&&a.x2Data.forEach(function(a){a>d&&(d=a,b=!0)})});b&&(this.dataMax=d)}});""});J(e,"Series/GanttSeries.js",[e["Core/Globals.js"],e["Core/Options.js"],e["Core/Utilities.js"]],function(e,n,v){var x=n.dateFormat,w=v.isNumber,y=v.merge,C=v.pick;n=v.seriesType;var u=v.splat,l=e.seriesTypes.xrange;n("gantt","xrange", +{grouping:!1,dataLabels:{enabled:!0},tooltip:{headerFormat:'{series.name}
    ',pointFormat:null,pointFormatter:function(){var b=this.series,e=b.chart.tooltip,l=b.xAxis,n=b.tooltipOptions.dateTimeLabelFormats,w=l.options.startOfWeek,v=b.tooltipOptions,k=v.xDateFormat;b=this.options.milestone;var f=""+(this.name||this.yCategory)+"";if(v.pointFormat)return this.tooltipFormatter(v.pointFormat);k||(k=u(e.getDateFormat(l.closestPointRange,this.start,w,n))[0]); +e=x(k,this.start);l=x(k,this.end);f+="
    ";return b?f+(e+"
    "):f+("Start: "+e+"
    End: ")+(l+"
    ")}},connectors:{type:"simpleConnect",animation:{reversed:!0},startMarker:{enabled:!0,symbol:"arrow-filled",radius:4,fill:"#fa0",align:"left"},endMarker:{enabled:!1,align:"right"}}},{pointArrayMap:["start","end","y"],keyboardMoveVertical:!1,translatePoint:function(b){l.prototype.translatePoint.call(this,b);if(b.options.milestone){var e=b.shapeArgs;var q=e.height;b.shapeArgs={x:e.x-q/2,y:e.y,width:q, +height:q}}},drawPoint:function(b,e){var m=this.options,n=this.chart.renderer,u=b.shapeArgs,v=b.plotY,k=b.graphic,f=b.selected&&"select",a=m.stacking&&!m.borderRadius;if(b.options.milestone)if(w(v)&&null!==b.y&&!1!==b.visible){u=n.symbols.diamond(u.x,u.y,u.width,u.height);if(k)k[e]({d:u});else b.graphic=n.path(u).addClass(b.getClassName(),!0).add(b.group||this.group);this.chart.styledMode||b.graphic.attr(this.pointAttribs(b,f)).shadow(m.shadow,null,a)}else k&&(b.graphic=k.destroy());else l.prototype.drawPoint.call(this, +b,e)},setData:e.Series.prototype.setData,setGanttPointAliases:function(b){function e(e,l){"undefined"!==typeof l&&(b[e]=l)}e("x",C(b.start,b.x));e("x2",C(b.end,b.x2));e("partialFill",C(b.completed,b.partialFill));e("connect",C(b.dependency,b.connect))}},y(l.prototype.pointClass.prototype,{applyOptions:function(b,m){b=y(b);e.seriesTypes.gantt.prototype.setGanttPointAliases(b);return b=l.prototype.pointClass.prototype.applyOptions.call(this,b,m)},isValid:function(){return("number"===typeof this.start|| +"number"===typeof this.x)&&("number"===typeof this.end||"number"===typeof this.x2||this.milestone)}}));""});J(e,"Core/Chart/GanttChart.js",[e["Core/Chart/Chart.js"],e["Core/Globals.js"],e["Core/Utilities.js"]],function(e,n,v){var x=v.getOptions,w=v.isArray,y=v.merge,C=v.splat;n.ganttChart=function(u,l,b){var m="string"===typeof u||u.nodeName,q=l.series,z=x(),v,G=l;l=arguments[m?1:0];w(l.xAxis)||(l.xAxis=[l.xAxis||{},{}]);l.xAxis=l.xAxis.map(function(b,f){1===f&&(v=0);return y(z.xAxis,{grid:{enabled:!0}, +opposite:!0,linkedTo:v},b,{type:"datetime"})});l.yAxis=C(l.yAxis||{}).map(function(b){return y(z.yAxis,{grid:{enabled:!0},staticScale:50,reversed:!0,type:b.categories?b.type:"treegrid"},b)});l.series=null;l=y(!0,{chart:{type:"gantt"},title:{text:null},legend:{enabled:!1},navigator:{series:{type:"gantt"}}},l,{isGantt:!0});l.series=G.series=q;(l.series||[]).forEach(function(b){b.data&&b.data.forEach(function(b){n.seriesTypes.gantt.prototype.setGanttPointAliases(b)})});return m?new e(u,l,b):new e(l, +l)}});J(e,"Core/Axis/ScrollbarAxis.js",[e["Core/Globals.js"],e["Core/Utilities.js"]],function(e,n){var v=n.addEvent,x=n.defined,w=n.pick;return function(){function n(){}n.compose=function(n,u){v(n,"afterInit",function(){var l=this;l.options&&l.options.scrollbar&&l.options.scrollbar.enabled&&(l.options.scrollbar.vertical=!l.horiz,l.options.startOnTick=l.options.endOnTick=!1,l.scrollbar=new u(l.chart.renderer,l.options.scrollbar,l.chart),v(l.scrollbar,"changed",function(b){var m=w(l.options&&l.options.min, +l.min),q=w(l.options&&l.options.max,l.max),n=x(l.dataMin)?Math.min(m,l.min,l.dataMin):m,u=(x(l.dataMax)?Math.max(q,l.max,l.dataMax):q)-n;x(m)&&x(q)&&(l.horiz&&!l.reversed||!l.horiz&&l.reversed?(m=n+u*this.to,n+=u*this.from):(m=n+u*(1-this.from),n+=u*(1-this.to)),w(this.options.liveRedraw,e.svg&&!e.isTouchDevice&&!this.chart.isBoosting)||"mouseup"===b.DOMType||!x(b.DOMType)?l.setExtremes(n,m,!0,"mousemove"!==b.DOMType,b):this.setRange(this.from,this.to))}))});v(n,"afterRender",function(){var e=Math.min(w(this.options.min, +this.min),this.min,w(this.dataMin,this.min)),b=Math.max(w(this.options.max,this.max),this.max,w(this.dataMax,this.max)),m=this.scrollbar,q=this.axisTitleMargin+(this.titleOffset||0),n=this.chart.scrollbarsOffsets,u=this.options.margin||0;m&&(this.horiz?(this.opposite||(n[1]+=q),m.position(this.left,this.top+this.height+2+n[1]-(this.opposite?u:0),this.width,this.height),this.opposite||(n[1]+=u),q=1):(this.opposite&&(n[0]+=q),m.position(this.left+this.width+2+n[0]-(this.opposite?0:u),this.top,this.width, +this.height),this.opposite&&(n[0]+=u),q=0),n[q]+=m.size+m.options.margin,isNaN(e)||isNaN(b)||!x(this.min)||!x(this.max)||this.min===this.max?m.setRange(0,1):(n=(this.min-e)/(b-e),e=(this.max-e)/(b-e),this.horiz&&!this.reversed||!this.horiz&&this.reversed?m.setRange(n,e):m.setRange(1-e,1-n)))});v(n,"afterGetOffset",function(){var e=this.horiz?2:1,b=this.scrollbar;b&&(this.chart.scrollbarsOffsets=[0,0],this.chart.axisOffset[e]+=b.size+b.options.margin)})};return n}()});J(e,"Core/Scrollbar.js",[e["Core/Axis/Axis.js"], +e["Core/Globals.js"],e["Core/Axis/ScrollbarAxis.js"],e["Core/Utilities.js"],e["Core/Options.js"]],function(e,n,v,x,w){var y=x.addEvent,C=x.correctFloat,u=x.defined,l=x.destroyObjectProperties,b=x.fireEvent,m=x.merge,q=x.pick,z=x.removeEvent;x=w.defaultOptions;var F=n.hasTouch,G=n.isTouchDevice,k=n.swapXY=function(b,a){a&&b.forEach(function(a){for(var b=a.length,e,c=0;cthis.calculatedWidth?b.minWidth:0;return{chartX:(a.chartX-this.x-this.xOffset)/(this.barWidth-b),chartY:(a.chartY-this.y-this.yOffset)/(this.barWidth-b)}};e.prototype.destroy=function(){var a=this.chart.scroller;this.removeEvents();["track","scrollbarRifles","scrollbar","scrollbarGroup","group"].forEach(function(a){this[a]&&this[a].destroy&&(this[a]=this[a].destroy())},this);a&&this===a.scrollbar&&(a.scrollbar=null,l(a.scrollbarButtons))};e.prototype.drawScrollbarButton=function(a){var b= +this.renderer,d=this.scrollbarButtons,e=this.options,c=this.size;var f=b.g().add(this.group);d.push(f);f=b.rect().addClass("highcharts-scrollbar-button").add(f);this.chart.styledMode||f.attr({stroke:e.buttonBorderColor,"stroke-width":e.buttonBorderWidth,fill:e.buttonBackgroundColor});f.attr(f.crisp({x:-.5,y:-.5,width:c+1,height:c+1,r:e.buttonBorderRadius},f.strokeWidth()));f=b.path(k([["M",c/2+(a?-1:1),c/2-3],["L",c/2+(a?-1:1),c/2+3],["L",c/2+(a?2:-2),c/2]],e.vertical)).addClass("highcharts-scrollbar-arrow").add(d[a]); +this.chart.styledMode||f.attr({fill:e.buttonArrowColor})};e.prototype.init=function(a,b,d){this.scrollbarButtons=[];this.renderer=a;this.userOptions=b;this.options=m(e.defaultOptions,b);this.chart=d;this.size=q(this.options.size,this.options.height);b.enabled&&(this.render(),this.addEvents())};e.prototype.mouseDownHandler=function(a){a=this.chart.pointer.normalize(a);a=this.cursorToScrollbarPosition(a);this.chartX=a.chartX;this.chartY=a.chartY;this.initPositions=[this.from,this.to];this.grabbedCenter= +!0};e.prototype.mouseMoveHandler=function(a){var e=this.chart.pointer.normalize(a),d=this.options.vertical?"chartY":"chartX",f=this.initPositions||[];!this.grabbedCenter||a.touches&&0===a.touches[0][d]||(e=this.cursorToScrollbarPosition(e)[d],d=this[d],d=e-d,this.hasDragged=!0,this.updatePosition(f[0]+d,f[1]+d),this.hasDragged&&b(this,"changed",{from:this.from,to:this.to,trigger:"scrollbar",DOMType:a.type,DOMEvent:a}))};e.prototype.mouseUpHandler=function(a){this.hasDragged&&b(this,"changed",{from:this.from, +to:this.to,trigger:"scrollbar",DOMType:a.type,DOMEvent:a});this.grabbedCenter=this.hasDragged=this.chartX=this.chartY=null};e.prototype.position=function(a,b,d,e){var c=this.options.vertical,f=0,h=this.rendered?"animate":"attr";this.x=a;this.y=b+this.trackBorderWidth;this.width=d;this.xOffset=this.height=e;this.yOffset=f;c?(this.width=this.yOffset=d=f=this.size,this.xOffset=b=0,this.barWidth=e-2*d,this.x=a+=this.options.margin):(this.height=this.xOffset=e=b=this.size,this.barWidth=d-2*e,this.y+=this.options.margin); +this.group[h]({translateX:a,translateY:this.y});this.track[h]({width:d,height:e});this.scrollbarButtons[1][h]({translateX:c?0:d-b,translateY:c?e-f:0})};e.prototype.removeEvents=function(){this._events.forEach(function(a){z.apply(null,a)});this._events.length=0};e.prototype.render=function(){var a=this.renderer,b=this.options,d=this.size,e=this.chart.styledMode,c;this.group=c=a.g("scrollbar").attr({zIndex:b.zIndex,translateY:-99999}).add();this.track=a.rect().addClass("highcharts-scrollbar-track").attr({x:0, +r:b.trackBorderRadius||0,height:d,width:d}).add(c);e||this.track.attr({fill:b.trackBackgroundColor,stroke:b.trackBorderColor,"stroke-width":b.trackBorderWidth});this.trackBorderWidth=this.track.strokeWidth();this.track.attr({y:-this.trackBorderWidth%2/2});this.scrollbarGroup=a.g().add(c);this.scrollbar=a.rect().addClass("highcharts-scrollbar-thumb").attr({height:d,width:d,r:b.barBorderRadius||0}).add(this.scrollbarGroup);this.scrollbarRifles=a.path(k([["M",-3,d/4],["L",-3,2*d/3],["M",0,d/4],["L", +0,2*d/3],["M",3,d/4],["L",3,2*d/3]],b.vertical)).addClass("highcharts-scrollbar-rifles").add(this.scrollbarGroup);e||(this.scrollbar.attr({fill:b.barBackgroundColor,stroke:b.barBorderColor,"stroke-width":b.barBorderWidth}),this.scrollbarRifles.attr({stroke:b.rifleColor,"stroke-width":1}));this.scrollbarStrokeWidth=this.scrollbar.strokeWidth();this.scrollbarGroup.translate(-this.scrollbarStrokeWidth%2/2,-this.scrollbarStrokeWidth%2/2);this.drawScrollbarButton(0);this.drawScrollbarButton(1)};e.prototype.setRange= +function(a,b){var d=this.options,e=d.vertical,c=d.minWidth,f=this.barWidth,h,k=!this.rendered||this.hasDragged||this.chart.navigator&&this.chart.navigator.hasDragged?"attr":"animate";if(u(f)){a=Math.max(a,0);var m=Math.ceil(f*a);this.calculatedWidth=h=C(f*Math.min(b,1)-m);h=h?this.scrollbarRifles.hide():this.scrollbarRifles.show(!0);!1===d.showFull&&(0>=a&&1<=b?this.group.hide():this.group.show());this.rendered=!0}};e.prototype.trackClick=function(a){var e=this.chart.pointer.normalize(a),d=this.to-this.from,f=this.y+this.scrollbarTop,c=this.x+this.scrollbarLeft;this.options.vertical&&e.chartY> +f||!this.options.vertical&&e.chartX>c?this.updatePosition(this.from+d,this.to+d):this.updatePosition(this.from-d,this.to-d);b(this,"changed",{from:this.from,to:this.to,trigger:"scrollbar",DOMEvent:a})};e.prototype.update=function(a){this.destroy();this.init(this.chart.renderer,m(!0,this.options,a),this.chart)};e.prototype.updatePosition=function(a,b){1a&&(b=C(b-a),a=0);this.from=a;this.to=b};e.defaultOptions={height:G?20:14,barBorderRadius:0,buttonBorderRadius:0,liveRedraw:void 0, +margin:10,minWidth:6,step:.2,zIndex:3,barBackgroundColor:"#cccccc",barBorderWidth:1,barBorderColor:"#cccccc",buttonArrowColor:"#333333",buttonBackgroundColor:"#e6e6e6",buttonBorderColor:"#cccccc",buttonBorderWidth:1,rifleColor:"#333333",trackBackgroundColor:"#f2f2f2",trackBorderColor:"#f2f2f2",trackBorderWidth:1};return e}();n.Scrollbar||(x.scrollbar=m(!0,w.defaultOptions,x.scrollbar),n.Scrollbar=w,v.compose(e,w));return n.Scrollbar});J(e,"Extensions/RangeSelector.js",[e["Core/Axis/Axis.js"],e["Core/Chart/Chart.js"], +e["Core/Globals.js"],e["Core/Options.js"],e["Core/Renderer/SVG/SVGElement.js"],e["Core/Utilities.js"]],function(e,n,v,x,w,y){var C=x.defaultOptions,u=y.addEvent,l=y.createElement,b=y.css,m=y.defined,q=y.destroyObjectProperties,z=y.discardElement,F=y.extend,G=y.fireEvent,k=y.isNumber,f=y.merge,a=y.objectEach,h=y.pick,d=y.pInt,r=y.splat;F(C,{rangeSelector:{verticalAlign:"top",buttonTheme:{width:28,height:18,padding:2,zIndex:7},floating:!1,x:0,y:0,height:void 0,inputPosition:{align:"right",x:0,y:0}, +buttonPosition:{align:"left",x:0,y:0},labelStyle:{color:"#666666"}}});C.lang=f(C.lang,{rangeSelectorZoom:"Zoom",rangeSelectorFrom:"From",rangeSelectorTo:"To"});var c=function(){function c(a){this.buttons=void 0;this.buttonOptions=c.prototype.defaultButtons;this.options=void 0;this.chart=a;this.init(a)}c.prototype.clickButton=function(a,b){var c=this.chart,d=this.buttonOptions[a],f=c.xAxis[0],g=c.scroller&&c.scroller.getUnionExtremes()||f||{},p=g.dataMin,t=g.dataMax,l=f&&Math.round(Math.min(f.max, +h(t,f.max))),q=d.type;g=d._range;var n,v=d.dataGrouping;if(null!==p&&null!==t){c.fixedRange=g;v&&(this.forcedDataGrouping=!0,e.prototype.setDataGrouping.call(f||{chart:this.chart},v,!1),this.frozenStates=d.preserveDataGrouping);if("month"===q||"year"===q)if(f){q={range:d,max:l,chart:c,dataMin:p,dataMax:t};var M=f.minFromRange.call(q);k(q.newMax)&&(l=q.newMax)}else g=d;else if(g)M=Math.max(l-g,p),l=Math.min(M+g,t);else if("ytd"===q)if(f)"undefined"===typeof t&&(p=Number.MAX_VALUE,t=Number.MIN_VALUE, +c.series.forEach(function(a){a=a.xData;p=Math.min(a[0],p);t=Math.max(a[a.length-1],t)}),b=!1),l=this.getYTDExtremes(t,p,c.time.useUTC),M=n=l.min,l=l.max;else{this.deferredYTDClick=a;return}else"all"===q&&f&&(M=p,l=t);m(M)&&(M+=d._offsetMin);m(l)&&(l+=d._offsetMax);this.setSelected(a);if(f)f.setExtremes(M,l,h(b,1),null,{trigger:"rangeSelectorButton",rangeSelectorButton:d});else{var I=r(c.options.xAxis)[0];var A=I.range;I.range=g;var w=I.min;I.min=n;u(c,"load",function(){I.range=A;I.min=w})}}};c.prototype.setSelected= +function(a){this.selected=this.options.selected=a};c.prototype.init=function(a){var b=this,c=a.options.rangeSelector,d=c.buttons||b.defaultButtons.slice(),e=c.selected,g=function(){var a=b.minInput,g=b.maxInput;a&&a.blur&&G(a,"blur");g&&g.blur&&G(g,"blur")};b.chart=a;b.options=c;b.buttons=[];b.buttonOptions=d;this.unMouseDown=u(a.container,"mousedown",g);this.unResize=u(a,"resize",g);d.forEach(b.computeButtonRange);"undefined"!==typeof e&&d[e]&&this.clickButton(e,!1);u(a,"load",function(){a.xAxis&& +a.xAxis[0]&&u(a.xAxis[0],"setExtremes",function(g){this.max-this.min!==a.fixedRange&&"rangeSelectorButton"!==g.trigger&&"updatedData"!==g.trigger&&b.forcedDataGrouping&&!b.frozenStates&&this.setDataGrouping(!1,!1)})})};c.prototype.updateButtonStates=function(){var a=this,b=this.chart,c=b.xAxis[0],d=Math.round(c.max-c.min),e=!c.hasVisibleSeries,g=b.scroller&&b.scroller.getUnionExtremes()||c,f=g.dataMin,h=g.dataMax;b=a.getYTDExtremes(h,f,b.time.useUTC);var l=b.min,m=b.max,r=a.selected,q=k(r),n=a.options.allButtonsEnabled, +u=a.buttons;a.buttonOptions.forEach(function(b,g){var p=b._range,k=b.type,t=b.count||1,H=u[g],E=0,D=b._offsetMax-b._offsetMin;b=g===r;var B=p>h-f,L=p=864E5*{month:28,year:365}[k]*t-D&&d-36E5<=864E5*{month:31,year:366}[k]*t+D?p=!0:"ytd"===k?(p=m-l+D===d,K=!b):"all"===k&&(p=c.max-c.min>=h-f,v=!b&&q&&p);k=!n&&(B||L||v||e);t=b&&p||p&&!q&&!K||b&&a.frozenStates;k?E=3:t&&(q=!0,E=2);H.state!==E&&(H.setState(E),0===E&&r===g&&a.setSelected(null))})}; +c.prototype.computeButtonRange=function(a){var b=a.type,c=a.count||1,d={millisecond:1,second:1E3,minute:6E4,hour:36E5,day:864E5,week:6048E5};if(d[b])a._range=d[b]*c;else if("month"===b||"year"===b)a._range=864E5*{month:30,year:365}[b]*c;a._offsetMin=h(a.offsetMin,0);a._offsetMax=h(a.offsetMax,0);a._range+=a._offsetMax-a._offsetMin};c.prototype.setInputValue=function(a,b){var c=this.chart.options.rangeSelector,d=this.chart.time,e=this[a+"Input"];m(b)&&(e.previousValue=e.HCTime,e.HCTime=b);e.value= +d.dateFormat(c.inputEditDateFormat||"%Y-%m-%d",e.HCTime);this[a+"DateBox"].attr({text:d.dateFormat(c.inputDateFormat||"%b %e, %Y",e.HCTime)})};c.prototype.showInput=function(a){var c=this.inputGroup,d=this[a+"DateBox"];b(this[a+"Input"],{left:c.translateX+d.x+"px",top:c.translateY+"px",width:d.width-2+"px",height:d.height-2+"px",border:"2px solid silver"})};c.prototype.hideInput=function(a){b(this[a+"Input"],{border:0,width:"1px",height:"1px"});this.setInputValue(a)};c.prototype.defaultInputDateParser= +function(a,b){var c=new Date;return v.isSafari?Date.parse(a.split(" ").join("T")):b?Date.parse(a+"Z"):Date.parse(a)-6E4*c.getTimezoneOffset()};c.prototype.drawInput=function(a){function c(){var a=q.value,b=h.xAxis[0];var g=h.scroller&&h.scroller.xAxis?h.scroller.xAxis:b;var c=g.dataMin,f=g.dataMax;g=(p.inputDateParser||M)(a,h.time.useUTC);g!==q.previousValue&&(q.previousValue=g,k(g)||(g=a.split("-"),g=Date.UTC(d(g[0]),d(g[1])-1,d(g[2]))),k(g)&&(h.time.useUTC||(g+=6E4*(new Date).getTimezoneOffset()), +r?g>e.maxInput.HCTime?g=void 0:gf&&(g=f),"undefined"!==typeof g&&b.setExtremes(r?g:b.min,r?b.max:g,void 0,void 0,{trigger:"rangeSelectorInput"})))}var e=this,h=e.chart,t=h.renderer.style||{},g=h.renderer,p=h.options.rangeSelector,m=e.div,r="min"===a,q,n,u=this.inputGroup,M=this.defaultInputDateParser;this[a+"Label"]=n=g.label(C.lang[r?"rangeSelectorFrom":"rangeSelectorTo"],this.inputGroup.offset).addClass("highcharts-range-label").attr({padding:2}).add(u); +u.offset+=n.width+5;this[a+"DateBox"]=g=g.label("",u.offset).addClass("highcharts-range-input").attr({padding:2,width:p.inputBoxWidth||90,height:p.inputBoxHeight||17,"text-align":"center"}).on("click",function(){e.showInput(a);e[a+"Input"].focus()});h.styledMode||g.attr({stroke:p.inputBoxBorderColor||"#cccccc","stroke-width":1});g.add(u);u.offset+=g.width+(r?10:0);this[a+"Input"]=q=l("input",{name:a,className:"highcharts-range-selector",type:"text"},{top:h.plotTop+"px"},m);h.styledMode||(n.css(f(t, +p.labelStyle)),g.css(f({color:"#333333"},t,p.inputStyle)),b(q,F({position:"absolute",border:0,width:"1px",height:"1px",padding:0,textAlign:"center",fontSize:t.fontSize,fontFamily:t.fontFamily,top:"-9999em"},p.inputStyle)));q.onfocus=function(){e.showInput(a)};q.onblur=function(){q===v.doc.activeElement&&c();e.hideInput(a);q.blur()};q.onchange=c;q.onkeypress=function(a){13===a.keyCode&&c()}};c.prototype.getPosition=function(){var a=this.chart,b=a.options.rangeSelector;a="top"===b.verticalAlign?a.plotTop- +a.axisOffset[0]:0;return{buttonTop:a+b.buttonPosition.y,inputTop:a+b.inputPosition.y-10}};c.prototype.getYTDExtremes=function(a,b,c){var d=this.chart.time,e=new d.Date(a),g=d.get("FullYear",e);c=c?d.Date.UTC(g,0,1):+new d.Date(g,0,1);b=Math.max(b||0,c);e=e.getTime();return{max:Math.min(a||e,e),min:b}};c.prototype.render=function(a,b){var c=this,d=c.chart,e=d.renderer,g=d.container,f=d.options,k=f.exporting&&!1!==f.exporting.enabled&&f.navigation&&f.navigation.buttonOptions,t=C.lang,m=c.div,q=f.rangeSelector, +r=h(f.chart.style&&f.chart.style.zIndex,0)+1;f=q.floating;var n=c.buttons;m=c.inputGroup;var u=q.buttonTheme,v=q.buttonPosition,A=q.inputPosition,w=q.inputEnabled,y=u&&u.states,x=d.plotLeft,z=c.buttonGroup,I,G=c.options.verticalAlign,F=d.legend,J=F&&F.options,Q=v.y,P=A.y,R=d.hasLoaded,S=R?"animate":"attr",O=0,N=0;if(!1!==q.enabled){c.rendered||(c.group=I=e.g("range-selector-group").attr({zIndex:7}).add(),c.buttonGroup=z=e.g("range-selector-buttons").add(I),c.zoomText=e.text(t.rangeSelectorZoom,0, +15).add(z),d.styledMode||(c.zoomText.css(q.labelStyle),u["stroke-width"]=h(u["stroke-width"],0)),c.buttonOptions.forEach(function(a,b){n[b]=e.button(a.text,0,0,function(g){var d=a.events&&a.events.click,e;d&&(e=d.call(a,g));!1!==e&&c.clickButton(b);c.isActive=!0},u,y&&y.hover,y&&y.select,y&&y.disabled).attr({"text-align":"center"}).add(z)}),!1!==w&&(c.div=m=l("div",null,{position:"relative",height:0,zIndex:r}),g.parentNode.insertBefore(m,g),c.inputGroup=m=e.g("input-group").add(I),m.offset=0,c.drawInput("min"), +c.drawInput("max")));c.zoomText[S]({x:h(x+v.x,x)});var T=h(x+v.x,x)+c.zoomText.getBBox().width+5;c.buttonOptions.forEach(function(a,b){n[b][S]({x:T});T+=n[b].width+h(q.buttonSpacing,5)});x=d.plotLeft-d.spacing[3];c.updateButtonStates();k&&this.titleCollision(d)&&"top"===G&&"right"===v.align&&v.y+z.getBBox().height-12<(k.y||0)+k.height&&(O=-40);g=v.x-d.spacing[3];"right"===v.align?g+=O-x:"center"===v.align&&(g-=x/2);z.align({y:v.y,width:z.getBBox().width,align:v.align,x:g},!0,d.spacingBox);c.group.placed= +R;c.buttonGroup.placed=R;!1!==w&&(O=k&&this.titleCollision(d)&&"top"===G&&"right"===A.align&&A.y-m.getBBox().height-12<(k.y||0)+k.height+d.spacing[0]?-40:0,"left"===A.align?g=x:"right"===A.align&&(g=-Math.max(d.axisOffset[1],-O)),m.align({y:A.y,width:m.getBBox().width,align:A.align,x:A.x+g-2},!0,d.spacingBox),k=m.alignAttr.translateX+m.alignOptions.x-O+m.getBBox().x+2,g=m.alignOptions.width,t=z.alignAttr.translateX+z.getBBox().x,x=z.getBBox().width+20,(A.align===v.align||t+x>k&&k+g>t&&Q=-O?0:-O),translateY:m.alignAttr.translateY+z.getBBox().height+10}),c.setInputValue("min",a),c.setInputValue("max",b),c.inputGroup.placed=R);c.group.align({verticalAlign:G},!0,d.spacingBox);a=c.group.getBBox().height+20;b=c.group.alignAttr.translateY;"bottom"===G&&(F=J&&"bottom"===J.verticalAlign&&J.enabled&&!J.floating?F.legendHeight+h(J.margin,10):0,a=a+F-20,N=b-a-(f?0:q.y)-(d.titleOffset?d.titleOffset[2]:0)-10);if("top"===G)f&&(N=0),d.titleOffset&& +d.titleOffset[0]&&(N=d.titleOffset[0]),N+=d.margin[0]-d.spacing[0]||0;else if("middle"===G)if(P===Q)N=0>P?b+void 0:b;else if(P||Q)N=0>P||0>Q?N-Math.min(P,Q):b-a+NaN;c.group.translate(q.x,q.y+Math.floor(N));!1!==w&&(c.minInput.style.marginTop=c.group.translateY+"px",c.maxInput.style.marginTop=c.group.translateY+"px");c.rendered=!0}};c.prototype.getHeight=function(){var a=this.options,b=this.group,c=a.y,d=a.buttonPosition.y,e=a.inputPosition.y;if(a.height)return a.height;a=b?b.getBBox(!0).height+13+ +c:0;b=Math.min(e,d);if(0>e&&0>d||0m&&(n?b=e-k:e=b+k);C(b)&&C(e)||(b=e=void 0);return{min:b,max:e}};return b}();return function(){function b(){}b.compose=function(b){b.keepProps.push("navigatorAxis");x(b,"init",function(){this.navigatorAxis||(this.navigatorAxis=new l(this))});x(b,"zoom",function(b){var e=this.chart.options, +m=e.navigator,l=this.navigatorAxis,k=e.chart.pinchType,f=e.rangeSelector;e=e.chart.zoomType;this.isXAxis&&(m&&m.enabled||f&&f.enabled)&&("y"===e?b.zoomed=!1:(!v&&"xy"===e||v&&"xy"===k)&&this.options.range&&(m=l.previousZoom,y(b.newMin)?l.previousZoom=[this.min,this.max]:m&&(b.newMin=m[0],b.newMax=m[1],l.previousZoom=void 0)));"undefined"!==typeof b.zoomed&&b.preventDefault()})};b.AdditionsClass=l;return b}()});J(e,"Core/Navigator.js",[e["Core/Axis/Axis.js"],e["Core/Chart/Chart.js"],e["Core/Color.js"], +e["Core/Globals.js"],e["Core/Axis/NavigatorAxis.js"],e["Core/Options.js"],e["Core/Scrollbar.js"],e["Core/Utilities.js"]],function(e,n,v,x,w,y,C,u){v=v.parse;var l=y.defaultOptions,b=u.addEvent,m=u.clamp,q=u.correctFloat,z=u.defined,F=u.destroyObjectProperties,G=u.erase,k=u.extend,f=u.find,a=u.isArray,h=u.isNumber,d=u.merge,r=u.pick,c=u.removeEvent,A=u.splat,t=x.hasTouch,I=x.isTouchDevice;y=x.Series;var D=function(a){for(var b=[],c=1;cw&&(this.grabbedLeft?c=p.toPixels(b-w-k,!0):this.grabbedRight&&(e=p.toPixels(a+w+k,!0)));this.zoomedMax= +m(Math.max(c,e),0,t);this.zoomedMin=m(this.fixedWidth?this.zoomedMax-this.fixedWidth:Math.min(c,e),0,t);this.range=this.zoomedMax-this.zoomedMin;t=Math.round(this.zoomedMax);c=Math.round(this.zoomedMin);n&&(this.navigatorGroup.attr({visibility:"visible"}),u=u&&!this.hasDragged?"animate":"attr",this.drawMasks(c,t,v,u),this.drawOutline(c,t,v,u),this.navigatorOptions.handles.enabled&&(this.drawHandle(c,0,v,u),this.drawHandle(t,1,v,u)));this.scrollbar&&(v?(v=this.top-g,l=this.left-g+(n||!l.opposite?0: +(l.titleOffset||0)+l.axisTitleMargin),g=f+2*g):(v=this.top+(n?this.height:-g),l=this.left-g),this.scrollbar.position(l,v,d,g),this.scrollbar.setRange(this.zoomedMin/(f||1),this.zoomedMax/(f||1)));this.rendered=!0}};n.prototype.addMouseEvents=function(){var a=this,c=a.chart,e=c.container,d=[],f,h;a.mouseMoveHandler=f=function(b){a.onMouseMove(b)};a.mouseUpHandler=h=function(b){a.onMouseUp(b)};d=a.getPartsEvents("mousedown");d.push(b(c.renderTo,"mousemove",f),b(e.ownerDocument,"mouseup",h));t&&(d.push(b(c.renderTo, +"touchmove",f),b(e.ownerDocument,"touchend",h)),d.concat(a.getPartsEvents("touchstart")));a.eventsToUnbind=d;a.series&&a.series[0]&&d.push(b(a.series[0].xAxis,"foundExtremes",function(){c.navigator.modifyNavigatorAxisExtremes()}))};n.prototype.getPartsEvents=function(a){var c=this,e=[];["shades","handles"].forEach(function(d){c[d].forEach(function(g,f){e.push(b(g.element,a,function(a){c[d+"Mousedown"](a,f)}))})});return e};n.prototype.shadesMousedown=function(a,b){a=this.chart.pointer.normalize(a); +var c=this.chart,e=this.xAxis,d=this.zoomedMin,g=this.left,f=this.size,h=this.range,p=a.chartX;c.inverted&&(p=a.chartY,g=this.top);if(1===b)this.grabbedCenter=p,this.fixedWidth=h,this.dragOffset=p-d;else{a=p-g-h/2;if(0===b)a=Math.max(0,a);else if(2===b&&a+h>=f)if(a=f-h,this.reversedExtremes){a-=h;var k=this.getUnionExtremes().dataMin}else var m=this.getUnionExtremes().dataMax;a!==d&&(this.fixedWidth=h,b=e.navigatorAxis.toFixedRange(a,a+h,k,m),z(b.min)&&c.xAxis[0].setExtremes(Math.min(b.min,b.max), +Math.max(b.min,b.max),!0,null,{trigger:"navigator"}))}};n.prototype.handlesMousedown=function(a,b){this.chart.pointer.normalize(a);a=this.chart;var c=a.xAxis[0],d=this.reversedExtremes;0===b?(this.grabbedLeft=!0,this.otherHandlePos=this.zoomedMax,this.fixedExtreme=d?c.min:c.max):(this.grabbedRight=!0,this.otherHandlePos=this.zoomedMin,this.fixedExtreme=d?c.max:c.min);a.fixedRange=null};n.prototype.onMouseMove=function(a){var b=this,c=b.chart,d=b.left,e=b.navigatorSize,g=b.range,f=b.dragOffset,h=c.inverted; +a.touches&&0===a.touches[0].pageX||(a=c.pointer.normalize(a),c=a.chartX,h&&(d=b.top,c=a.chartY),b.grabbedLeft?(b.hasDragged=!0,b.render(0,0,c-d,b.otherHandlePos)):b.grabbedRight?(b.hasDragged=!0,b.render(0,0,b.otherHandlePos,c-d)):b.grabbedCenter&&(b.hasDragged=!0,ce+f-g&&(c=e+f-g),b.render(0,0,c-f,c-f+g)),b.hasDragged&&b.scrollbar&&r(b.scrollbar.options.liveRedraw,x.svg&&!I&&!this.chart.isBoosting)&&(a.DOMType=a.type,setTimeout(function(){b.onMouseUp(a)},0)))};n.prototype.onMouseUp=function(a){var b= +this.chart,c=this.xAxis,d=this.scrollbar,e=a.DOMEvent||a,g=b.inverted,f=this.rendered&&!this.hasDragged?"animate":"attr";if(this.hasDragged&&(!d||!d.hasDragged)||"scrollbar"===a.trigger){d=this.getUnionExtremes();if(this.zoomedMin===this.otherHandlePos)var k=this.fixedExtreme;else if(this.zoomedMax===this.otherHandlePos)var m=this.fixedExtreme;this.zoomedMax===this.size&&(m=this.reversedExtremes?d.dataMin:d.dataMax);0===this.zoomedMin&&(k=this.reversedExtremes?d.dataMax:d.dataMin);c=c.navigatorAxis.toFixedRange(this.zoomedMin, +this.zoomedMax,k,m);z(c.min)&&b.xAxis[0].setExtremes(Math.min(c.min,c.max),Math.max(c.min,c.max),!0,this.hasDragged?!1:null,{trigger:"navigator",triggerOp:"navigator-drag",DOMEvent:e})}"mousemove"!==a.DOMType&&"touchmove"!==a.DOMType&&(this.grabbedLeft=this.grabbedRight=this.grabbedCenter=this.fixedWidth=this.fixedExtreme=this.otherHandlePos=this.hasDragged=this.dragOffset=null);this.navigatorEnabled&&h(this.zoomedMin)&&h(this.zoomedMax)&&(b=Math.round(this.zoomedMin),a=Math.round(this.zoomedMax), +this.shades&&this.drawMasks(b,a,g,f),this.outline&&this.drawOutline(b,a,g,f),this.navigatorOptions.handles.enabled&&Object.keys(this.handles).length===this.handles.length&&(this.drawHandle(b,0,g,f),this.drawHandle(a,1,g,f)))};n.prototype.removeEvents=function(){this.eventsToUnbind&&(this.eventsToUnbind.forEach(function(a){a()}),this.eventsToUnbind=void 0);this.removeBaseSeriesEvents()};n.prototype.removeBaseSeriesEvents=function(){var a=this.baseSeries||[];this.navigatorEnabled&&a[0]&&(!1!==this.navigatorOptions.adaptToUpdatedData&& +a.forEach(function(a){c(a,"updatedData",this.updatedDataHandler)},this),a[0].xAxis&&c(a[0].xAxis,"foundExtremes",this.modifyBaseAxisExtremes))};n.prototype.init=function(a){var c=a.options,g=c.navigator,f=g.enabled,h=c.scrollbar,k=h.enabled;c=f?g.height:0;var m=k?h.height:0;this.handles=[];this.shades=[];this.chart=a;this.setBaseSeries();this.height=c;this.scrollbarHeight=m;this.scrollbarEnabled=k;this.navigatorEnabled=f;this.navigatorOptions=g;this.scrollbarOptions=h;this.outlineHeight=c+m;this.opposite= +r(g.opposite,!(f||!a.inverted));var l=this;f=l.baseSeries;h=a.xAxis.length;k=a.yAxis.length;var n=f&&f[0]&&f[0].xAxis||a.xAxis[0]||{options:{}};a.isDirtyBox=!0;l.navigatorEnabled?(l.xAxis=new e(a,d({breaks:n.options.breaks,ordinal:n.options.ordinal},g.xAxis,{id:"navigator-x-axis",yAxis:"navigator-y-axis",isX:!0,type:"datetime",index:h,isInternal:!0,offset:0,keepOrdinalPadding:!0,startOnTick:!1,endOnTick:!1,minPadding:0,maxPadding:0,zoomEnabled:!1},a.inverted?{offsets:[m,0,-m,0],width:c}:{offsets:[0, +-m,0,m],height:c})),l.yAxis=new e(a,d(g.yAxis,{id:"navigator-y-axis",alignTicks:!1,offset:0,index:k,isInternal:!0,zoomEnabled:!1},a.inverted?{width:c}:{height:c})),f||g.series.data?l.updateNavigatorSeries(!1):0===a.series.length&&(l.unbindRedraw=b(a,"beforeRedraw",function(){0h.indexOf(b)?(b&&(c(b,"updatedData",f.updatedDataHandler),delete b.navigatorSeries),a.chart&&a.destroy(), +!1):!0});h&&h.length&&h.forEach(function(b){var c=b.navigatorSeries,v=k({color:b.color,visible:b.visible},a(n)?l.navigator.series:n);c&&!1===f.navigatorOptions.adaptToUpdatedData||(t.name="Navigator "+h.length,m=b.options||{},q=m.navigatorOptions||{},p=d(m,t,v,q),p.pointRange=r(v.pointRange,q.pointRange,l.plotOptions[p.type||"line"].pointRange),v=q.data||v.data,f.hasNavigatorData=f.hasNavigatorData||!!v,p.data=v||m.data&&m.data.slice(0),c&&c.options?c.update(p,e):(b.navigatorSeries=g.initSeries(p), +b.navigatorSeries.baseSeries=b,u.push(b.navigatorSeries)))});if(n.data&&(!h||!h.length)||a(n))f.hasNavigatorData=!1,n=A(n),n.forEach(function(a,b){t.name="Navigator "+(u.length+1);p=d(l.navigator.series,{color:g.series[b]&&!g.series[b].options.isInternal&&g.series[b].color||g.options.colors[b]||g.options.colors[0]},t,a);p.data=a.data;p.data&&(f.hasNavigatorData=!0,u.push(g.initSeries(p)))});b&&this.addBaseSeriesEvents()};n.prototype.addBaseSeriesEvents=function(){var a=this,c=a.baseSeries||[];c[0]&& +c[0].xAxis&&b(c[0].xAxis,"foundExtremes",this.modifyBaseAxisExtremes);c.forEach(function(c){b(c,"show",function(){this.navigatorSeries&&this.navigatorSeries.setVisible(!0,!1)});b(c,"hide",function(){this.navigatorSeries&&this.navigatorSeries.setVisible(!1,!1)});!1!==this.navigatorOptions.adaptToUpdatedData&&c.xAxis&&b(c,"updatedData",this.updatedDataHandler);b(c,"remove",function(){this.navigatorSeries&&(G(a.series,this.navigatorSeries),z(this.navigatorSeries.options)&&this.navigatorSeries.remove(!1), +delete this.navigatorSeries)})},this)};n.prototype.getBaseSeriesMin=function(a){return this.baseSeries.reduce(function(a,b){return Math.min(a,b.xData?b.xData[0]:a)},a)};n.prototype.modifyNavigatorAxisExtremes=function(){var a=this.xAxis,b;"undefined"!==typeof a.getExtremes&&(!(b=this.getUnionExtremes(!0))||b.dataMin===a.min&&b.dataMax===a.max||(a.min=b.dataMin,a.max=b.dataMax))};n.prototype.modifyBaseAxisExtremes=function(){var a=this.chart.navigator,b=this.getExtremes(),c=b.dataMin,d=b.dataMax;b= +b.max-b.min;var e=a.stickToMin,f=a.stickToMax,k=r(this.options.overscroll,0),l=a.series&&a.series[0],m=!!this.setExtremes;if(!this.eventArgs||"rangeSelectorButton"!==this.eventArgs.trigger){if(e){var n=c;var q=n+b}f&&(q=d+k,e||(n=Math.max(c,q-b,a.getBaseSeriesMin(l&&l.xData?l.xData[0]:-Number.MAX_VALUE))));m&&(e||f)&&h(n)&&(this.min=this.userMin=n,this.max=this.userMax=q)}a.stickToMin=a.stickToMax=null};n.prototype.updatedDataHandler=function(){var a=this.chart.navigator,b=this.navigatorSeries,c= +a.getBaseSeriesMin(this.xData[0]);a.stickToMax=a.reversedExtremes?0===Math.round(a.zoomedMin):Math.round(a.zoomedMax)>=Math.round(a.size);a.stickToMin=h(this.xAxis.min)&&this.xAxis.min<=c&&(!this.chart.fixedRange||!a.stickToMax);b&&!a.hasNavigatorData&&(b.options.pointStart=this.xData[0],b.setData(this.options.data,!1,null,!1))};n.prototype.addChartEvents=function(){this.eventsToUnbind||(this.eventsToUnbind=[]);this.eventsToUnbind.push(b(this.chart,"redraw",function(){var a=this.navigator,b=a&&(a.baseSeries&& +a.baseSeries[0]&&a.baseSeries[0].xAxis||this.xAxis[0]);b&&a.render(b.min,b.max)}),b(this.chart,"getMargins",function(){var a=this.navigator,b=a.opposite?"plotTop":"marginBottom";this.inverted&&(b=a.opposite?"marginRight":"plotLeft");this[b]=(this[b]||0)+(a.navigatorEnabled||!this.inverted?a.outlineHeight:0)+a.navigatorOptions.margin}))};n.prototype.destroy=function(){this.removeEvents();this.xAxis&&(G(this.chart.xAxis,this.xAxis),G(this.chart.axes,this.xAxis));this.yAxis&&(G(this.chart.yAxis,this.yAxis), +G(this.chart.axes,this.yAxis));(this.series||[]).forEach(function(a){a.destroy&&a.destroy()});"series xAxis yAxis shades outline scrollbarTrack scrollbarRifles scrollbarGroup scrollbar navigatorGroup rendered".split(" ").forEach(function(a){this[a]&&this[a].destroy&&this[a].destroy();this[a]=null},this);[this.handles].forEach(function(a){F(a)},this)};return n}();x.Navigator||(x.Navigator=B,w.compose(e),b(n,"beforeShowResetZoom",function(){var a=this.options,b=a.navigator,c=a.rangeSelector;if((b&& +b.enabled||c&&c.enabled)&&(!I&&"x"===a.chart.zoomType||I&&"x"===a.chart.pinchType))return!1}),b(n,"beforeRender",function(){var a=this.options;if(a.navigator.enabled||a.scrollbar.enabled)this.scroller=this.navigator=new B(this)}),b(n,"afterSetChartSize",function(){var a=this.legend,b=this.navigator;if(b){var c=a&&a.options;var d=b.xAxis;var e=b.yAxis;var f=b.scrollbarHeight;this.inverted?(b.left=b.opposite?this.chartWidth-f-b.height:this.spacing[3]+f,b.top=this.plotTop+f):(b.left=this.plotLeft+f, +b.top=b.navigatorOptions.top||this.chartHeight-b.height-f-this.spacing[2]-(this.rangeSelector&&this.extraBottomMargin?this.rangeSelector.getHeight():0)-(c&&"bottom"===c.verticalAlign&&"proximate"!==c.layout&&c.enabled&&!c.floating?a.legendHeight+r(c.margin,10):0)-(this.titleOffset?this.titleOffset[2]:0));d&&e&&(this.inverted?d.options.left=e.options.left=b.left:d.options.top=e.options.top=b.top,d.setAxisSize(),e.setAxisSize())}}),b(n,"update",function(a){var b=a.options.navigator||{},c=a.options.scrollbar|| +{};this.navigator||this.scroller||!b.enabled&&!c.enabled||(d(!0,this.options.navigator,b),d(!0,this.options.scrollbar,c),delete a.options.navigator,delete a.options.scrollbar)}),b(n,"afterUpdate",function(a){this.navigator||this.scroller||!this.options.navigator.enabled&&!this.options.scrollbar.enabled||(this.scroller=this.navigator=new B(this),r(a.redraw,!0)&&this.redraw(a.animation))}),b(n,"afterAddSeries",function(){this.navigator&&this.navigator.setBaseSeries(null,!1)}),b(y,"afterUpdate",function(){this.chart.navigator&& +!this.options.isInternal&&this.chart.navigator.setBaseSeries(null,!1)}),n.prototype.callbacks.push(function(a){var b=a.navigator;b&&a.xAxis[0]&&(a=a.xAxis[0].getExtremes(),b.render(a.min,a.max))}));x.Navigator=B;return x.Navigator});J(e,"masters/modules/gantt.src.js",[],function(){})}); +//# sourceMappingURL=gantt.js.map \ No newline at end of file diff --git a/highcharts/modules/gantt.js.map b/highcharts/modules/gantt.js.map new file mode 100644 index 0000000..b1100cd --- /dev/null +++ b/highcharts/modules/gantt.js.map @@ -0,0 +1 @@ +{"version":3,"file":"gantt.js.map","lineCount":197,"mappings":"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","sources":["gantt.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","U","extend","isNumber","pick","getListOfParents","data","ids","listOfParents","reduce","prev","curr","parent","push","Object","keys","parents","forEach","list","children","indexOf","child","getNode","id","level","mapOfIdToChildren","options","descendants","height","after","before","node","depth","start","end","map","childStart","childEnd","milestone","Math","max","Tree","getTree","d","addEvent","defined","isObject","wrap","TreeGridTick","onInit","tick","treeGrid","Additions","renderLabelIcon","params","isNew","labelIcon","renderer","labelBox","xy","width","x","padding","y","rotation","collapsed","shouldRender","show","icon","symbols","type","addClass","add","group","attr","styledMode","color","css","cursor","stroke","lineColor","strokeWidth","lineWidth","translateX","translateY","wrapGetLabelPosition","proceed","label","horiz","labelOptions","tickmarkOffset","index","step","lbOptions","labels","pos","axis","isTreeGrid","result","symbolOptions","symbol","indentation","mapOfPosToGridNode","wrapRenderLabel","tickPositions","chart","element","Array","prototype","slice","call","arguments","isCollapsed","styles","parentGroup","removeClassName","prefixClassName","removeClass","object","attachedTreeGridEvents","textDecoration","style","toggleCollapse","applied","compose","TickClass","collapse","TickClass.prototype.collapse","redraw","expand","TickClass.prototype.expand","TickClass.prototype.toggleCollapse","Additions.prototype.collapse","brokenAxis","breaks","setBreaks","Additions.prototype.expand","Additions.prototype.toggleCollapse","Color","isArray","merge","getColor","mapOptionsToLevel","parentColor","parentColorIndex","series","colors","siblings","points","chartOptionsChart","point","i","getColorByPoint","colorByPoint","colorIndexByPoint","length","colorCount","colorVariation","key","parse","brighten","to","get","colorIndex","getLevelOptions","from","levels","converted","defaults","item","levelIsConstant","setTreeValues","tree","idRoot","nodeRoot","mapIdToNode","optionsPoint","childrenTotal","levelDynamic","name","visible","newOptions","val","value","isLeaf","updateRootId","rootId","rootNode","userOptions","Axis","H","O","Tick","dateFormat","erase","find","timeUnits","Chart","applyGridOptions","align","categories","showLastLabel","labelRotation","getMaxLabelDimensions","Axis.prototype.getMaxLabelDimensions","ticks","dimensions","tickWidth","tickHeight","getBBox","textStr","round","dateFormats","W","H.dateFormats.W","timestamp","Date","firstDay","thursday","valueOf","set","firstThursday","toString","floor","E","H.dateFormats.E","charAt","axes","grid","columns","column","setAxisSize","setAxisTranslation","e","reversed","gridOptions","labelOpts","side","GridAxis","Side","tickPos","nextTickPos","tickSize","crispCorr","enabled","bottom","top","offset","chartHeight","len","translate","left","chartWidth","right","slotWidth","lblMetrics","fontMetrics","fontSize","labelHeight","useHTML","b","lines","h","f","GridAxisAdditions","isOuterAxis","GridAxisAdditions.prototype.isOuterAxis","columnIndex","linkedParent","parentAxis","thisIndex","lastIndex","coll","otherAxis","isInternal","GridAxis.compose","AxisClass","keepProps","wrapUnsquish","onAfterGetOffset","onAfterGetTitlePosition","onAfterInit","onAfterRender","onAfterSetAxisTranslation","onAfterSetOptions","onAfterSetOptions2","onAfterSetScale","onAfterTickSize","onTrimTicks","onDestroy","GridAxis.onAfterGetOffset","getOffset","GridAxis.onAfterGetTitlePosition","title","axisTitle","axisHeight","axisLeft","opposite","_a","axisTitleOptions","axisTop","axisWidth","titleWidth","xOption","yOption","titleMargin","margin","titleFontSize","offAxis","titlePosition","GridAxis.onAfterInit","isLinked","isFirst","isLast","p","isXAxis","columnOptions","linkedTo","scrollbar","isColumn","GridAxis.onAfterRender","maxLabelDimensions","rightWall","destroy","axisLine","linePath","getLinePath","startPoint","endPoint","distance","tickLength","axisLineExtra","animate","zIndex","axisGroup","showAxis","render","GridAxis.onAfterSetAxisTranslation","tickInfo","info","userLabels","pointRange","dateTimeLabelFormats","unitName","range","count","GridAxis.onAfterSetOptions","gridAxisOptions","className","hour","day","week","month","borderWidth","text","reserveSpace","units","tickPixelInterval","tickPositioner","tickInterval","gridAxisOptions.tickPositioner","min","parentInfo","unitIdx","unitRange","getTimeTicks","startOfWeek","minPadding","maxPadding","GridAxis.onAfterSetOptions2","GridAxis.onAfterSetScale","setScale","GridAxis.onAfterTickSize","defaultLeftAxisOptions","_b","labelPadding","abs","cellHeight","GridAxis.onDestroy","keepEvents","GridAxis.onInit","borderColor","tickColor","GridAxis.onTrimTicks","categoryAxis","firstPos","lastPos","startOnTick","endOnTick","GridAxis.wrapUnsquish","StackItem","fireEvent","Series","BrokenAxisAdditions","hasBreaks","isInBreak","BrokenAxisAdditions.isInBreak","brk","repeat","Infinity","test","inclusive","ret","lin2Val","BrokenAxisAdditions.lin2Val","breakArray","nval","val2Lin","BrokenAxisAdditions.val2Lin","findBreakAt","BrokenAxisAdditions.prototype.findBreakAt","isInAnyBreak","BrokenAxisAdditions.prototype.isInAnyBreak","testKeep","keep","inbrk","showPoints","BrokenAxisAdditions.prototype.setBreaks","isDirty","forceRedraw","val2lin","lin2val","ordinal","setExtremes","axis.setExtremes","newMin","newMax","animation","eventArguments","axisBreak","axis.setAxisTranslation","saveOld","unitLength","breakArrayT","userMin","userMax","pointRangePadding","move","size","breakSize","sort","a","inBrk","staticScale","transA","minPixelPadding","minPointOffset","BrokenAxis","BrokenAxis.compose","SeriesClass","seriesProto","drawBreaks","seriesProto.drawBreaks","threshold","eventName","brokenAxis_1","toUpperCase","gappedPath","seriesProto.gappedPath","currentDataGrouping","groupingSize","gapSize","yAxis","stack","next","gapUnit","basePointRange","current","xRange","splice","isNull","stacking","stacks","stackKey","stackLabels","total","getGraphPath","newPositions","connectNulls","xAxis","isPointInBreak","drawPointsWrapped","pointArrayMap","mixinTreeSeries","isString","TreeGridAxis","getBreakFromNode","collapseStart","collapseEnd","getTreeGridFromData","uniqueNames","numberOfSeries","collapsedNodes","mapOfIdToNode","posIterator","uniqueNamesEnabled","treeParams","gridNode","parentNode","parentGridNode","hasSameName","nodes","updateYValuesAndTickPos","setValues","diff","seriesIndex","onBeforeRender","target","filter","some","hasRendered","isDirtyData","arr","s","hasNames","setData","wrapGenerateTick","levelOptions","parameters","category","addLabel","wrapGetMaxLabelDimensions","retVal","treeDepth","wrapInit","concat","n","fontWeight","wrapSetTickInterval","dataMin","dataMax","getTickPositions","Additions.prototype.getTickPositions","Additions.prototype.isCollapsed","utils","PlotLineOrBand","defaultConfig","currentDateIndicator","format","formatter","cdiOptions","plotLines","getLabelText","defaultMethod","defaultLabelOptions","chartOptions","scrollablePlotArea","minHeight","adjustHeight","Chart.prototype.adjustHeight","redrawTrigger","initiatedScale","plotHeight","setSize","clipRect","sharedClipKey","SVGRenderer","arrow","SVGRenderer.prototype.symbols.arrow","w","Point","getPointBB","shapeArgs","xMin","xMax","yMin","yMax","bb","graphic","plotX","plotY","error","objectEach","deg2rad","defaultOptions","connectors","marker","verticalAlign","inside","startMarker","endMarker","Connection","toPoint","pathfinder","graphics","fromPoint","init","Connection.prototype.init","renderPath","Connection.prototype.renderPath","attribs","forExport","pathGraphic","connection","g","seriesGroup","plotLeft","plotTop","opacity","anim","addMarker","Connection.prototype.addMarker","anchor","getPathfinderAnchorPoint","segment","pathVector","radians","getRadiansToVector","markerVector","getMarkerVector","radius","box","rotationOriginX","rotationOriginY","fill","getPath","Connection.prototype.getPath","algorithm","algorithms","chartObstacles","obstacles","requiresObstacles","getChartObstacles","algorithmMargin","chartObstacleMetrics","getObstacleMetrics","lineObstacles","obstacleMetrics","hardBounds","plotWidth","obstacleOptions","startDirectionX","getAlgorithmStartDirection","Connection.prototype.render","dashStyle","dashstyle","ceil","pathResult","Connection.prototype.destroy","markerOptions","v1","v2","atan2","markerRadius","twoPI","PI","rectWidth","rectHeight","rAtan","leftOrRightRegion","rectHalfWidth","rectHalfHeight","rectHorizontalCenter","rectVerticalCenter","markerPoint","xFactor","yFactor","theta","tanTheta","tan","cos","sin","findLastObstacleBefore","startIx","cmp","findObstacleFromPoint","obstacle","pathFromSegments","segments","limitObstacleToBounds","bounds","simpleConnect","copyFromPoint","fromKey","toKey","getMeOut","direction","useMax","dir","startObstacleIx","endObstacleIx","endObstacle","waypoint","endSegment","startObstacle","prevWaypoint","waypoint2","fastAvoid","pivotPoint","directionIsX","searchDirection","firstPoint","lastPoint","lowestPoint","highestPoint","getDodgeDirection","dirIsX","softBounds","soft","hard","toPointMax","toPointMin","maxOutOfSoftBounds","minOutOfSoftBounds","maxOutOfHardBounds","minOutOfHardBounds","minDistance","maxDistance","minPivot","maxPivot","clearPathTo","obstacleMargin","softMinX","softMaxX","softMinY","softMaxY","envelopingObstacle","waypointUseMax","envelopWaypoint","secondEnvelopingObstacle","forceObstacleBreak","pivot","extractFromObstacle","goalPoint","endSegments","metrics","maxWidth","maxHeight","extractedEndPoint","reverse","straight","pathfinderAlgorithms","calculateObstacleMargin","j","obstacleDistance","distances","bbMargin","yOverlap","xOverlap","xDistance","yDistance","warnLegacy","acc","splat","Pathfinder","connections","Pathfinder.prototype.init","update","Pathfinder.prototype.update","deferRender","oldConnections","connects","connect","isInside","k","found","lenOld","lenNew","renderConnections","Pathfinder.prototype.renderConnections","pathfinderRemoveRenderEvent","Pathfinder.prototype.getChartObstacles","calculatedMargin","sLen","pLen","Pathfinder.prototype.getObstacleMetrics","Pathfinder.prototype.getAlgorithmStartDirection","yCenter","undef","callbacks","clamp","correctFloat","seriesType","columnType","seriesTypes","dataLabels","amount","partialFill","tooltip","headerFormat","pointFormat","borderRadius","parallelArrays","requireSorting","line","cropShoulder","getExtremesFromAll","autoIncrement","noop","buildKDTree","getColumnMetrics","swapAxes","cropData","xData","yData","crop","x2Data","findPointIndex","cropped","cropStart","pointIndex","x2","touched","translatePoint","columnMetrics","minPointLength","posX","plotX2","inverted","crisper","yOffset","pointHeight","widthDifference","pointWidth","pointPlacement","r","dlLeft","dlRight","dlWidth","dlBox","centerX","tooltipPos","xIndex","yIndex","tooltipYOffset","partShapeArgs","clipRectWidth","clipRectArgs","drawPoint","verb","seriesOpts","shapeType","pfOptions","cutOff","pointState","state","stateOpts","states","pointStateVerb","pointAttr","pointAttribs","rect","getClassName","partRect","partialClipRect","clip","shadow","drawPoints","getAnimationVerb","pointCount","animationLimit","resolveColor","setState","getLabelConfig","cfg","yCats","yCategory","tooltipDateKeys","isValid","axisSeries","modMax","Number","MAX_VALUE","xrange","grouping","pointFormatter","formats","tooltipOptions","ttOptions","xDateFormat","tooltipFormatter","getDateFormat","closestPointRange","keyboardMoveVertical","selected","diamondShape","diamond","setGanttPointAliases","addIfExists","prop","completed","dependency","pointClass","applyOptions","gantt","getOptions","ganttChart","H.ganttChart","renderTo","callback","hasRenderToArg","nodeName","seriesOptions","defaultLinkedTo","xAxisOptions","yAxisOptions","legend","navigator","isGantt","ScrollbarAxis","ScrollbarAxis.compose","ScrollbarClass","vertical","axisMin","axisMax","unitedMin","unitedMax","liveRedraw","svg","isTouchDevice","isBoosting","DOMType","setRange","scrollMin","scrollMax","axisTitleMargin","titleOffset","scrollbarsOffsets","axisMargin","position","offsetsIndex","isNaN","axisOffset","destroyObjectProperties","removeEvent","hasTouch","swapXY","H.swapXY","seg","temp","Scrollbar","_events","chartY","chartX","scrollbarButtons","scrollbarGroup","scrollbarLeft","scrollbarRifles","scrollbarStrokeWidth","scrollbarTop","track","trackBorderWidth","addEvents","Scrollbar.prototype.addEvents","buttonsOrder","buttons","bar","mouseDownHandler","bind","mouseMoveHandler","mouseUpHandler","buttonToMinClick","buttonToMaxClick","trackClick","ownerDocument","Scrollbar.prototype.buttonToMaxClick","scroller","updatePosition","trigger","DOMEvent","Scrollbar.prototype.buttonToMinClick","cursorToScrollbarPosition","Scrollbar.prototype.cursorToScrollbarPosition","normalizedEvent","minWidthDifference","minWidth","calculatedWidth","xOffset","barWidth","Scrollbar.prototype.destroy","removeEvents","drawScrollbarButton","Scrollbar.prototype.drawScrollbarButton","tempElem","buttonBorderColor","buttonBorderWidth","buttonBackgroundColor","crisp","buttonBorderRadius","buttonArrowColor","Scrollbar.prototype.init","Scrollbar.prototype.mouseDownHandler","pointer","normalize","mousePosition","initPositions","grabbedCenter","Scrollbar.prototype.mouseMoveHandler","touches","chartPosition","scrollPosition","change","hasDragged","Scrollbar.prototype.mouseUpHandler","Scrollbar.prototype.position","method","rendered","Scrollbar.prototype.removeEvents","Scrollbar.prototype.render","trackBorderRadius","trackBackgroundColor","trackBorderColor","barBorderRadius","barBackgroundColor","barBorderColor","barBorderWidth","rifleColor","Scrollbar.prototype.setRange","fullWidth","newSize","fromPX","newPos","newRiflesPos","hide","showFull","Scrollbar.prototype.trackClick","Scrollbar.prototype.update","Scrollbar.prototype.updatePosition","SVGElement","createElement","discardElement","pInt","rangeSelector","buttonTheme","floating","inputPosition","buttonPosition","labelStyle","lang","rangeSelectorZoom","rangeSelectorFrom","rangeSelectorTo","RangeSelector","buttonOptions","defaultButtons","clickButton","RangeSelector.prototype.clickButton","rangeOptions","baseAxis","unionExtremes","getUnionExtremes","_range","rangeMin","dataGrouping","fixedRange","forcedDataGrouping","setDataGrouping","frozenStates","preserveDataGrouping","ctx","minFromRange","MIN_VALUE","ytdExtremes","getYTDExtremes","time","useUTC","deferredYTDClick","_offsetMin","_offsetMax","setSelected","rangeSelectorButton","baseXAxisOptions","rangeSetting","minSetting","resetMinAndRange","RangeSelector.prototype.setSelected","RangeSelector.prototype.init","selectedOption","blurInputs","minInput","maxInput","blur","unMouseDown","container","unResize","computeButtonRange","updateButtonStates","RangeSelector.prototype.updateButtonStates","actualRange","hasNoData","hasVisibleSeries","ytdMin","ytdMax","selectedExists","allButtonsEnabled","button","offsetRange","isSelected","isTooGreatRange","isTooSmallRange","minRange","isYTDButNotSelected","isAllButAlreadyShowingAll","isSameRange","year","disable","select","RangeSelector.prototype.computeButtonRange","fixedTimes","millisecond","second","minute","offsetMin","offsetMax","setInputValue","RangeSelector.prototype.setInputValue","inputTime","input","previousValue","HCTime","inputEditDateFormat","inputDateFormat","showInput","RangeSelector.prototype.showInput","inputGroup","dateBox","border","hideInput","RangeSelector.prototype.hideInput","defaultInputDateParser","RangeSelector.prototype.defaultInputDateParser","inputDate","date","isSafari","split","join","getTimezoneOffset","drawInput","RangeSelector.prototype.drawInput","updateExtremes","inputValue","chartAxis","dataAxis","inputDateParser","UTC","isMin","chartStyle","div","inputBoxWidth","inputBoxHeight","on","focus","inputBoxBorderColor","inputStyle","textAlign","fontFamily","onfocus","input.onfocus","onblur","input.onblur","doc","activeElement","onchange","onkeypress","input.onkeypress","event","keyCode","getPosition","RangeSelector.prototype.getPosition","buttonTop","inputTop","RangeSelector.prototype.getYTDExtremes","now","startOfYear","getTime","RangeSelector.prototype.render","navButtonOptions","exporting","navigation","inputsZIndex","inputEnabled","buttonGroup","legendOptions","buttonPositionY","inputPositionY","hasLoaded","exportingX","zoomText","buttonEvents","events","click","callDefaultEvent","isActive","hover","disabled","insertBefore","buttonLeft","buttonSpacing","spacing","titleCollision","spacingBox","placed","inputGroupX","alignAttr","alignOptions","inputGroupWidth","buttonGroupX","buttonGroupWidth","groupHeight","alignTranslateY","legendHeight","minPosition","marginTop","getHeight","RangeSelector.prototype.getHeight","rangeSelectorGroup","yPosition","rangeSelectorHeight","RangeSelector.prototype.titleCollision","subtitle","RangeSelector.prototype.update","RangeSelector.prototype.destroy","rSelector","window","HTMLElement","Axis.prototype.minFromRange","getTrueRange","base","timeName","basePeriod","updateNames","getAxisMargins","extraBottomMargin","extraTopMargin","optionsRangeSelector","extraBottomMarginWas","extraTopMarginWas","isDirtyBox","marginBottom","renderRangeSelector","extremes","getExtremes","display","alignTo","layout","unbindSetExtremes","unbindRender","destroyEvents","NavigatorAxisAdditions","NavigatorAxisAdditions.prototype.destroy","toFixedRange","NavigatorAxisAdditions.prototype.toFixedRange","pxMin","pxMax","fixedMin","fixedMax","halfPointRange","changeRatio","NavigatorAxis","NavigatorAxis.compose","navigatorAxis","pinchType","zoomType","zoomed","previousZoom","preventDefault","AdditionsClass","numExt","extreme","_i","numbers","defaultSeriesType","areaspline","maskInside","handles","backgroundColor","maskFill","setOpacity","outlineColor","outlineWidth","fillOpacity","compare","approximation","groupPixelWidth","smoothed","overscroll","gridLineColor","gridLineWidth","crosshair","Renderer","halfWidth","markerPosition","Navigator","zoomedMin","zoomedMax","shades","outlineHeight","outline","navigatorSize","navigatorSeries","navigatorOptions","navigatorGroup","navigatorEnabled","baseSeries","drawHandle","Navigator.prototype.drawHandle","parseInt","drawOutline","Navigator.prototype.drawOutline","halfOutline","outlineCorrection","scrollbarHeight","navigatorTop","verticalMin","drawMasks","Navigator.prototype.drawMasks","navigatorHeight","shade","renderElements","Navigator.prototype.renderElements","mouseCursor","visibility","hasMask","handlesOptions","Navigator.prototype.update","Navigator.prototype.render","scrollbarXAxis","fake","maxRange","navigatorWidth","toPixels","toValue","currentRange","grabbedLeft","grabbedRight","fixedWidth","addMouseEvents","Navigator.prototype.addMouseEvents","eventsToUnbind","onMouseMove","onMouseUp","getPartsEvents","modifyNavigatorAxisExtremes","Navigator.prototype.getPartsEvents","navigatorItem","shadesMousedown","Navigator.prototype.shadesMousedown","navigatorPosition","dragOffset","reversedExtremes","ext","handlesMousedown","Navigator.prototype.handlesMousedown","baseXAxis","otherHandlePos","fixedExtreme","Navigator.prototype.onMouseMove","pageX","setTimeout","Navigator.prototype.onMouseUp","triggerOp","Navigator.prototype.removeEvents","unbind","removeBaseSeriesEvents","Navigator.prototype.removeBaseSeriesEvents","adaptToUpdatedData","updatedDataHandler","modifyBaseAxisExtremes","Navigator.prototype.init","scrollbarOptions","scrollbarEnabled","setBaseSeries","xAxisIndex","yAxisIndex","baseXaxis","isX","keepOrdinalPadding","zoomEnabled","offsets","alignTicks","updateNavigatorSeries","unbindRedraw","scrollTrackWidth","valueRange","addBaseSeriesEvents","addChartEvents","Navigator.prototype.getUnionExtremes","returnFalseOnNoBaseSeries","navAxis","navAxisOptions","baseAxisOptions","Navigator.prototype.setBaseSeries","baseSeriesOptions","showInNavigator","Navigator.prototype.updateNavigatorSeries","baseOptions","mergedNavSeriesOptions","chartNavigatorSeriesOptions","baseNavigatorOptions","navSeriesMixin","enableMouseTracking","padXAxis","showInLegend","inactive","navSeries","eachBaseSeries","linkedNavSeries","userNavOptions","plotOptions","navigatorSeriesData","hasNavigatorData","initSeries","userSeriesOptions","Navigator.prototype.addBaseSeriesEvents","setVisible","remove","getBaseSeriesMin","Navigator.prototype.getBaseSeriesMin","currentSeriesMin","Navigator.prototype.modifyNavigatorAxisExtremes","Navigator.prototype.modifyBaseAxisExtremes","baseExtremes","baseDataMin","baseDataMax","stickToMin","stickToMax","hasSetExtremes","eventArgs","Navigator.prototype.updatedDataHandler","xDataMin","pointStart","Navigator.prototype.addChartEvents","marginName","Navigator.prototype.destroy"]} \ No newline at end of file diff --git a/highcharts/modules/gantt.src.js b/highcharts/modules/gantt.src.js new file mode 100644 index 0000000..8b9eaa3 --- /dev/null +++ b/highcharts/modules/gantt.src.js @@ -0,0 +1,12203 @@ +/** + * @license Highcharts Gantt JS v8.2.0 (2020-08-20) + * + * Gantt series + * + * (c) 2016-2019 Lars A. V. Cabrera + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/gantt', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'Gantt/Tree.js', [_modules['Core/Utilities.js']], function (U) { + /* * + * + * (c) 2016-2020 Highsoft AS + * + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* eslint no-console: 0 */ + var extend = U.extend, + isNumber = U.isNumber, + pick = U.pick; + /** + * Creates an object map from parent id to childrens index. + * + * @private + * @function Highcharts.Tree#getListOfParents + * + * @param {Array<*>} data + * List of points set in options. `Array.parent` is parent id of point. + * + * @param {Array} ids + * List of all point ids. + * + * @return {Highcharts.Dictionary>} + * Map from parent id to children index in data + */ + var getListOfParents = function (data, + ids) { + var listOfParents = data.reduce(function (prev, + curr) { + var parent = pick(curr.parent, ''); + if (typeof prev[parent] === 'undefined') { + prev[parent] = []; + } + prev[parent].push(curr); + return prev; + }, {}), parents = Object.keys(listOfParents); + // If parent does not exist, hoist parent to root of tree. + parents.forEach(function (parent, list) { + var children = listOfParents[parent]; + if ((parent !== '') && (ids.indexOf(parent) === -1)) { + children.forEach(function (child) { + list[''].push(child); + }); + delete list[parent]; + } + }); + return listOfParents; + }; + var getNode = function (id, + parent, + level, + data, + mapOfIdToChildren, + options) { + var descendants = 0, + height = 0, + after = options && options.after, + before = options && options.before, + node = { + data: data, + depth: level - 1, + id: id, + level: level, + parent: parent + }, + start, + end, + children; + // Allow custom logic before the children has been created. + if (typeof before === 'function') { + before(node, options); + } + // Call getNode recursively on the children. Calulate the height of the + // node, and the number of descendants. + children = ((mapOfIdToChildren[id] || [])).map(function (child) { + var node = getNode(child.id, + id, (level + 1), + child, + mapOfIdToChildren, + options), + childStart = child.start, + childEnd = (child.milestone === true ? + childStart : + child.end); + // Start should be the lowest child.start. + start = ((!isNumber(start) || childStart < start) ? + childStart : + start); + // End should be the largest child.end. + // If child is milestone, then use start as end. + end = ((!isNumber(end) || childEnd > end) ? + childEnd : + end); + descendants = descendants + 1 + node.descendants; + height = Math.max(node.height + 1, height); + return node; + }); + // Calculate start and end for point if it is not already explicitly set. + if (data) { + data.start = pick(data.start, start); + data.end = pick(data.end, end); + } + extend(node, { + children: children, + descendants: descendants, + height: height + }); + // Allow custom logic after the children has been created. + if (typeof after === 'function') { + after(node, options); + } + return node; + }; + var getTree = function (data, + options) { + var ids = data.map(function (d) { + return d.id; + }), mapOfIdToChildren = getListOfParents(data, ids); + return getNode('', null, 1, null, mapOfIdToChildren, options); + }; + var Tree = { + getListOfParents: getListOfParents, + getNode: getNode, + getTree: getTree + }; + + return Tree; + }); + _registerModule(_modules, 'Core/Axis/TreeGridTick.js', [_modules['Core/Utilities.js']], function (U) { + /* * + * + * (c) 2016 Highsoft AS + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + defined = U.defined, + isObject = U.isObject, + isNumber = U.isNumber, + pick = U.pick, + wrap = U.wrap; + /** + * @private + */ + var TreeGridTick; + (function (TreeGridTick) { + /* * + * + * Interfaces + * + * */ + /* * + * + * Variables + * + * */ + var applied = false; + /* * + * + * Functions + * + * */ + /** + * @private + */ + function compose(TickClass) { + if (!applied) { + addEvent(TickClass, 'init', onInit); + wrap(TickClass.prototype, 'getLabelPosition', wrapGetLabelPosition); + wrap(TickClass.prototype, 'renderLabel', wrapRenderLabel); + // backwards compatibility + TickClass.prototype.collapse = function (redraw) { + this.treeGrid.collapse(redraw); + }; + TickClass.prototype.expand = function (redraw) { + this.treeGrid.expand(redraw); + }; + TickClass.prototype.toggleCollapse = function (redraw) { + this.treeGrid.toggleCollapse(redraw); + }; + applied = true; + } + } + TreeGridTick.compose = compose; + /** + * @private + */ + function onInit() { + var tick = this; + if (!tick.treeGrid) { + tick.treeGrid = new Additions(tick); + } + } + /** + * @private + */ + function onTickHover(label) { + label.addClass('highcharts-treegrid-node-active'); + if (!label.renderer.styledMode) { + label.css({ + textDecoration: 'underline' + }); + } + } + /** + * @private + */ + function onTickHoverExit(label, options) { + var css = defined(options.style) ? options.style : {}; + label.removeClass('highcharts-treegrid-node-active'); + if (!label.renderer.styledMode) { + label.css({ textDecoration: css.textDecoration }); + } + } + /** + * @private + */ + function renderLabelIcon(tick, params) { + var treeGrid = tick.treeGrid, + isNew = !treeGrid.labelIcon, + renderer = params.renderer, + labelBox = params.xy, + options = params.options, + width = options.width, + height = options.height, + iconCenter = { + x: labelBox.x - (width / 2) - options.padding, + y: labelBox.y - (height / 2) + }, + rotation = params.collapsed ? 90 : 180, + shouldRender = params.show && isNumber(iconCenter.y); + var icon = treeGrid.labelIcon; + if (!icon) { + treeGrid.labelIcon = icon = renderer + .path(renderer.symbols[options.type](options.x, options.y, width, height)) + .addClass('highcharts-label-icon') + .add(params.group); + } + // Set the new position, and show or hide + if (!shouldRender) { + icon.attr({ y: -9999 }); // #1338 + } + // Presentational attributes + if (!renderer.styledMode) { + icon + .attr({ + 'stroke-width': 1, + 'fill': pick(params.color, '#666666') + }) + .css({ + cursor: 'pointer', + stroke: options.lineColor, + strokeWidth: options.lineWidth + }); + } + // Update the icon positions + icon[isNew ? 'attr' : 'animate']({ + translateX: iconCenter.x, + translateY: iconCenter.y, + rotation: rotation + }); + } + /** + * @private + */ + function wrapGetLabelPosition(proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index, step) { + var tick = this, + lbOptions = pick(tick.options && tick.options.labels, + labelOptions), + pos = tick.pos, + axis = tick.axis, + options = axis.options, + isTreeGrid = options.type === 'treegrid', + result = proceed.apply(tick, + [x, + y, + label, + horiz, + lbOptions, + tickmarkOffset, + index, + step]); + var symbolOptions, + indentation, + mapOfPosToGridNode, + node, + level; + if (isTreeGrid) { + symbolOptions = (lbOptions && isObject(lbOptions.symbol, true) ? + lbOptions.symbol : + {}); + indentation = (lbOptions && isNumber(lbOptions.indentation) ? + lbOptions.indentation : + 0); + mapOfPosToGridNode = axis.treeGrid.mapOfPosToGridNode; + node = mapOfPosToGridNode && mapOfPosToGridNode[pos]; + level = (node && node.depth) || 1; + result.x += ( + // Add space for symbols + ((symbolOptions.width) + (symbolOptions.padding * 2)) + + // Apply indentation + ((level - 1) * indentation)); + } + return result; + } + /** + * @private + */ + function wrapRenderLabel(proceed) { + var tick = this, pos = tick.pos, axis = tick.axis, label = tick.label, mapOfPosToGridNode = axis.treeGrid.mapOfPosToGridNode, options = axis.options, labelOptions = pick(tick.options && tick.options.labels, options && options.labels), symbolOptions = (labelOptions && isObject(labelOptions.symbol, true) ? + labelOptions.symbol : + {}), node = mapOfPosToGridNode && mapOfPosToGridNode[pos], level = node && node.depth, isTreeGrid = options.type === 'treegrid', shouldRender = axis.tickPositions.indexOf(pos) > -1, prefixClassName = 'highcharts-treegrid-node-', styledMode = axis.chart.styledMode; + var collapsed, + addClassName, + removeClassName; + if (isTreeGrid && node) { + // Add class name for hierarchical styling. + if (label && + label.element) { + label.addClass(prefixClassName + 'level-' + level); + } + } + proceed.apply(tick, Array.prototype.slice.call(arguments, 1)); + if (isTreeGrid && + label && + label.element && + node && + node.descendants && + node.descendants > 0) { + collapsed = axis.treeGrid.isCollapsed(node); + renderLabelIcon(tick, { + color: !styledMode && label.styles && label.styles.color || '', + collapsed: collapsed, + group: label.parentGroup, + options: symbolOptions, + renderer: label.renderer, + show: shouldRender, + xy: label.xy + }); + // Add class name for the node. + addClassName = prefixClassName + + (collapsed ? 'collapsed' : 'expanded'); + removeClassName = prefixClassName + + (collapsed ? 'expanded' : 'collapsed'); + label + .addClass(addClassName) + .removeClass(removeClassName); + if (!styledMode) { + label.css({ + cursor: 'pointer' + }); + } + // Add events to both label text and icon + [label, tick.treeGrid.labelIcon].forEach(function (object) { + if (object && !object.attachedTreeGridEvents) { + // On hover + addEvent(object.element, 'mouseover', function () { + onTickHover(label); + }); + // On hover out + addEvent(object.element, 'mouseout', function () { + onTickHoverExit(label, labelOptions); + }); + addEvent(object.element, 'click', function () { + tick.treeGrid.toggleCollapse(); + }); + object.attachedTreeGridEvents = true; + } + }); + } + } + /* * + * + * Classes + * + * */ + /** + * @private + * @class + */ + var Additions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + /** + * @private + */ + function Additions(tick) { + this.tick = tick; + } + /* * + * + * Functions + * + * */ + /** + * Collapse the grid cell. Used when axis is of type treegrid. + * + * @see gantt/treegrid-axis/collapsed-dynamically/demo.js + * + * @private + * @function Highcharts.Tick#collapse + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + */ + Additions.prototype.collapse = function (redraw) { + var tick = this.tick, + axis = tick.axis, + brokenAxis = axis.brokenAxis; + if (brokenAxis && + axis.treeGrid.mapOfPosToGridNode) { + var pos = tick.pos, + node = axis.treeGrid.mapOfPosToGridNode[pos], + breaks = axis.treeGrid.collapse(node); + brokenAxis.setBreaks(breaks, pick(redraw, true)); + } + }; + /** + * Expand the grid cell. Used when axis is of type treegrid. + * + * @see gantt/treegrid-axis/collapsed-dynamically/demo.js + * + * @private + * @function Highcharts.Tick#expand + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + */ + Additions.prototype.expand = function (redraw) { + var tick = this.tick, + axis = tick.axis, + brokenAxis = axis.brokenAxis; + if (brokenAxis && + axis.treeGrid.mapOfPosToGridNode) { + var pos = tick.pos, + node = axis.treeGrid.mapOfPosToGridNode[pos], + breaks = axis.treeGrid.expand(node); + brokenAxis.setBreaks(breaks, pick(redraw, true)); + } + }; + /** + * Toggle the collapse/expand state of the grid cell. Used when axis is + * of type treegrid. + * + * @see gantt/treegrid-axis/collapsed-dynamically/demo.js + * + * @private + * @function Highcharts.Tick#toggleCollapse + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + */ + Additions.prototype.toggleCollapse = function (redraw) { + var tick = this.tick, + axis = tick.axis, + brokenAxis = axis.brokenAxis; + if (brokenAxis && + axis.treeGrid.mapOfPosToGridNode) { + var pos = tick.pos, + node = axis.treeGrid.mapOfPosToGridNode[pos], + breaks = axis.treeGrid.toggleCollapse(node); + brokenAxis.setBreaks(breaks, pick(redraw, true)); + } + }; + return Additions; + }()); + TreeGridTick.Additions = Additions; + })(TreeGridTick || (TreeGridTick = {})); + + return TreeGridTick; + }); + _registerModule(_modules, 'Mixins/TreeSeries.js', [_modules['Core/Color.js'], _modules['Core/Utilities.js']], function (Color, U) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend, + isArray = U.isArray, + isNumber = U.isNumber, + isObject = U.isObject, + merge = U.merge, + pick = U.pick; + var isBoolean = function (x) { + return typeof x === 'boolean'; + }, isFn = function (x) { + return typeof x === 'function'; + }; + /* eslint-disable valid-jsdoc */ + /** + * @todo Combine buildTree and buildNode with setTreeValues + * @todo Remove logic from Treemap and make it utilize this mixin. + * @private + */ + var setTreeValues = function setTreeValues(tree, + options) { + var before = options.before, + idRoot = options.idRoot, + mapIdToNode = options.mapIdToNode, + nodeRoot = mapIdToNode[idRoot], + levelIsConstant = (isBoolean(options.levelIsConstant) ? + options.levelIsConstant : + true), + points = options.points, + point = points[tree.i], + optionsPoint = point && point.options || {}, + childrenTotal = 0, + children = [], + value; + extend(tree, { + levelDynamic: tree.level - (levelIsConstant ? 0 : nodeRoot.level), + name: pick(point && point.name, ''), + visible: (idRoot === tree.id || + (isBoolean(options.visible) ? options.visible : false)) + }); + if (isFn(before)) { + tree = before(tree, options); + } + // First give the children some values + tree.children.forEach(function (child, i) { + var newOptions = extend({}, + options); + extend(newOptions, { + index: i, + siblings: tree.children.length, + visible: tree.visible + }); + child = setTreeValues(child, newOptions); + children.push(child); + if (child.visible) { + childrenTotal += child.val; + } + }); + tree.visible = childrenTotal > 0 || tree.visible; + // Set the values + value = pick(optionsPoint.value, childrenTotal); + extend(tree, { + children: children, + childrenTotal: childrenTotal, + isLeaf: tree.visible && !childrenTotal, + val: value + }); + return tree; + }; + /** + * @private + */ + var getColor = function getColor(node, + options) { + var index = options.index, + mapOptionsToLevel = options.mapOptionsToLevel, + parentColor = options.parentColor, + parentColorIndex = options.parentColorIndex, + series = options.series, + colors = options.colors, + siblings = options.siblings, + points = series.points, + getColorByPoint, + chartOptionsChart = series.chart.options.chart, + point, + level, + colorByPoint, + colorIndexByPoint, + color, + colorIndex; + /** + * @private + */ + function variation(color) { + var colorVariation = level && level.colorVariation; + if (colorVariation) { + if (colorVariation.key === 'brightness') { + return Color.parse(color).brighten(colorVariation.to * (index / siblings)).get(); + } + } + return color; + } + if (node) { + point = points[node.i]; + level = mapOptionsToLevel[node.level] || {}; + getColorByPoint = point && level.colorByPoint; + if (getColorByPoint) { + colorIndexByPoint = point.index % (colors ? + colors.length : + chartOptionsChart.colorCount); + colorByPoint = colors && colors[colorIndexByPoint]; + } + // Select either point color, level color or inherited color. + if (!series.chart.styledMode) { + color = pick(point && point.options.color, level && level.color, colorByPoint, parentColor && variation(parentColor), series.color); + } + colorIndex = pick(point && point.options.colorIndex, level && level.colorIndex, colorIndexByPoint, parentColorIndex, options.colorIndex); + } + return { + color: color, + colorIndex: colorIndex + }; + }; + /** + * Creates a map from level number to its given options. + * + * @private + * @function getLevelOptions + * @param {object} params + * Object containing parameters. + * - `defaults` Object containing default options. The default options + * are merged with the userOptions to get the final options for a + * specific level. + * - `from` The lowest level number. + * - `levels` User options from series.levels. + * - `to` The highest level number. + * @return {Highcharts.Dictionary|null} + * Returns a map from level number to its given options. + */ + var getLevelOptions = function getLevelOptions(params) { + var result = null, + defaults, + converted, + i, + from, + to, + levels; + if (isObject(params)) { + result = {}; + from = isNumber(params.from) ? params.from : 1; + levels = params.levels; + converted = {}; + defaults = isObject(params.defaults) ? params.defaults : {}; + if (isArray(levels)) { + converted = levels.reduce(function (obj, item) { + var level, + levelIsConstant, + options; + if (isObject(item) && isNumber(item.level)) { + options = merge({}, item); + levelIsConstant = (isBoolean(options.levelIsConstant) ? + options.levelIsConstant : + defaults.levelIsConstant); + // Delete redundant properties. + delete options.levelIsConstant; + delete options.level; + // Calculate which level these options apply to. + level = item.level + (levelIsConstant ? 0 : from - 1); + if (isObject(obj[level])) { + extend(obj[level], options); + } + else { + obj[level] = options; + } + } + return obj; + }, {}); + } + to = isNumber(params.to) ? params.to : 1; + for (i = 0; i <= to; i++) { + result[i] = merge({}, defaults, isObject(converted[i]) ? converted[i] : {}); + } + } + return result; + }; + /** + * Update the rootId property on the series. Also makes sure that it is + * accessible to exporting. + * + * @private + * @function updateRootId + * + * @param {object} series + * The series to operate on. + * + * @return {string} + * Returns the resulting rootId after update. + */ + var updateRootId = function (series) { + var rootId, + options; + if (isObject(series)) { + // Get the series options. + options = isObject(series.options) ? series.options : {}; + // Calculate the rootId. + rootId = pick(series.rootNode, options.rootId, ''); + // Set rootId on series.userOptions to pick it up in exporting. + if (isObject(series.userOptions)) { + series.userOptions.rootId = rootId; + } + // Set rootId on series to pick it up on next update. + series.rootNode = rootId; + } + return rootId; + }; + var result = { + getColor: getColor, + getLevelOptions: getLevelOptions, + setTreeValues: setTreeValues, + updateRootId: updateRootId + }; + + return result; + }); + _registerModule(_modules, 'Core/Axis/GridAxis.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Globals.js'], _modules['Core/Options.js'], _modules['Core/Axis/Tick.js'], _modules['Core/Utilities.js']], function (Axis, H, O, Tick, U) { + /* * + * + * (c) 2016 Highsoft AS + * Authors: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var dateFormat = O.dateFormat; + var addEvent = U.addEvent, + defined = U.defined, + erase = U.erase, + find = U.find, + isArray = U.isArray, + isNumber = U.isNumber, + merge = U.merge, + pick = U.pick, + timeUnits = U.timeUnits, + wrap = U.wrap; + var argsToArray = function (args) { + return Array.prototype.slice.call(args, 1); + }, isObject = function (x) { + // Always use strict mode + return U.isObject(x, true); + }, Chart = H.Chart; + var applyGridOptions = function applyGridOptions(axis) { + var options = axis.options; + // Center-align by default + if (!options.labels) { + options.labels = {}; + } + options.labels.align = pick(options.labels.align, 'center'); + // @todo: Check against tickLabelPlacement between/on etc + /* Prevents adding the last tick label if the axis is not a category + axis. + Since numeric labels are normally placed at starts and ends of a + range of value, and this module makes the label point at the value, + an "extra" label would appear. */ + if (!axis.categories) { + options.showLastLabel = false; + } + // Prevents rotation of labels when squished, as rotating them would not + // help. + axis.labelRotation = 0; + options.labels.rotation = 0; + }; + /** + * For a datetime axis, the scale will automatically adjust to the + * appropriate unit. This member gives the default string + * representations used for each unit. For intermediate values, + * different units may be used, for example the `day` unit can be used + * on midnight and `hour` unit be used for intermediate values on the + * same axis. + * For grid axes (like in Gantt charts), + * it is possible to declare as a list to provide different + * formats depending on available space. + * For an overview of the replacement codes, see + * [dateFormat](/class-reference/Highcharts#dateFormat). + * + * Defaults to: + * ```js + * { + hour: { + list: ['%H:%M', '%H'] + }, + day: { + list: ['%A, %e. %B', '%a, %e. %b', '%E'] + }, + week: { + list: ['Week %W', 'W%W'] + }, + month: { + list: ['%B', '%b', '%o'] + } + }, + * ``` + * + * @sample {gantt} gantt/demo/left-axis-table + * Gantt Chart with custom axis date format. + * + * @product gantt + * @apioption xAxis.dateTimeLabelFormats + */ + /** + * Set grid options for the axis labels. Requires Highcharts Gantt. + * + * @since 6.2.0 + * @product gantt + * @apioption xAxis.grid + */ + /** + * Enable grid on the axis labels. Defaults to true for Gantt charts. + * + * @type {boolean} + * @default true + * @since 6.2.0 + * @product gantt + * @apioption xAxis.grid.enabled + */ + /** + * Set specific options for each column (or row for horizontal axes) in the + * grid. Each extra column/row is its own axis, and the axis options can be set + * here. + * + * @sample gantt/demo/left-axis-table + * Left axis as a table + * + * @type {Array} + * @apioption xAxis.grid.columns + */ + /** + * Set border color for the label grid lines. + * + * @type {Highcharts.ColorString} + * @apioption xAxis.grid.borderColor + */ + /** + * Set border width of the label grid lines. + * + * @type {number} + * @default 1 + * @apioption xAxis.grid.borderWidth + */ + /** + * Set cell height for grid axis labels. By default this is calculated from font + * size. This option only applies to horizontal axes. + * + * @sample gantt/grid-axis/cellheight + * Gant chart with custom cell height + * @type {number} + * @apioption xAxis.grid.cellHeight + */ + ''; // detach doclets above + /** + * Get the largest label width and height. + * + * @private + * @function Highcharts.Axis#getMaxLabelDimensions + * + * @param {Highcharts.Dictionary} ticks + * All the ticks on one axis. + * + * @param {Array} tickPositions + * All the tick positions on one axis. + * + * @return {Highcharts.SizeObject} + * Object containing the properties height and width. + * + * @todo Move this to the generic axis implementation, as it is used there. + */ + Axis.prototype.getMaxLabelDimensions = function (ticks, tickPositions) { + var dimensions = { + width: 0, + height: 0 + }; + tickPositions.forEach(function (pos) { + var tick = ticks[pos], + tickHeight = 0, + tickWidth = 0, + label; + if (isObject(tick)) { + label = isObject(tick.label) ? tick.label : {}; + // Find width and height of tick + tickHeight = label.getBBox ? label.getBBox().height : 0; + if (label.textStr) { + // Set the tickWidth same as the label width after ellipsis + // applied #10281 + tickWidth = Math.round(label.getBBox().width); + } + // Update the result if width and/or height are larger + dimensions.height = Math.max(tickHeight, dimensions.height); + dimensions.width = Math.max(tickWidth, dimensions.width); + } + }); + return dimensions; + }; + // Adds week date format + H.dateFormats.W = function (timestamp) { + var d = new this.Date(timestamp); + var firstDay = (this.get('Day', + d) + 6) % 7; + var thursday = new this.Date(d.valueOf()); + this.set('Date', thursday, this.get('Date', d) - firstDay + 3); + var firstThursday = new this.Date(this.get('FullYear', + thursday), 0, 1); + if (this.get('Day', firstThursday) !== 4) { + this.set('Month', d, 0); + this.set('Date', d, 1 + (11 - this.get('Day', firstThursday)) % 7); + } + return (1 + + Math.floor((thursday.valueOf() - firstThursday.valueOf()) / 604800000)).toString(); + }; + // First letter of the day of the week, e.g. 'M' for 'Monday'. + H.dateFormats.E = function (timestamp) { + return dateFormat('%a', timestamp, true).charAt(0); + }; + /* eslint-disable no-invalid-this */ + addEvent(Chart, 'afterSetChartSize', function () { + this.axes.forEach(function (axis) { + (axis.grid && axis.grid.columns || []).forEach(function (column) { + column.setAxisSize(); + column.setAxisTranslation(); + }); + }); + }); + // Center tick labels in cells. + addEvent(Tick, 'afterGetLabelPosition', function (e) { + var tick = this, + label = tick.label, + axis = tick.axis, + reversed = axis.reversed, + chart = axis.chart, + options = axis.options, + gridOptions = options.grid || {}, + labelOpts = axis.options.labels, + align = labelOpts.align, + // verticalAlign is currently not supported for axis.labels. + verticalAlign = 'middle', // labelOpts.verticalAlign, + side = GridAxis.Side[axis.side], + tickmarkOffset = e.tickmarkOffset, + tickPositions = axis.tickPositions, + tickPos = tick.pos - tickmarkOffset, + nextTickPos = (isNumber(tickPositions[e.index + 1]) ? + tickPositions[e.index + 1] - tickmarkOffset : + axis.max + tickmarkOffset), + tickSize = axis.tickSize('tick'), + tickWidth = tickSize ? tickSize[0] : 0, + crispCorr = tickSize ? tickSize[1] / 2 : 0, + labelHeight, + lblMetrics, + lines, + bottom, + top, + left, + right; + // Only center tick labels in grid axes + if (gridOptions.enabled === true) { + // Calculate top and bottom positions of the cell. + if (side === 'top') { + bottom = axis.top + axis.offset; + top = bottom - tickWidth; + } + else if (side === 'bottom') { + top = chart.chartHeight - axis.bottom + axis.offset; + bottom = top + tickWidth; + } + else { + bottom = axis.top + axis.len - axis.translate(reversed ? nextTickPos : tickPos); + top = axis.top + axis.len - axis.translate(reversed ? tickPos : nextTickPos); + } + // Calculate left and right positions of the cell. + if (side === 'right') { + left = chart.chartWidth - axis.right + axis.offset; + right = left + tickWidth; + } + else if (side === 'left') { + right = axis.left + axis.offset; + left = right - tickWidth; + } + else { + left = Math.round(axis.left + axis.translate(reversed ? nextTickPos : tickPos)) - crispCorr; + right = Math.round(axis.left + axis.translate(reversed ? tickPos : nextTickPos)) - crispCorr; + } + tick.slotWidth = right - left; + // Calculate the positioning of the label based on + // alignment. + e.pos.x = (align === 'left' ? + left : + align === 'right' ? + right : + left + ((right - left) / 2) // default to center + ); + e.pos.y = (verticalAlign === 'top' ? + top : + verticalAlign === 'bottom' ? + bottom : + top + ((bottom - top) / 2) // default to middle + ); + lblMetrics = chart.renderer.fontMetrics(labelOpts.style.fontSize, label.element); + labelHeight = label.getBBox().height; + // Adjustment to y position to align the label correctly. + // Would be better to have a setter or similar for this. + if (!labelOpts.useHTML) { + lines = Math.round(labelHeight / lblMetrics.h); + e.pos.y += ( + // Center the label + // TODO: why does this actually center the label? + ((lblMetrics.b - (lblMetrics.h - lblMetrics.f)) / 2) + + // Adjust for height of additional lines. + -(((lines - 1) * lblMetrics.h) / 2)); + } + else { + e.pos.y += ( + // Readjust yCorr in htmlUpdateTransform + lblMetrics.b + + // Adjust for height of html label + -(labelHeight / 2)); + } + e.pos.x += (axis.horiz && labelOpts.x || 0); + } + }); + /* eslint-enable no-invalid-this */ + /** + * Additions for grid axes. + * @private + * @class + */ + var GridAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function GridAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Checks if an axis is the outer axis in its dimension. Since + * axes are placed outwards in order, the axis with the highest + * index is the outermost axis. + * + * Example: If there are multiple x-axes at the top of the chart, + * this function returns true if the axis supplied is the last + * of the x-axes. + * + * @private + * + * @return {boolean} + * True if the axis is the outermost axis in its dimension; false if + * not. + */ + GridAxisAdditions.prototype.isOuterAxis = function () { + var axis = this.axis; + var chart = axis.chart; + var columnIndex = axis.grid.columnIndex; + var columns = (axis.linkedParent && axis.linkedParent.grid.columns || + axis.grid.columns); + var parentAxis = columnIndex ? axis.linkedParent : axis; + var thisIndex = -1, + lastIndex = 0; + chart[axis.coll].forEach(function (otherAxis, index) { + if (otherAxis.side === axis.side && !otherAxis.options.isInternal) { + lastIndex = index; + if (otherAxis === parentAxis) { + // Get the index of the axis in question + thisIndex = index; + } + } + }); + return (lastIndex === thisIndex && + (isNumber(columnIndex) ? columns.length === columnIndex : true)); + }; + return GridAxisAdditions; + }()); + /** + * Axis with grid support. + * @private + * @class + */ + var GridAxis = /** @class */ (function () { + function GridAxis() { + } + /* * + * + * Static Functions + * + * */ + /* eslint-disable valid-jsdoc */ + /** + * Extends axis class with grid support. + * @private + */ + GridAxis.compose = function (AxisClass) { + Axis.keepProps.push('grid'); + wrap(AxisClass.prototype, 'unsquish', GridAxis.wrapUnsquish); + // Add event handlers + addEvent(AxisClass, 'init', GridAxis.onInit); + addEvent(AxisClass, 'afterGetOffset', GridAxis.onAfterGetOffset); + addEvent(AxisClass, 'afterGetTitlePosition', GridAxis.onAfterGetTitlePosition); + addEvent(AxisClass, 'afterInit', GridAxis.onAfterInit); + addEvent(AxisClass, 'afterRender', GridAxis.onAfterRender); + addEvent(AxisClass, 'afterSetAxisTranslation', GridAxis.onAfterSetAxisTranslation); + addEvent(AxisClass, 'afterSetOptions', GridAxis.onAfterSetOptions); + addEvent(AxisClass, 'afterSetOptions', GridAxis.onAfterSetOptions2); + addEvent(AxisClass, 'afterSetScale', GridAxis.onAfterSetScale); + addEvent(AxisClass, 'afterTickSize', GridAxis.onAfterTickSize); + addEvent(AxisClass, 'trimTicks', GridAxis.onTrimTicks); + addEvent(AxisClass, 'destroy', GridAxis.onDestroy); + }; + /** + * Handle columns and getOffset. + * @private + */ + GridAxis.onAfterGetOffset = function () { + var grid = this.grid; + (grid && grid.columns || []).forEach(function (column) { + column.getOffset(); + }); + }; + /** + * @private + */ + GridAxis.onAfterGetTitlePosition = function (e) { + var axis = this; + var options = axis.options; + var gridOptions = options.grid || {}; + if (gridOptions.enabled === true) { + // compute anchor points for each of the title align options + var title = axis.axisTitle, + axisHeight = axis.height, + horiz = axis.horiz, + axisLeft = axis.left, + offset = axis.offset, + opposite = axis.opposite, + _a = axis.options.title, + axisTitleOptions = _a === void 0 ? {} : _a, + axisTop = axis.top, + axisWidth = axis.width; + var tickSize = axis.tickSize(); + var titleWidth = title && title.getBBox().width; + var xOption = axisTitleOptions.x || 0; + var yOption = axisTitleOptions.y || 0; + var titleMargin = pick(axisTitleOptions.margin, + horiz ? 5 : 10); + var titleFontSize = axis.chart.renderer.fontMetrics(axisTitleOptions.style && + axisTitleOptions.style.fontSize, + title).f; + var crispCorr = tickSize ? tickSize[0] / 2 : 0; + // TODO account for alignment + // the position in the perpendicular direction of the axis + var offAxis = ((horiz ? axisTop + axisHeight : axisLeft) + + (horiz ? 1 : -1) * // horizontal axis reverses the margin + (opposite ? -1 : 1) * // so does opposite axes + crispCorr + + (axis.side === GridAxis.Side.bottom ? titleFontSize : 0)); + e.titlePosition.x = horiz ? + axisLeft - titleWidth / 2 - titleMargin + xOption : + offAxis + (opposite ? axisWidth : 0) + offset + xOption; + e.titlePosition.y = horiz ? + (offAxis - + (opposite ? axisHeight : 0) + + (opposite ? titleFontSize : -titleFontSize) / 2 + + offset + + yOption) : + axisTop - titleMargin + yOption; + } + }; + /** + * @private + */ + GridAxis.onAfterInit = function () { + var axis = this; + var chart = axis.chart, + _a = axis.options.grid, + gridOptions = _a === void 0 ? {} : _a, + userOptions = axis.userOptions; + if (gridOptions.enabled) { + applyGridOptions(axis); + /* eslint-disable no-invalid-this */ + // TODO: wrap the axis instead + wrap(axis, 'labelFormatter', function (proceed) { + var _a = this, + axis = _a.axis, + value = _a.value; + var tickPos = axis.tickPositions; + var series = (axis.isLinked ? + axis.linkedParent : + axis).series[0]; + var isFirst = value === tickPos[0]; + var isLast = value === tickPos[tickPos.length - 1]; + var point = series && find(series.options.data, + function (p) { + return p[axis.isXAxis ? 'x' : 'y'] === value; + }); + // Make additional properties available for the + // formatter + this.isFirst = isFirst; + this.isLast = isLast; + this.point = point; + // Call original labelFormatter + return proceed.call(this); + }); + /* eslint-enable no-invalid-this */ + } + if (gridOptions.columns) { + var columns = axis.grid.columns = [], + columnIndex = axis.grid.columnIndex = 0; + // Handle columns, each column is a grid axis + while (++columnIndex < gridOptions.columns.length) { + var columnOptions = merge(userOptions, + gridOptions.columns[gridOptions.columns.length - columnIndex - 1], { + linkedTo: 0, + // Force to behave like category axis + type: 'category', + // Disable by default the scrollbar on the grid axis + scrollbar: { + enabled: false + } + }); + delete columnOptions.grid.columns; // Prevent recursion + var column = new Axis(axis.chart, + columnOptions); + column.grid.isColumn = true; + column.grid.columnIndex = columnIndex; + // Remove column axis from chart axes array, and place it + // in the columns array. + erase(chart.axes, column); + erase(chart[axis.coll], column); + columns.push(column); + } + } + }; + /** + * Draw an extra line on the far side of the outermost axis, + * creating floor/roof/wall of a grid. And some padding. + * ``` + * Make this: + * (axis.min) __________________________ (axis.max) + * | | | | | + * Into this: + * (axis.min) __________________________ (axis.max) + * ___|____|____|____|____|__ + * ``` + * @private + */ + GridAxis.onAfterRender = function () { + var axis = this; + var grid = axis.grid; + var options = axis.options; + var renderer = axis.chart.renderer; + var gridOptions = options.grid || {}; + var yStartIndex, + yEndIndex, + xStartIndex, + xEndIndex; + if (gridOptions.enabled === true) { + // @todo acutual label padding (top, bottom, left, right) + axis.maxLabelDimensions = axis.getMaxLabelDimensions(axis.ticks, axis.tickPositions); + // Remove right wall before rendering if updating + if (axis.rightWall) { + axis.rightWall.destroy(); + } + /* + Draw an extra axis line on outer axes + > + Make this: |______|______|______|___ + + > _________________________ + Into this: |______|______|______|__| + */ + if (axis.grid && axis.grid.isOuterAxis() && axis.axisLine) { + var lineWidth = options.lineWidth; + if (lineWidth) { + var linePath = axis.getLinePath(lineWidth); + var startPoint = linePath[0]; + var endPoint = linePath[1]; + // Negate distance if top or left axis + // Subtract 1px to draw the line at the end of the tick + var tickLength = (axis.tickSize('tick') || [1])[0]; + var distance = (tickLength - 1) * ((axis.side === GridAxis.Side.top || + axis.side === GridAxis.Side.left) ? -1 : 1); + // If axis is horizontal, reposition line path vertically + if (startPoint[0] === 'M' && endPoint[0] === 'L') { + if (axis.horiz) { + startPoint[2] += distance; + endPoint[2] += distance; + } + else { + // If axis is vertical, reposition line path + // horizontally + startPoint[1] += distance; + endPoint[1] += distance; + } + } + if (!axis.grid.axisLineExtra) { + axis.grid.axisLineExtra = renderer + .path(linePath) + .attr({ + zIndex: 7 + }) + .addClass('highcharts-axis-line') + .add(axis.axisGroup); + if (!renderer.styledMode) { + axis.grid.axisLineExtra.attr({ + stroke: options.lineColor, + 'stroke-width': lineWidth + }); + } + } + else { + axis.grid.axisLineExtra.animate({ + d: linePath + }); + } + // show or hide the line depending on + // options.showEmpty + axis.axisLine[axis.showAxis ? 'show' : 'hide'](true); + } + } + (grid && grid.columns || []).forEach(function (column) { + column.render(); + }); + } + }; + /** + * @private + */ + GridAxis.onAfterSetAxisTranslation = function () { + var axis = this; + var tickInfo = axis.tickPositions && axis.tickPositions.info; + var options = axis.options; + var gridOptions = options.grid || {}; + var userLabels = axis.userOptions.labels || {}; + if (axis.horiz) { + if (gridOptions.enabled === true) { + axis.series.forEach(function (series) { + series.options.pointRange = 0; + }); + } + // Lower level time ticks, like hours or minutes, represent + // points in time and not ranges. These should be aligned + // left in the grid cell by default. The same applies to + // years of higher order. + if (tickInfo && + options.dateTimeLabelFormats && + options.labels && + !defined(userLabels.align) && + (options.dateTimeLabelFormats[tickInfo.unitName].range === false || + tickInfo.count > 1 // years + )) { + options.labels.align = 'left'; + if (!defined(userLabels.x)) { + options.labels.x = 3; + } + } + } + }; + /** + * Creates a left and right wall on horizontal axes: + * - Places leftmost tick at the start of the axis, to create a left + * wall + * - Ensures that the rightmost tick is at the end of the axis, to + * create a right wall. + * @private + */ + GridAxis.onAfterSetOptions = function (e) { + var options = this.options, + userOptions = e.userOptions, + gridAxisOptions, + gridOptions = ((options && isObject(options.grid)) ? options.grid : {}); + if (gridOptions.enabled === true) { + // Merge the user options into default grid axis options so + // that when a user option is set, it takes presedence. + gridAxisOptions = merge(true, { + className: ('highcharts-grid-axis ' + (userOptions.className || '')), + dateTimeLabelFormats: { + hour: { + list: ['%H:%M', '%H'] + }, + day: { + list: ['%A, %e. %B', '%a, %e. %b', '%E'] + }, + week: { + list: ['Week %W', 'W%W'] + }, + month: { + list: ['%B', '%b', '%o'] + } + }, + grid: { + borderWidth: 1 + }, + labels: { + padding: 2, + style: { + fontSize: '13px' + } + }, + margin: 0, + title: { + text: null, + reserveSpace: false, + rotation: 0 + }, + // In a grid axis, only allow one unit of certain types, + // for example we shouln't have one grid cell spanning + // two days. + units: [[ + 'millisecond', + [1, 10, 100] + ], [ + 'second', + [1, 10] + ], [ + 'minute', + [1, 5, 15] + ], [ + 'hour', + [1, 6] + ], [ + 'day', + [1] + ], [ + 'week', + [1] + ], [ + 'month', + [1] + ], [ + 'year', + null + ]] + }, userOptions); + // X-axis specific options + if (this.coll === 'xAxis') { + // For linked axes, tickPixelInterval is used only if + // the tickPositioner below doesn't run or returns + // undefined (like multiple years) + if (defined(userOptions.linkedTo) && + !defined(userOptions.tickPixelInterval)) { + gridAxisOptions.tickPixelInterval = 350; + } + // For the secondary grid axis, use the primary axis' + // tick intervals and return ticks one level higher. + if ( + // Check for tick pixel interval in options + !defined(userOptions.tickPixelInterval) && + // Only for linked axes + defined(userOptions.linkedTo) && + !defined(userOptions.tickPositioner) && + !defined(userOptions.tickInterval)) { + gridAxisOptions.tickPositioner = function (min, max) { + var parentInfo = (this.linkedParent && + this.linkedParent.tickPositions && + this.linkedParent.tickPositions.info); + if (parentInfo) { + var unitIdx, + count, + unitName, + i, + units = gridAxisOptions.units, + unitRange; + for (i = 0; i < units.length; i++) { + if (units[i][0] === + parentInfo.unitName) { + unitIdx = i; + break; + } + } + // Get the first allowed count on the next + // unit. + if (units[unitIdx + 1]) { + unitName = units[unitIdx + 1][0]; + count = + (units[unitIdx + 1][1] || [1])[0]; + // In case the base X axis shows years, make + // the secondary axis show ten times the + // years (#11427) + } + else if (parentInfo.unitName === 'year') { + unitName = 'year'; + count = parentInfo.count * 10; + } + unitRange = timeUnits[unitName]; + this.tickInterval = unitRange * count; + return this.getTimeTicks({ + unitRange: unitRange, + count: count, + unitName: unitName + }, min, max, this.options.startOfWeek); + } + }; + } + } + // Now merge the combined options into the axis options + merge(true, this.options, gridAxisOptions); + if (this.horiz) { + /* _________________________ + Make this: ___|_____|_____|_____|__| + ^ ^ + _________________________ + Into this: |_____|_____|_____|_____| + ^ ^ */ + options.minPadding = pick(userOptions.minPadding, 0); + options.maxPadding = pick(userOptions.maxPadding, 0); + } + // If borderWidth is set, then use its value for tick and + // line width. + if (isNumber(options.grid.borderWidth)) { + options.tickWidth = options.lineWidth = gridOptions.borderWidth; + } + } + }; + /** + * @private + */ + GridAxis.onAfterSetOptions2 = function (e) { + var axis = this; + var userOptions = e.userOptions; + var gridOptions = userOptions && userOptions.grid || {}; + var columns = gridOptions.columns; + // Add column options to the parent axis. Children has their column + // options set on init in onGridAxisAfterInit. + if (gridOptions.enabled && columns) { + merge(true, axis.options, columns[columns.length - 1]); + } + }; + /** + * Handle columns and setScale. + * @private + */ + GridAxis.onAfterSetScale = function () { + var axis = this; + (axis.grid.columns || []).forEach(function (column) { + column.setScale(); + }); + }; + /** + * Draw vertical axis ticks extra long to create cell floors and roofs. + * Overrides the tickLength for vertical axes. + * @private + */ + GridAxis.onAfterTickSize = function (e) { + var defaultLeftAxisOptions = Axis.defaultLeftAxisOptions; + var _a = this, + horiz = _a.horiz, + maxLabelDimensions = _a.maxLabelDimensions, + _b = _a.options.grid, + gridOptions = _b === void 0 ? {} : _b; + if (gridOptions.enabled && maxLabelDimensions) { + var labelPadding = (Math.abs(defaultLeftAxisOptions.labels.x) * 2); + var distance = horiz ? + gridOptions.cellHeight || labelPadding + maxLabelDimensions.height : + labelPadding + maxLabelDimensions.width; + if (isArray(e.tickSize)) { + e.tickSize[0] = distance; + } + else { + e.tickSize = [distance, 0]; + } + } + }; + /** + * @private + */ + GridAxis.onDestroy = function (e) { + var grid = this.grid; + (grid.columns || []).forEach(function (column) { + column.destroy(e.keepEvents); + }); + grid.columns = void 0; + }; + /** + * Wraps axis init to draw cell walls on vertical axes. + * @private + */ + GridAxis.onInit = function (e) { + var axis = this; + var userOptions = e.userOptions || {}; + var gridOptions = userOptions.grid || {}; + if (gridOptions.enabled && defined(gridOptions.borderColor)) { + userOptions.tickColor = userOptions.lineColor = gridOptions.borderColor; + } + if (!axis.grid) { + axis.grid = new GridAxisAdditions(axis); + } + }; + /** + * Makes tick labels which are usually ignored in a linked axis + * displayed if they are within range of linkedParent.min. + * ``` + * _____________________________ + * | | | | | + * Make this: | | 2 | 3 | 4 | + * |___|_______|_______|_______| + * ^ + * _____________________________ + * | | | | | + * Into this: | 1 | 2 | 3 | 4 | + * |___|_______|_______|_______| + * ^ + * ``` + * @private + * @todo Does this function do what the drawing says? Seems to affect + * ticks and not the labels directly? + */ + GridAxis.onTrimTicks = function () { + var axis = this; + var options = axis.options; + var gridOptions = options.grid || {}; + var categoryAxis = axis.categories; + var tickPositions = axis.tickPositions; + var firstPos = tickPositions[0]; + var lastPos = tickPositions[tickPositions.length - 1]; + var linkedMin = axis.linkedParent && axis.linkedParent.min; + var linkedMax = axis.linkedParent && axis.linkedParent.max; + var min = linkedMin || axis.min; + var max = linkedMax || axis.max; + var tickInterval = axis.tickInterval; + var endMoreThanMin = (firstPos < min && + firstPos + tickInterval > min); + var startLessThanMax = (lastPos > max && + lastPos - tickInterval < max); + if (gridOptions.enabled === true && + !categoryAxis && + (axis.horiz || axis.isLinked)) { + if (endMoreThanMin && !options.startOnTick) { + tickPositions[0] = min; + } + if (startLessThanMax && !options.endOnTick) { + tickPositions[tickPositions.length - 1] = max; + } + } + }; + /** + * Avoid altering tickInterval when reserving space. + * @private + */ + GridAxis.wrapUnsquish = function (proceed) { + var axis = this; + var _a = axis.options.grid, + gridOptions = _a === void 0 ? {} : _a; + if (gridOptions.enabled === true && axis.categories) { + return axis.tickInterval; + } + return proceed.apply(axis, argsToArray(arguments)); + }; + return GridAxis; + }()); + (function (GridAxis) { + /** + * Enum for which side the axis is on. Maps to axis.side. + * @private + */ + var Side; + (function (Side) { + Side[Side["top"] = 0] = "top"; + Side[Side["right"] = 1] = "right"; + Side[Side["bottom"] = 2] = "bottom"; + Side[Side["left"] = 3] = "left"; + })(Side = GridAxis.Side || (GridAxis.Side = {})); + })(GridAxis || (GridAxis = {})); + GridAxis.compose(Axis); + + return GridAxis; + }); + _registerModule(_modules, 'Core/Axis/BrokenAxis.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js'], _modules['Extensions/Stacking.js']], function (Axis, H, U, StackItem) { + /* * + * + * (c) 2009-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + find = U.find, + fireEvent = U.fireEvent, + isArray = U.isArray, + isNumber = U.isNumber, + pick = U.pick; + var Series = H.Series; + /* eslint-disable valid-jsdoc */ + /** + * Provides support for broken axes. + * @private + * @class + */ + var BrokenAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function BrokenAxisAdditions(axis) { + this.hasBreaks = false; + this.axis = axis; + } + /* * + * + * Static Functions + * + * */ + /** + * @private + */ + BrokenAxisAdditions.isInBreak = function (brk, val) { + var ret, + repeat = brk.repeat || Infinity, + from = brk.from, + length = brk.to - brk.from, + test = (val >= from ? + (val - from) % repeat : + repeat - ((from - val) % repeat)); + if (!brk.inclusive) { + ret = test < length && test !== 0; + } + else { + ret = test <= length; + } + return ret; + }; + /** + * @private + */ + BrokenAxisAdditions.lin2Val = function (val) { + var axis = this; + var brokenAxis = axis.brokenAxis; + var breakArray = brokenAxis && brokenAxis.breakArray; + if (!breakArray) { + return val; + } + var nval = val, + brk, + i; + for (i = 0; i < breakArray.length; i++) { + brk = breakArray[i]; + if (brk.from >= nval) { + break; + } + else if (brk.to < nval) { + nval += brk.len; + } + else if (BrokenAxisAdditions.isInBreak(brk, nval)) { + nval += brk.len; + } + } + return nval; + }; + /** + * @private + */ + BrokenAxisAdditions.val2Lin = function (val) { + var axis = this; + var brokenAxis = axis.brokenAxis; + var breakArray = brokenAxis && brokenAxis.breakArray; + if (!breakArray) { + return val; + } + var nval = val, + brk, + i; + for (i = 0; i < breakArray.length; i++) { + brk = breakArray[i]; + if (brk.to <= val) { + nval -= brk.len; + } + else if (brk.from >= val) { + break; + } + else if (BrokenAxisAdditions.isInBreak(brk, val)) { + nval -= (val - brk.from); + break; + } + } + return nval; + }; + /* * + * + * Functions + * + * */ + /** + * Returns the first break found where the x is larger then break.from and + * smaller then break.to. + * + * @param {number} x + * The number which should be within a break. + * + * @param {Array} breaks + * The array of breaks to search within. + * + * @return {Highcharts.XAxisBreaksOptions|undefined} + * Returns the first break found that matches, returns false if no break is + * found. + */ + BrokenAxisAdditions.prototype.findBreakAt = function (x, breaks) { + return find(breaks, function (b) { + return b.from < x && x < b.to; + }); + }; + /** + * @private + */ + BrokenAxisAdditions.prototype.isInAnyBreak = function (val, testKeep) { + var brokenAxis = this; + var axis = brokenAxis.axis; + var breaks = axis.options.breaks, + i = breaks && breaks.length, + inbrk, + keep, + ret; + if (i) { + while (i--) { + if (BrokenAxisAdditions.isInBreak(breaks[i], val)) { + inbrk = true; + if (!keep) { + keep = pick(breaks[i].showPoints, !axis.isXAxis); + } + } + } + if (inbrk && testKeep) { + ret = inbrk && !keep; + } + else { + ret = inbrk; + } + } + return ret; + }; + /** + * Dynamically set or unset breaks in an axis. This function in lighter than + * usin Axis.update, and it also preserves animation. + * + * @private + * @function Highcharts.Axis#setBreaks + * + * @param {Array} [breaks] + * The breaks to add. When `undefined` it removes existing breaks. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart immediately. + * + * @return {void} + */ + BrokenAxisAdditions.prototype.setBreaks = function (breaks, redraw) { + var brokenAxis = this; + var axis = brokenAxis.axis; + var hasBreaks = (isArray(breaks) && !!breaks.length); + axis.isDirty = brokenAxis.hasBreaks !== hasBreaks; + brokenAxis.hasBreaks = hasBreaks; + axis.options.breaks = axis.userOptions.breaks = breaks; + axis.forceRedraw = true; // Force recalculation in setScale + // Recalculate series related to the axis. + axis.series.forEach(function (series) { + series.isDirty = true; + }); + if (!hasBreaks && axis.val2lin === BrokenAxisAdditions.val2Lin) { + // Revert to prototype functions + delete axis.val2lin; + delete axis.lin2val; + } + if (hasBreaks) { + axis.userOptions.ordinal = false; + axis.lin2val = BrokenAxisAdditions.lin2Val; + axis.val2lin = BrokenAxisAdditions.val2Lin; + axis.setExtremes = function (newMin, newMax, redraw, animation, eventArguments) { + // If trying to set extremes inside a break, extend min to + // after, and max to before the break ( #3857 ) + if (brokenAxis.hasBreaks) { + var axisBreak, + breaks = this.options.breaks; + while ((axisBreak = brokenAxis.findBreakAt(newMin, breaks))) { + newMin = axisBreak.to; + } + while ((axisBreak = brokenAxis.findBreakAt(newMax, breaks))) { + newMax = axisBreak.from; + } + // If both min and max is within the same break. + if (newMax < newMin) { + newMax = newMin; + } + } + Axis.prototype.setExtremes.call(this, newMin, newMax, redraw, animation, eventArguments); + }; + axis.setAxisTranslation = function (saveOld) { + Axis.prototype.setAxisTranslation.call(this, saveOld); + brokenAxis.unitLength = null; + if (brokenAxis.hasBreaks) { + var breaks = axis.options.breaks || [], + // Temporary one: + breakArrayT = [], + breakArray = [], + length = 0, + inBrk, + repeat, + min = axis.userMin || axis.min, + max = axis.userMax || axis.max, + pointRangePadding = pick(axis.pointRangePadding, 0), + start, + i; + // Min & max check (#4247) + breaks.forEach(function (brk) { + repeat = brk.repeat || Infinity; + if (BrokenAxisAdditions.isInBreak(brk, min)) { + min += + (brk.to % repeat) - + (min % repeat); + } + if (BrokenAxisAdditions.isInBreak(brk, max)) { + max -= + (max % repeat) - + (brk.from % repeat); + } + }); + // Construct an array holding all breaks in the axis + breaks.forEach(function (brk) { + start = brk.from; + repeat = brk.repeat || Infinity; + while (start - repeat > min) { + start -= repeat; + } + while (start < min) { + start += repeat; + } + for (i = start; i < max; i += repeat) { + breakArrayT.push({ + value: i, + move: 'in' + }); + breakArrayT.push({ + value: i + (brk.to - brk.from), + move: 'out', + size: brk.breakSize + }); + } + }); + breakArrayT.sort(function (a, b) { + return ((a.value === b.value) ? + ((a.move === 'in' ? 0 : 1) - + (b.move === 'in' ? 0 : 1)) : + a.value - b.value); + }); + // Simplify the breaks + inBrk = 0; + start = min; + breakArrayT.forEach(function (brk) { + inBrk += (brk.move === 'in' ? 1 : -1); + if (inBrk === 1 && brk.move === 'in') { + start = brk.value; + } + if (inBrk === 0) { + breakArray.push({ + from: start, + to: brk.value, + len: brk.value - start - (brk.size || 0) + }); + length += brk.value - start - (brk.size || 0); + } + }); + /** + * HC <= 8 backwards compatibility, used by demo samples. + * @deprecated + * @private + * @requires modules/broken-axis + */ + axis.breakArray = brokenAxis.breakArray = breakArray; + // Used with staticScale, and below the actual axis length, + // when breaks are substracted. + brokenAxis.unitLength = max - min - length + pointRangePadding; + fireEvent(axis, 'afterBreaks'); + if (axis.staticScale) { + axis.transA = axis.staticScale; + } + else if (brokenAxis.unitLength) { + axis.transA *= + (max - axis.min + pointRangePadding) / + brokenAxis.unitLength; + } + if (pointRangePadding) { + axis.minPixelPadding = + axis.transA * axis.minPointOffset; + } + axis.min = min; + axis.max = max; + } + }; + } + if (pick(redraw, true)) { + axis.chart.redraw(); + } + }; + return BrokenAxisAdditions; + }()); + /** + * Axis with support of broken data rows. + * @private + * @class + */ + var BrokenAxis = /** @class */ (function () { + function BrokenAxis() { + } + /** + * Adds support for broken axes. + * @private + */ + BrokenAxis.compose = function (AxisClass, SeriesClass) { + AxisClass.keepProps.push('brokenAxis'); + var seriesProto = Series.prototype; + /** + * @private + */ + seriesProto.drawBreaks = function (axis, keys) { + var series = this, + points = series.points, + breaks, + threshold, + eventName, + y; + if (axis && // #5950 + axis.brokenAxis && + axis.brokenAxis.hasBreaks) { + var brokenAxis_1 = axis.brokenAxis; + keys.forEach(function (key) { + breaks = brokenAxis_1 && brokenAxis_1.breakArray || []; + threshold = axis.isXAxis ? + axis.min : + pick(series.options.threshold, axis.min); + points.forEach(function (point) { + y = pick(point['stack' + key.toUpperCase()], point[key]); + breaks.forEach(function (brk) { + if (isNumber(threshold) && isNumber(y)) { + eventName = false; + if ((threshold < brk.from && y > brk.to) || + (threshold > brk.from && y < brk.from)) { + eventName = 'pointBreak'; + } + else if ((threshold < brk.from && y > brk.from && y < brk.to) || + (threshold > brk.from && y > brk.to && y < brk.from)) { + eventName = 'pointInBreak'; + } + if (eventName) { + fireEvent(axis, eventName, { point: point, brk: brk }); + } + } + }); + }); + }); + } + }; + /** + * Extend getGraphPath by identifying gaps in the data so that we can + * draw a gap in the line or area. This was moved from ordinal axis + * module to broken axis module as of #5045. + * + * @private + * @function Highcharts.Series#gappedPath + * + * @return {Highcharts.SVGPathArray} + * Gapped path + */ + seriesProto.gappedPath = function () { + var currentDataGrouping = this.currentDataGrouping, + groupingSize = currentDataGrouping && currentDataGrouping.gapSize, + gapSize = this.options.gapSize, + points = this.points.slice(), + i = points.length - 1, + yAxis = this.yAxis, + stack; + /** + * Defines when to display a gap in the graph, together with the + * [gapUnit](plotOptions.series.gapUnit) option. + * + * In case when `dataGrouping` is enabled, points can be grouped + * into a larger time span. This can make the grouped points to have + * a greater distance than the absolute value of `gapSize` property, + * which will result in disappearing graph completely. To prevent + * this situation the mentioned distance between grouped points is + * used instead of previously defined `gapSize`. + * + * In practice, this option is most often used to visualize gaps in + * time series. In a stock chart, intraday data is available for + * daytime hours, while gaps will appear in nights and weekends. + * + * @see [gapUnit](plotOptions.series.gapUnit) + * @see [xAxis.breaks](#xAxis.breaks) + * + * @sample {highstock} stock/plotoptions/series-gapsize/ + * Setting the gap size to 2 introduces gaps for weekends + * in daily datasets. + * + * @type {number} + * @default 0 + * @product highstock + * @requires modules/broken-axis + * @apioption plotOptions.series.gapSize + */ + /** + * Together with [gapSize](plotOptions.series.gapSize), this option + * defines where to draw gaps in the graph. + * + * When the `gapUnit` is `"relative"` (default), a gap size of 5 + * means that if the distance between two points is greater than + * 5 times that of the two closest points, the graph will be broken. + * + * When the `gapUnit` is `"value"`, the gap is based on absolute + * axis values, which on a datetime axis is milliseconds. This also + * applies to the navigator series that inherits gap options from + * the base series. + * + * @see [gapSize](plotOptions.series.gapSize) + * + * @type {string} + * @default relative + * @since 5.0.13 + * @product highstock + * @validvalue ["relative", "value"] + * @requires modules/broken-axis + * @apioption plotOptions.series.gapUnit + */ + if (gapSize && i > 0) { // #5008 + // Gap unit is relative + if (this.options.gapUnit !== 'value') { + gapSize *= this.basePointRange; + } + // Setting a new gapSize in case dataGrouping is enabled (#7686) + if (groupingSize && + groupingSize > gapSize && + // Except when DG is forced (e.g. from other series) + // and has lower granularity than actual points (#11351) + groupingSize >= this.basePointRange) { + gapSize = groupingSize; + } + // extension for ordinal breaks + var current = void 0, + next = void 0; + while (i--) { + // Reassign next if it is not visible + if (!(next && next.visible !== false)) { + next = points[i + 1]; + } + current = points[i]; + // Skip iteration if one of the points is not visible + if (next.visible === false || current.visible === false) { + continue; + } + if (next.x - current.x > gapSize) { + var xRange = (current.x + next.x) / 2; + points.splice(// insert after this one + i + 1, 0, { + isNull: true, + x: xRange + }); + // For stacked chart generate empty stack items, #6546 + if (yAxis.stacking && this.options.stacking) { + stack = yAxis.stacking.stacks[this.stackKey][xRange] = + new StackItem(yAxis, yAxis.options + .stackLabels, false, xRange, this.stack); + stack.total = 0; + } + } + // Assign current to next for the upcoming iteration + next = current; + } + } + // Call base method + return this.getGraphPath(points); + }; + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'init', function () { + var axis = this; + if (!axis.brokenAxis) { + axis.brokenAxis = new BrokenAxisAdditions(axis); + } + }); + addEvent(AxisClass, 'afterInit', function () { + if (typeof this.brokenAxis !== 'undefined') { + this.brokenAxis.setBreaks(this.options.breaks, false); + } + }); + addEvent(AxisClass, 'afterSetTickPositions', function () { + var axis = this; + var brokenAxis = axis.brokenAxis; + if (brokenAxis && + brokenAxis.hasBreaks) { + var tickPositions = this.tickPositions, + info = this.tickPositions.info, + newPositions = [], + i; + for (i = 0; i < tickPositions.length; i++) { + if (!brokenAxis.isInAnyBreak(tickPositions[i])) { + newPositions.push(tickPositions[i]); + } + } + this.tickPositions = newPositions; + this.tickPositions.info = info; + } + }); + // Force Axis to be not-ordinal when breaks are defined + addEvent(AxisClass, 'afterSetOptions', function () { + if (this.brokenAxis && this.brokenAxis.hasBreaks) { + this.options.ordinal = false; + } + }); + addEvent(SeriesClass, 'afterGeneratePoints', function () { + var _a = this, + isDirty = _a.isDirty, + connectNulls = _a.options.connectNulls, + points = _a.points, + xAxis = _a.xAxis, + yAxis = _a.yAxis; + // Set, or reset visibility of the points. Axis.setBreaks marks the + // series as isDirty + if (isDirty) { + var i = points.length; + while (i--) { + var point = points[i]; + // Respect nulls inside the break (#4275) + var nullGap = point.y === null && connectNulls === false; + var isPointInBreak = (!nullGap && ((xAxis && + xAxis.brokenAxis && + xAxis.brokenAxis.isInAnyBreak(point.x, + true)) || (yAxis && + yAxis.brokenAxis && + yAxis.brokenAxis.isInAnyBreak(point.y, + true)))); + // Set point.visible if in any break. + // If not in break, reset visible to original value. + point.visible = isPointInBreak ? + false : + point.options.visible !== false; + } + } + }); + addEvent(SeriesClass, 'afterRender', function drawPointsWrapped() { + this.drawBreaks(this.xAxis, ['x']); + this.drawBreaks(this.yAxis, pick(this.pointArrayMap, ['y'])); + }); + }; + return BrokenAxis; + }()); + BrokenAxis.compose(Axis, Series); // @todo remove automatism + + return BrokenAxis; + }); + _registerModule(_modules, 'Core/Axis/TreeGridAxis.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Axis/Tick.js'], _modules['Gantt/Tree.js'], _modules['Core/Axis/TreeGridTick.js'], _modules['Mixins/TreeSeries.js'], _modules['Core/Utilities.js']], function (Axis, Tick, Tree, TreeGridTick, mixinTreeSeries, U) { + /* * + * + * (c) 2016 Highsoft AS + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var getLevelOptions = mixinTreeSeries.getLevelOptions; + var addEvent = U.addEvent, + find = U.find, + fireEvent = U.fireEvent, + isNumber = U.isNumber, + isObject = U.isObject, + isString = U.isString, + merge = U.merge, + pick = U.pick, + wrap = U.wrap; + /** + * @private + */ + var TreeGridAxis; + (function (TreeGridAxis) { + /* * + * + * Interfaces + * + * */ + /* * + * + * Variables + * + * */ + var applied = false; + /* * + * + * Functions + * + * */ + /** + * @private + */ + function compose(AxisClass) { + if (!applied) { + wrap(AxisClass.prototype, 'generateTick', wrapGenerateTick); + wrap(AxisClass.prototype, 'getMaxLabelDimensions', wrapGetMaxLabelDimensions); + wrap(AxisClass.prototype, 'init', wrapInit); + wrap(AxisClass.prototype, 'setTickInterval', wrapSetTickInterval); + TreeGridTick.compose(Tick); + applied = true; + } + } + TreeGridAxis.compose = compose; + /** + * @private + */ + function getBreakFromNode(node, max) { + var from = node.collapseStart || 0, + to = node.collapseEnd || 0; + // In broken-axis, the axis.max is minimized until it is not within a + // break. Therefore, if break.to is larger than axis.max, the axis.to + // should not add the 0.5 axis.tickMarkOffset, to avoid adding a break + // larger than axis.max. + // TODO consider simplifying broken-axis and this might solve itself + if (to >= max) { + from -= 0.5; + } + return { + from: from, + to: to, + showPoints: false + }; + } + /** + * Creates a tree structure of the data, and the treegrid. Calculates + * categories, and y-values of points based on the tree. + * + * @private + * @function getTreeGridFromData + * + * @param {Array} data + * All the data points to display in the axis. + * + * @param {boolean} uniqueNames + * Wether or not the data node with the same name should share grid cell. If + * true they do share cell. False by default. + * + * @param {number} numberOfSeries + * + * @return {object} + * Returns an object containing categories, mapOfIdToNode, + * mapOfPosToGridNode, and tree. + * + * @todo There should be only one point per line. + * @todo It should be optional to have one category per point, or merge + * cells + * @todo Add unit-tests. + */ + function getTreeGridFromData(data, uniqueNames, numberOfSeries) { + var categories = [], + collapsedNodes = [], + mapOfIdToNode = {}, + mapOfPosToGridNode = {}, + posIterator = -1, + uniqueNamesEnabled = typeof uniqueNames === 'boolean' ? uniqueNames : false, + tree; + // Build the tree from the series data. + var treeParams = { + // After the children has been created. + after: function (node) { + var gridNode = mapOfPosToGridNode[node.pos], + height = 0, + descendants = 0; + gridNode.children.forEach(function (child) { + descendants += (child.descendants || 0) + 1; + height = Math.max((child.height || 0) + 1, height); + }); + gridNode.descendants = descendants; + gridNode.height = height; + if (gridNode.collapsed) { + collapsedNodes.push(gridNode); + } + }, + // Before the children has been created. + before: function (node) { + var data = isObject(node.data, + true) ? node.data : {}, + name = isString(data.name) ? data.name : '', + parentNode = mapOfIdToNode[node.parent], + parentGridNode = (isObject(parentNode, + true) ? + mapOfPosToGridNode[parentNode.pos] : + null), + hasSameName = function (x) { + return x.name === name; + }, gridNode, pos; + // If not unique names, look for sibling node with the same name + if (uniqueNamesEnabled && + isObject(parentGridNode, true) && + !!(gridNode = find(parentGridNode.children, hasSameName))) { + // If there is a gridNode with the same name, reuse position + pos = gridNode.pos; + // Add data node to list of nodes in the grid node. + gridNode.nodes.push(node); + } + else { + // If it is a new grid node, increment position. + pos = posIterator++; + } + // Add new grid node to map. + if (!mapOfPosToGridNode[pos]) { + mapOfPosToGridNode[pos] = gridNode = { + depth: parentGridNode ? parentGridNode.depth + 1 : 0, + name: name, + nodes: [node], + children: [], + pos: pos + }; + // If not root, then add name to categories. + if (pos !== -1) { + categories.push(name); + } + // Add name to list of children. + if (isObject(parentGridNode, true)) { + parentGridNode.children.push(gridNode); + } + } + // Add data node to map + if (isString(node.id)) { + mapOfIdToNode[node.id] = node; + } + // If one of the points are collapsed, then start the grid node + // in collapsed state. + if (gridNode && + data.collapsed === true) { + gridNode.collapsed = true; + } + // Assign pos to data node + node.pos = pos; + } + }; + var updateYValuesAndTickPos = function (map, + numberOfSeries) { + var setValues = function (gridNode, + start, + result) { + var nodes = gridNode.nodes, + end = start + (start === -1 ? 0 : numberOfSeries - 1), + diff = (end - start) / 2, + padding = 0.5, + pos = start + diff; + nodes.forEach(function (node) { + var data = node.data; + if (isObject(data, true)) { + // Update point + data.y = start + (data.seriesIndex || 0); + // Remove the property once used + delete data.seriesIndex; + } + node.pos = pos; + }); + result[pos] = gridNode; + gridNode.pos = pos; + gridNode.tickmarkOffset = diff + padding; + gridNode.collapseStart = end + padding; + gridNode.children.forEach(function (child) { + setValues(child, end + 1, result); + end = (child.collapseEnd || 0) - padding; + }); + // Set collapseEnd to the end of the last child node. + gridNode.collapseEnd = end + padding; + return result; + }; + return setValues(map['-1'], -1, {}); + }; + // Create tree from data + tree = Tree.getTree(data, treeParams); + // Update y values of data, and set calculate tick positions. + mapOfPosToGridNode = updateYValuesAndTickPos(mapOfPosToGridNode, numberOfSeries); + // Return the resulting data. + return { + categories: categories, + mapOfIdToNode: mapOfIdToNode, + mapOfPosToGridNode: mapOfPosToGridNode, + collapsedNodes: collapsedNodes, + tree: tree + }; + } + /** + * Builds the tree of categories and calculates its positions. + * @private + * @param {object} e Event object + * @param {object} e.target The chart instance which the event was fired on. + * @param {object[]} e.target.axes The axes of the chart. + */ + function onBeforeRender(e) { + var chart = e.target, + axes = chart.axes; + axes.filter(function (axis) { + return axis.options.type === 'treegrid'; + }).forEach(function (axis) { + var options = axis.options || {}, + labelOptions = options.labels, + uniqueNames = options.uniqueNames, + numberOfSeries = 0, + isDirty, + data, + treeGrid, + max = options.max; + // Check whether any of series is rendering for the first time, + // visibility has changed, or its data is dirty, + // and only then update. #10570, #10580 + // Also check if mapOfPosToGridNode exists. #10887 + isDirty = (!axis.treeGrid.mapOfPosToGridNode || + axis.series.some(function (series) { + return !series.hasRendered || + series.isDirtyData || + series.isDirty; + })); + if (isDirty) { + // Concatenate data from all series assigned to this axis. + data = axis.series.reduce(function (arr, s) { + if (s.visible) { + // Push all data to array + (s.options.data || []).forEach(function (data) { + if (isObject(data, true)) { + // Set series index on data. Removed again + // after use. + data.seriesIndex = numberOfSeries; + arr.push(data); + } + }); + // Increment series index + if (uniqueNames === true) { + numberOfSeries++; + } + } + return arr; + }, []); + // If max is higher than set data - add a + // dummy data to render categories #10779 + if (max && data.length < max) { + for (var i = data.length; i <= max; i++) { + data.push({ + // Use the zero-width character + // to avoid conflict with uniqueNames + name: i + '\u200B' + }); + } + } + // setScale is fired after all the series is initialized, + // which is an ideal time to update the axis.categories. + treeGrid = getTreeGridFromData(data, uniqueNames || false, (uniqueNames === true) ? numberOfSeries : 1); + // Assign values to the axis. + axis.categories = treeGrid.categories; + axis.treeGrid.mapOfPosToGridNode = treeGrid.mapOfPosToGridNode; + axis.hasNames = true; + axis.treeGrid.tree = treeGrid.tree; + // Update yData now that we have calculated the y values + axis.series.forEach(function (series) { + var data = (series.options.data || []).map(function (d) { + return isObject(d, + true) ? merge(d) : d; + }); + // Avoid destroying points when series is not visible + if (series.visible) { + series.setData(data, false); + } + }); + // Calculate the label options for each level in the tree. + axis.treeGrid.mapOptionsToLevel = + getLevelOptions({ + defaults: labelOptions, + from: 1, + levels: labelOptions && labelOptions.levels, + to: axis.treeGrid.tree && axis.treeGrid.tree.height + }); + // Setting initial collapsed nodes + if (e.type === 'beforeRender') { + axis.treeGrid.collapsedNodes = treeGrid.collapsedNodes; + } + } + }); + } + /** + * Generates a tick for initial positioning. + * + * @private + * @function Highcharts.GridAxis#generateTick + * + * @param {Function} proceed + * The original generateTick function. + * + * @param {number} pos + * The tick position in axis values. + */ + function wrapGenerateTick(proceed, pos) { + var axis = this, + mapOptionsToLevel = axis.treeGrid.mapOptionsToLevel || {}, + isTreeGrid = axis.options.type === 'treegrid', + ticks = axis.ticks; + var tick = ticks[pos], + levelOptions, + options, + gridNode; + if (isTreeGrid && + axis.treeGrid.mapOfPosToGridNode) { + gridNode = axis.treeGrid.mapOfPosToGridNode[pos]; + levelOptions = mapOptionsToLevel[gridNode.depth]; + if (levelOptions) { + options = { + labels: levelOptions + }; + } + if (!tick) { + ticks[pos] = tick = + new Tick(axis, pos, void 0, void 0, { + category: gridNode.name, + tickmarkOffset: gridNode.tickmarkOffset, + options: options + }); + } + else { + // update labels depending on tick interval + tick.parameters.category = gridNode.name; + tick.options = options; + tick.addLabel(); + } + } + else { + proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); + } + } + /** + * Override to add indentation to axis.maxLabelDimensions. + * + * @private + * @function Highcharts.GridAxis#getMaxLabelDimensions + * + * @param {Function} proceed + * The original function + */ + function wrapGetMaxLabelDimensions(proceed) { + var axis = this, + options = axis.options, + labelOptions = options && options.labels, + indentation = (labelOptions && isNumber(labelOptions.indentation) ? + labelOptions.indentation : + 0), + retVal = proceed.apply(axis, + Array.prototype.slice.call(arguments, 1)), + isTreeGrid = axis.options.type === 'treegrid'; + var treeDepth; + if (isTreeGrid && axis.treeGrid.mapOfPosToGridNode) { + treeDepth = axis.treeGrid.mapOfPosToGridNode[-1].height || 0; + retVal.width += indentation * (treeDepth - 1); + } + return retVal; + } + /** + * @private + */ + function wrapInit(proceed, chart, userOptions) { + var axis = this, + isTreeGrid = userOptions.type === 'treegrid'; + if (!axis.treeGrid) { + axis.treeGrid = new Additions(axis); + } + // Set default and forced options for TreeGrid + if (isTreeGrid) { + // Add event for updating the categories of a treegrid. + // NOTE Preferably these events should be set on the axis. + addEvent(chart, 'beforeRender', onBeforeRender); + addEvent(chart, 'beforeRedraw', onBeforeRender); + // Add new collapsed nodes on addseries + addEvent(chart, 'addSeries', function (e) { + if (e.options.data) { + var treeGrid = getTreeGridFromData(e.options.data, + userOptions.uniqueNames || false, 1); + axis.treeGrid.collapsedNodes = (axis.treeGrid.collapsedNodes || []).concat(treeGrid.collapsedNodes); + } + }); + // Collapse all nodes in axis.treegrid.collapsednodes + // where collapsed equals true. + addEvent(axis, 'foundExtremes', function () { + if (axis.treeGrid.collapsedNodes) { + axis.treeGrid.collapsedNodes.forEach(function (node) { + var breaks = axis.treeGrid.collapse(node); + if (axis.brokenAxis) { + axis.brokenAxis.setBreaks(breaks, false); + // remove the node from the axis collapsedNodes + if (axis.treeGrid.collapsedNodes) { + axis.treeGrid.collapsedNodes = axis.treeGrid.collapsedNodes.filter(function (n) { + return node.collapseStart !== n.collapseStart || + node.collapseEnd !== n.collapseEnd; + }); + } + } + }); + } + }); + // If staticScale is not defined on the yAxis + // and chart height is set, set axis.isDirty + // to ensure collapsing works (#12012) + addEvent(axis, 'afterBreaks', function () { + var _a; + if (axis.coll === 'yAxis' && !axis.staticScale && ((_a = axis.chart.options.chart) === null || _a === void 0 ? void 0 : _a.height)) { + axis.isDirty = true; + } + }); + userOptions = merge({ + // Default options + grid: { + enabled: true + }, + // TODO: add support for align in treegrid. + labels: { + align: 'left', + /** + * Set options on specific levels in a tree grid axis. Takes + * precedence over labels options. + * + * @sample {gantt} gantt/treegrid-axis/labels-levels + * Levels on TreeGrid Labels + * + * @type {Array<*>} + * @product gantt + * @apioption yAxis.labels.levels + * + * @private + */ + levels: [{ + /** + * Specify the level which the options within this object + * applies to. + * + * @type {number} + * @product gantt + * @apioption yAxis.labels.levels.level + * + * @private + */ + level: void 0 + }, { + level: 1, + /** + * @type {Highcharts.CSSObject} + * @product gantt + * @apioption yAxis.labels.levels.style + * + * @private + */ + style: { + /** @ignore-option */ + fontWeight: 'bold' + } + }], + /** + * The symbol for the collapse and expand icon in a + * treegrid. + * + * @product gantt + * @optionparent yAxis.labels.symbol + * + * @private + */ + symbol: { + /** + * The symbol type. Points to a definition function in + * the `Highcharts.Renderer.symbols` collection. + * + * @type {Highcharts.SymbolKeyValue} + * + * @private + */ + type: 'triangle', + x: -5, + y: -5, + height: 10, + width: 10, + padding: 5 + } + }, + uniqueNames: false + }, userOptions, { + // Forced options + reversed: true, + // grid.columns is not supported in treegrid + grid: { + columns: void 0 + } + }); + } + // Now apply the original function with the original arguments, + // which are sliced off this function's arguments + proceed.apply(axis, [chart, userOptions]); + if (isTreeGrid) { + axis.hasNames = true; + axis.options.showLastLabel = true; + } + } + /** + * Set the tick positions, tickInterval, axis min and max. + * + * @private + * @function Highcharts.GridAxis#setTickInterval + * + * @param {Function} proceed + * The original setTickInterval function. + */ + function wrapSetTickInterval(proceed) { + var axis = this, + options = axis.options, + isTreeGrid = options.type === 'treegrid'; + if (isTreeGrid) { + axis.min = pick(axis.userMin, options.min, axis.dataMin); + axis.max = pick(axis.userMax, options.max, axis.dataMax); + fireEvent(axis, 'foundExtremes'); + // setAxisTranslation modifies the min and max according to + // axis breaks. + axis.setAxisTranslation(true); + axis.tickmarkOffset = 0.5; + axis.tickInterval = 1; + axis.tickPositions = axis.treeGrid.mapOfPosToGridNode ? + axis.treeGrid.getTickPositions() : + []; + } + else { + proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); + } + } + /* * + * + * Classes + * + * */ + /** + * @private + * @class + */ + var Additions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + /** + * @private + */ + function Additions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Calculates the new axis breaks to collapse a node. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {Highcharts.GridNode} node + * The node to collapse. + * + * @param {number} pos + * The tick position to collapse. + * + * @return {Array} + * Returns an array of the new breaks for the axis. + */ + Additions.prototype.collapse = function (node) { + var axis = this.axis, + breaks = (axis.options.breaks || []), + obj = getBreakFromNode(node, + axis.max); + breaks.push(obj); + return breaks; + }; + /** + * Calculates the new axis breaks to expand a node. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {Highcharts.GridNode} node + * The node to expand. + * + * @param {number} pos + * The tick position to expand. + * + * @return {Array} + * Returns an array of the new breaks for the axis. + */ + Additions.prototype.expand = function (node) { + var axis = this.axis, + breaks = (axis.options.breaks || []), + obj = getBreakFromNode(node, + axis.max); + // Remove the break from the axis breaks array. + return breaks.reduce(function (arr, b) { + if (b.to !== obj.to || b.from !== obj.from) { + arr.push(b); + } + return arr; + }, []); + }; + /** + * Creates a list of positions for the ticks on the axis. Filters out + * positions that are outside min and max, or is inside an axis break. + * + * @private + * + * @return {Array} + * List of positions. + */ + Additions.prototype.getTickPositions = function () { + var axis = this.axis; + return Object.keys(axis.treeGrid.mapOfPosToGridNode || {}).reduce(function (arr, key) { + var pos = +key; + if (axis.min <= pos && + axis.max >= pos && + !(axis.brokenAxis && axis.brokenAxis.isInAnyBreak(pos))) { + arr.push(pos); + } + return arr; + }, []); + }; + /** + * Check if a node is collapsed. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {object} node + * The node to check if is collapsed. + * + * @param {number} pos + * The tick position to collapse. + * + * @return {boolean} + * Returns true if collapsed, false if expanded. + */ + Additions.prototype.isCollapsed = function (node) { + var axis = this.axis, + breaks = (axis.options.breaks || []), + obj = getBreakFromNode(node, + axis.max); + return breaks.some(function (b) { + return b.from === obj.from && b.to === obj.to; + }); + }; + /** + * Calculates the new axis breaks after toggling the collapse/expand + * state of a node. If it is collapsed it will be expanded, and if it is + * exapended it will be collapsed. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {Highcharts.GridNode} node + * The node to toggle. + * + * @return {Array} + * Returns an array of the new breaks for the axis. + */ + Additions.prototype.toggleCollapse = function (node) { + return (this.isCollapsed(node) ? + this.expand(node) : + this.collapse(node)); + }; + return Additions; + }()); + TreeGridAxis.Additions = Additions; + })(TreeGridAxis || (TreeGridAxis = {})); + // Make utility functions available for testing. + Axis.prototype.utils = { + getNode: Tree.getNode + }; + TreeGridAxis.compose(Axis); + + return TreeGridAxis; + }); + _registerModule(_modules, 'Extensions/CurrentDateIndication.js', [_modules['Core/Globals.js'], _modules['Core/Options.js'], _modules['Core/Utilities.js'], _modules['Core/Axis/PlotLineOrBand.js']], function (H, O, U, PlotLineOrBand) { + /* * + * + * (c) 2016-2020 Highsoft AS + * + * Author: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var dateFormat = O.dateFormat; + var addEvent = U.addEvent, + merge = U.merge, + wrap = U.wrap; + var Axis = H.Axis; + var defaultConfig = { + /** + * Show an indicator on the axis for the current date and time. Can be a + * boolean or a configuration object similar to + * [xAxis.plotLines](#xAxis.plotLines). + * + * @sample gantt/current-date-indicator/demo + * Current date indicator enabled + * @sample gantt/current-date-indicator/object-config + * Current date indicator with custom options + * + * @declare Highcharts.AxisCurrentDateIndicatorOptions + * @type {boolean|*} + * @default true + * @extends xAxis.plotLines + * @excluding value + * @product gantt + * @apioption xAxis.currentDateIndicator + */ + currentDateIndicator: true, + color: '#ccd6eb', + width: 2, + /** + * @declare Highcharts.AxisCurrentDateIndicatorLabelOptions + */ + label: { + /** + * Format of the label. This options is passed as the fist argument to + * [dateFormat](/class-reference/Highcharts#dateFormat) function. + * + * @type {string} + * @default '%a, %b %d %Y, %H:%M' + * @product gantt + * @apioption xAxis.currentDateIndicator.label.format + */ + format: '%a, %b %d %Y, %H:%M', + formatter: function (value, format) { + return dateFormat(format, value); + }, + rotation: 0, + /** + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + fontSize: '10px' + } + } + }; + /* eslint-disable no-invalid-this */ + addEvent(Axis, 'afterSetOptions', function () { + var options = this.options, + cdiOptions = options.currentDateIndicator; + if (cdiOptions) { + cdiOptions = typeof cdiOptions === 'object' ? + merge(defaultConfig, cdiOptions) : merge(defaultConfig); + cdiOptions.value = new Date(); + if (!options.plotLines) { + options.plotLines = []; + } + options.plotLines.push(cdiOptions); + } + }); + addEvent(PlotLineOrBand, 'render', function () { + // If the label already exists, update its text + if (this.label) { + this.label.attr({ + text: this.getLabelText(this.options.label) + }); + } + }); + wrap(PlotLineOrBand.prototype, 'getLabelText', function (defaultMethod, defaultLabelOptions) { + var options = this.options; + if (options.currentDateIndicator && options.label && + typeof options.label.formatter === 'function') { + options.value = new Date(); + return options.label.formatter + .call(this, options.value, options.label.format); + } + return defaultMethod.call(this, defaultLabelOptions); + }); + + }); + _registerModule(_modules, 'Extensions/StaticScale.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) { + /* * + * + * (c) 2016-2020 Torstein Honsi, Lars Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + defined = U.defined, + isNumber = U.isNumber, + pick = U.pick; + var Chart = H.Chart; + /* eslint-disable no-invalid-this */ + /** + * For vertical axes only. Setting the static scale ensures that each tick unit + * is translated into a fixed pixel height. For example, setting the static + * scale to 24 results in each Y axis category taking up 24 pixels, and the + * height of the chart adjusts. Adding or removing items will make the chart + * resize. + * + * @sample gantt/xrange-series/demo/ + * X-range series with static scale + * + * @type {number} + * @default 50 + * @since 6.2.0 + * @product gantt + * @apioption yAxis.staticScale + */ + addEvent(H.Axis, 'afterSetOptions', function () { + var chartOptions = this.chart.options && this.chart.options.chart; + if (!this.horiz && + isNumber(this.options.staticScale) && + (!chartOptions.height || + (chartOptions.scrollablePlotArea && + chartOptions.scrollablePlotArea.minHeight))) { + this.staticScale = this.options.staticScale; + } + }); + Chart.prototype.adjustHeight = function () { + if (this.redrawTrigger !== 'adjustHeight') { + (this.axes || []).forEach(function (axis) { + var chart = axis.chart, + animate = !!chart.initiatedScale && + chart.options.animation, + staticScale = axis.options.staticScale, + height, + diff; + if (axis.staticScale && defined(axis.min)) { + height = pick(axis.brokenAxis && axis.brokenAxis.unitLength, axis.max + axis.tickInterval - axis.min) * staticScale; + // Minimum height is 1 x staticScale. + height = Math.max(height, staticScale); + diff = height - chart.plotHeight; + if (Math.abs(diff) >= 1) { + chart.plotHeight = height; + chart.redrawTrigger = 'adjustHeight'; + chart.setSize(void 0, chart.chartHeight + diff, animate); + } + // Make sure clip rects have the right height before initial + // animation. + axis.series.forEach(function (series) { + var clipRect = series.sharedClipKey && + chart[series.sharedClipKey]; + if (clipRect) { + clipRect.attr({ + height: chart.plotHeight + }); + } + }); + } + }); + this.initiatedScale = true; + } + this.redrawTrigger = null; + }; + addEvent(Chart, 'render', Chart.prototype.adjustHeight); + + }); + _registerModule(_modules, 'Extensions/ArrowSymbols.js', [_modules['Core/Renderer/SVG/SVGRenderer.js']], function (SVGRenderer) { + /* * + * + * (c) 2017 Highsoft AS + * Authors: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Creates an arrow symbol. Like a triangle, except not filled. + * ``` + * o + * o + * o + * o + * o + * o + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + SVGRenderer.prototype.symbols.arrow = function (x, y, w, h) { + return [ + ['M', x, y + h / 2], + ['L', x + w, y], + ['L', x, y + h / 2], + ['L', x + w, y + h] + ]; + }; + /** + * Creates a half-width arrow symbol. Like a triangle, except not filled. + * ``` + * o + * o + * o + * o + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + SVGRenderer.prototype.symbols['arrow-half'] = function (x, y, w, h) { + return SVGRenderer.prototype.symbols.arrow(x, y, w / 2, h); + }; + /** + * Creates a left-oriented triangle. + * ``` + * o + * ooooooo + * ooooooooooooo + * ooooooo + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the triangle + * + * @param {number} y + * y position of the triangle + * + * @param {number} w + * width of the triangle + * + * @param {number} h + * height of the triangle + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + SVGRenderer.prototype.symbols['triangle-left'] = function (x, y, w, h) { + return [ + ['M', x + w, y], + ['L', x, y + h / 2], + ['L', x + w, y + h], + ['Z'] + ]; + }; + /** + * Alias function for triangle-left. + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + SVGRenderer.prototype.symbols['arrow-filled'] = SVGRenderer.prototype.symbols['triangle-left']; + /** + * Creates a half-width, left-oriented triangle. + * ``` + * o + * oooo + * ooooooo + * oooo + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the triangle + * + * @param {number} y + * y position of the triangle + * + * @param {number} w + * width of the triangle + * + * @param {number} h + * height of the triangle + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + SVGRenderer.prototype.symbols['triangle-left-half'] = function (x, y, w, h) { + return SVGRenderer.prototype.symbols['triangle-left'](x, y, w / 2, h); + }; + /** + * Alias function for triangle-left-half. + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + SVGRenderer.prototype.symbols['arrow-filled-half'] = SVGRenderer.prototype.symbols['triangle-left-half']; + + }); + _registerModule(_modules, 'Gantt/Connection.js', [_modules['Core/Globals.js'], _modules['Core/Options.js'], _modules['Core/Series/Point.js'], _modules['Core/Utilities.js']], function (H, O, Point, U) { + /* * + * + * (c) 2016 Highsoft AS + * Authors: Øystein Moseng, Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * The default pathfinder algorithm to use for a chart. It is possible to define + * your own algorithms by adding them to the + * `Highcharts.Pathfinder.prototype.algorithms` + * object before the chart has been created. + * + * The default algorithms are as follows: + * + * `straight`: Draws a straight line between the connecting + * points. Does not avoid other points when drawing. + * + * `simpleConnect`: Finds a path between the points using right angles + * only. Takes only starting/ending points into + * account, and will not avoid other points. + * + * `fastAvoid`: Finds a path between the points using right angles + * only. Will attempt to avoid other points, but its + * focus is performance over accuracy. Works well with + * less dense datasets. + * + * @typedef {"fastAvoid"|"simpleConnect"|"straight"|string} Highcharts.PathfinderTypeValue + */ + ''; // detach doclets above + var defaultOptions = O.defaultOptions; + var addEvent = U.addEvent, + defined = U.defined, + error = U.error, + extend = U.extend, + merge = U.merge, + objectEach = U.objectEach, + pick = U.pick, + splat = U.splat; + var deg2rad = H.deg2rad, + max = Math.max, + min = Math.min; + /* + @todo: + - Document how to write your own algorithms + - Consider adding a Point.pathTo method that wraps creating a connection + and rendering it + */ + // Set default Pathfinder options + extend(defaultOptions, { + /** + * The Pathfinder module allows you to define connections between any two + * points, represented as lines - optionally with markers for the start + * and/or end points. Multiple algorithms are available for calculating how + * the connecting lines are drawn. + * + * Connector functionality requires Highcharts Gantt to be loaded. In Gantt + * charts, the connectors are used to draw dependencies between tasks. + * + * @see [dependency](series.gantt.data.dependency) + * + * @sample gantt/pathfinder/demo + * Pathfinder connections + * + * @declare Highcharts.ConnectorsOptions + * @product gantt + * @optionparent connectors + */ + connectors: { + /** + * Enable connectors for this chart. Requires Highcharts Gantt. + * + * @type {boolean} + * @default true + * @since 6.2.0 + * @apioption connectors.enabled + */ + /** + * Set the default dash style for this chart's connecting lines. + * + * @type {string} + * @default solid + * @since 6.2.0 + * @apioption connectors.dashStyle + */ + /** + * Set the default color for this chart's Pathfinder connecting lines. + * Defaults to the color of the point being connected. + * + * @type {Highcharts.ColorString} + * @since 6.2.0 + * @apioption connectors.lineColor + */ + /** + * Set the default pathfinder margin to use, in pixels. Some Pathfinder + * algorithms attempt to avoid obstacles, such as other points in the + * chart. These algorithms use this margin to determine how close lines + * can be to an obstacle. The default is to compute this automatically + * from the size of the obstacles in the chart. + * + * To draw connecting lines close to existing points, set this to a low + * number. For more space around existing points, set this number + * higher. + * + * @sample gantt/pathfinder/algorithm-margin + * Small algorithmMargin + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.algorithmMargin + */ + /** + * Set the default pathfinder algorithm to use for this chart. It is + * possible to define your own algorithms by adding them to the + * Highcharts.Pathfinder.prototype.algorithms object before the chart + * has been created. + * + * The default algorithms are as follows: + * + * `straight`: Draws a straight line between the connecting + * points. Does not avoid other points when drawing. + * + * `simpleConnect`: Finds a path between the points using right angles + * only. Takes only starting/ending points into + * account, and will not avoid other points. + * + * `fastAvoid`: Finds a path between the points using right angles + * only. Will attempt to avoid other points, but its + * focus is performance over accuracy. Works well with + * less dense datasets. + * + * Default value: `straight` is used as default for most series types, + * while `simpleConnect` is used as default for Gantt series, to show + * dependencies between points. + * + * @sample gantt/pathfinder/demo + * Different types used + * + * @type {Highcharts.PathfinderTypeValue} + * @default undefined + * @since 6.2.0 + */ + type: 'straight', + /** + * Set the default pixel width for this chart's Pathfinder connecting + * lines. + * + * @since 6.2.0 + */ + lineWidth: 1, + /** + * Marker options for this chart's Pathfinder connectors. Note that + * this option is overridden by the `startMarker` and `endMarker` + * options. + * + * @declare Highcharts.ConnectorsMarkerOptions + * @since 6.2.0 + */ + marker: { + /** + * Set the radius of the connector markers. The default is + * automatically computed based on the algorithmMargin setting. + * + * Setting marker.width and marker.height will override this + * setting. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.radius + */ + /** + * Set the width of the connector markers. If not supplied, this + * is inferred from the marker radius. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.width + */ + /** + * Set the height of the connector markers. If not supplied, this + * is inferred from the marker radius. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.height + */ + /** + * Set the color of the connector markers. By default this is the + * same as the connector color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 6.2.0 + * @apioption connectors.marker.color + */ + /** + * Set the line/border color of the connector markers. By default + * this is the same as the marker color. + * + * @type {Highcharts.ColorString} + * @since 6.2.0 + * @apioption connectors.marker.lineColor + */ + /** + * Enable markers for the connectors. + */ + enabled: false, + /** + * Horizontal alignment of the markers relative to the points. + * + * @type {Highcharts.AlignValue} + */ + align: 'center', + /** + * Vertical alignment of the markers relative to the points. + * + * @type {Highcharts.VerticalAlignValue} + */ + verticalAlign: 'middle', + /** + * Whether or not to draw the markers inside the points. + */ + inside: false, + /** + * Set the line/border width of the pathfinder markers. + */ + lineWidth: 1 + }, + /** + * Marker options specific to the start markers for this chart's + * Pathfinder connectors. Overrides the generic marker options. + * + * @declare Highcharts.ConnectorsStartMarkerOptions + * @extends connectors.marker + * @since 6.2.0 + */ + startMarker: { + /** + * Set the symbol of the connector start markers. + */ + symbol: 'diamond' + }, + /** + * Marker options specific to the end markers for this chart's + * Pathfinder connectors. Overrides the generic marker options. + * + * @declare Highcharts.ConnectorsEndMarkerOptions + * @extends connectors.marker + * @since 6.2.0 + */ + endMarker: { + /** + * Set the symbol of the connector end markers. + */ + symbol: 'arrow-filled' + } + } + }); + /** + * Override Pathfinder connector options for a series. Requires Highcharts Gantt + * to be loaded. + * + * @declare Highcharts.SeriesConnectorsOptionsObject + * @extends connectors + * @since 6.2.0 + * @excluding enabled, algorithmMargin + * @product gantt + * @apioption plotOptions.series.connectors + */ + /** + * Connect to a point. This option can be either a string, referring to the ID + * of another point, or an object, or an array of either. If the option is an + * array, each element defines a connection. + * + * @sample gantt/pathfinder/demo + * Different connection types + * + * @declare Highcharts.XrangePointConnectorsOptionsObject + * @type {string|Array|*} + * @extends plotOptions.series.connectors + * @since 6.2.0 + * @excluding enabled + * @product gantt + * @requires highcharts-gantt + * @apioption series.xrange.data.connect + */ + /** + * The ID of the point to connect to. + * + * @type {string} + * @since 6.2.0 + * @product gantt + * @apioption series.xrange.data.connect.to + */ + /** + * Get point bounding box using plotX/plotY and shapeArgs. If using + * graphic.getBBox() directly, the bbox will be affected by animation. + * + * @private + * @function + * + * @param {Highcharts.Point} point + * The point to get BB of. + * + * @return {Highcharts.Dictionary|null} + * Result xMax, xMin, yMax, yMin. + */ + function getPointBB(point) { + var shapeArgs = point.shapeArgs, + bb; + // Prefer using shapeArgs (columns) + if (shapeArgs) { + return { + xMin: shapeArgs.x, + xMax: shapeArgs.x + shapeArgs.width, + yMin: shapeArgs.y, + yMax: shapeArgs.y + shapeArgs.height + }; + } + // Otherwise use plotX/plotY and bb + bb = point.graphic && point.graphic.getBBox(); + return bb ? { + xMin: point.plotX - bb.width / 2, + xMax: point.plotX + bb.width / 2, + yMin: point.plotY - bb.height / 2, + yMax: point.plotY + bb.height / 2 + } : null; + } + /** + * Calculate margin to place around obstacles for the pathfinder in pixels. + * Returns a minimum of 1 pixel margin. + * + * @private + * @function + * + * @param {Array} obstacles + * Obstacles to calculate margin from. + * + * @return {number} + * The calculated margin in pixels. At least 1. + */ + function calculateObstacleMargin(obstacles) { + var len = obstacles.length, + i = 0, + j, + obstacleDistance, + distances = [], + // Compute smallest distance between two rectangles + distance = function (a, + b, + bbMargin) { + // Count the distance even if we are slightly off + var margin = pick(bbMargin, 10), + yOverlap = a.yMax + margin > b.yMin - margin && + a.yMin - margin < b.yMax + margin, + xOverlap = a.xMax + margin > b.xMin - margin && + a.xMin - margin < b.xMax + margin, + xDistance = yOverlap ? (a.xMin > b.xMax ? a.xMin - b.xMax : b.xMin - a.xMax) : Infinity, + yDistance = xOverlap ? (a.yMin > b.yMax ? a.yMin - b.yMax : b.yMin - a.yMax) : Infinity; + // If the rectangles collide, try recomputing with smaller margin. + // If they collide anyway, discard the obstacle. + if (xOverlap && yOverlap) { + return (margin ? + distance(a, b, Math.floor(margin / 2)) : + Infinity); + } + return min(xDistance, yDistance); + }; + // Go over all obstacles and compare them to the others. + for (; i < len; ++i) { + // Compare to all obstacles ahead. We will already have compared this + // obstacle to the ones before. + for (j = i + 1; j < len; ++j) { + obstacleDistance = distance(obstacles[i], obstacles[j]); + // TODO: Magic number 80 + if (obstacleDistance < 80) { // Ignore large distances + distances.push(obstacleDistance); + } + } + } + // Ensure we always have at least one value, even in very spaceous charts + distances.push(80); + return max(Math.floor(distances.sort(function (a, b) { + return (a - b); + })[ + // Discard first 10% of the relevant distances, and then grab + // the smallest one. + Math.floor(distances.length / 10)] / 2 - 1 // Divide the distance by 2 and subtract 1. + ), 1 // 1 is the minimum margin + ); + } + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The Connection class. Used internally to represent a connection between two + * points. + * + * @private + * @class + * @name Highcharts.Connection + * + * @param {Highcharts.Point} from + * Connection runs from this Point. + * + * @param {Highcharts.Point} to + * Connection runs to this Point. + * + * @param {Highcharts.ConnectorsOptions} [options] + * Connection options. + */ + var Connection = /** @class */ (function () { + function Connection(from, to, options) { + /* * + * + * Properties + * + * */ + this.chart = void 0; + this.fromPoint = void 0; + this.graphics = void 0; + this.pathfinder = void 0; + this.toPoint = void 0; + this.init(from, to, options); + } + /** + * Initialize the Connection object. Used as constructor only. + * + * @function Highcharts.Connection#init + * + * @param {Highcharts.Point} from + * Connection runs from this Point. + * + * @param {Highcharts.Point} to + * Connection runs to this Point. + * + * @param {Highcharts.ConnectorsOptions} [options] + * Connection options. + */ + Connection.prototype.init = function (from, to, options) { + this.fromPoint = from; + this.toPoint = to; + this.options = options; + this.chart = from.series.chart; + this.pathfinder = this.chart.pathfinder; + }; + /** + * Add (or update) this connection's path on chart. Stores reference to the + * created element on this.graphics.path. + * + * @function Highcharts.Connection#renderPath + * + * @param {Highcharts.SVGPathArray} path + * Path to render, in array format. E.g. ['M', 0, 0, 'L', 10, 10] + * + * @param {Highcharts.SVGAttributes} [attribs] + * SVG attributes for the path. + * + * @param {Partial} [animation] + * Animation options for the rendering. + */ + Connection.prototype.renderPath = function (path, attribs, animation) { + var connection = this, + chart = this.chart, + styledMode = chart.styledMode, + pathfinder = chart.pathfinder, + animate = !chart.options.chart.forExport && animation !== false, + pathGraphic = connection.graphics && connection.graphics.path, + anim; + // Add the SVG element of the pathfinder group if it doesn't exist + if (!pathfinder.group) { + pathfinder.group = chart.renderer.g() + .addClass('highcharts-pathfinder-group') + .attr({ zIndex: -1 }) + .add(chart.seriesGroup); + } + // Shift the group to compensate for plot area. + // Note: Do this always (even when redrawing a path) to avoid issues + // when updating chart in a way that changes plot metrics. + pathfinder.group.translate(chart.plotLeft, chart.plotTop); + // Create path if does not exist + if (!(pathGraphic && pathGraphic.renderer)) { + pathGraphic = chart.renderer.path() + .add(pathfinder.group); + if (!styledMode) { + pathGraphic.attr({ + opacity: 0 + }); + } + } + // Set path attribs and animate to the new path + pathGraphic.attr(attribs); + anim = { d: path }; + if (!styledMode) { + anim.opacity = 1; + } + pathGraphic[animate ? 'animate' : 'attr'](anim, animation); + // Store reference on connection + this.graphics = this.graphics || {}; + this.graphics.path = pathGraphic; + }; + /** + * Calculate and add marker graphics for connection to the chart. The + * created/updated elements are stored on this.graphics.start and + * this.graphics.end. + * + * @function Highcharts.Connection#addMarker + * + * @param {string} type + * Marker type, either 'start' or 'end'. + * + * @param {Highcharts.ConnectorsMarkerOptions} options + * All options for this marker. Not calculated or merged with other + * options. + * + * @param {Highcharts.SVGPathArray} path + * Connection path in array format. This is used to calculate the + * rotation angle of the markers. + */ + Connection.prototype.addMarker = function (type, options, path) { + var connection = this, + chart = connection.fromPoint.series.chart, + pathfinder = chart.pathfinder, + renderer = chart.renderer, + point = (type === 'start' ? + connection.fromPoint : + connection.toPoint), + anchor = point.getPathfinderAnchorPoint(options), + markerVector, + radians, + rotation, + box, + width, + height, + pathVector, + segment; + if (!options.enabled) { + return; + } + // Last vector before start/end of path, used to get angle + if (type === 'start') { + segment = path[1]; + } + else { // 'end' + segment = path[path.length - 2]; + } + if (segment && segment[0] === 'M' || segment[0] === 'L') { + pathVector = { + x: segment[1], + y: segment[2] + }; + // Get angle between pathVector and anchor point and use it to + // create marker position. + radians = point.getRadiansToVector(pathVector, anchor); + markerVector = point.getMarkerVector(radians, options.radius, anchor); + // Rotation of marker is calculated from angle between pathVector + // and markerVector. + // (Note: + // Used to recalculate radians between markerVector and pathVector, + // but this should be the same as between pathVector and anchor.) + rotation = -radians / deg2rad; + if (options.width && options.height) { + width = options.width; + height = options.height; + } + else { + width = height = options.radius * 2; + } + // Add graphics object if it does not exist + connection.graphics = connection.graphics || {}; + box = { + x: markerVector.x - (width / 2), + y: markerVector.y - (height / 2), + width: width, + height: height, + rotation: rotation, + rotationOriginX: markerVector.x, + rotationOriginY: markerVector.y + }; + if (!connection.graphics[type]) { + // Create new marker element + connection.graphics[type] = renderer + .symbol(options.symbol) + .addClass('highcharts-point-connecting-path-' + type + '-marker') + .attr(box) + .add(pathfinder.group); + if (!renderer.styledMode) { + connection.graphics[type].attr({ + fill: options.color || connection.fromPoint.color, + stroke: options.lineColor, + 'stroke-width': options.lineWidth, + opacity: 0 + }) + .animate({ + opacity: 1 + }, point.series.options.animation); + } + } + else { + connection.graphics[type].animate(box); + } + } + }; + /** + * Calculate and return connection path. + * Note: Recalculates chart obstacles on demand if they aren't calculated. + * + * @function Highcharts.Connection#getPath + * + * @param {Highcharts.ConnectorsOptions} options + * Connector options. Not calculated or merged with other options. + * + * @return {object|undefined} + * Calculated SVG path data in array format. + */ + Connection.prototype.getPath = function (options) { + var pathfinder = this.pathfinder, + chart = this.chart, + algorithm = pathfinder.algorithms[options.type], + chartObstacles = pathfinder.chartObstacles; + if (typeof algorithm !== 'function') { + error('"' + options.type + '" is not a Pathfinder algorithm.'); + return { + path: [], + obstacles: [] + }; + } + // This function calculates obstacles on demand if they don't exist + if (algorithm.requiresObstacles && !chartObstacles) { + chartObstacles = + pathfinder.chartObstacles = + pathfinder.getChartObstacles(options); + // If the algorithmMargin was computed, store the result in default + // options. + chart.options.connectors.algorithmMargin = + options.algorithmMargin; + // Cache some metrics too + pathfinder.chartObstacleMetrics = + pathfinder.getObstacleMetrics(chartObstacles); + } + // Get the SVG path + return algorithm( + // From + this.fromPoint.getPathfinderAnchorPoint(options.startMarker), + // To + this.toPoint.getPathfinderAnchorPoint(options.endMarker), merge({ + chartObstacles: chartObstacles, + lineObstacles: pathfinder.lineObstacles || [], + obstacleMetrics: pathfinder.chartObstacleMetrics, + hardBounds: { + xMin: 0, + xMax: chart.plotWidth, + yMin: 0, + yMax: chart.plotHeight + }, + obstacleOptions: { + margin: options.algorithmMargin + }, + startDirectionX: pathfinder.getAlgorithmStartDirection(options.startMarker) + }, options)); + }; + /** + * (re)Calculate and (re)draw the connection. + * + * @function Highcharts.Connection#render + */ + Connection.prototype.render = function () { + var connection = this, + fromPoint = connection.fromPoint, + series = fromPoint.series, + chart = series.chart, + pathfinder = chart.pathfinder, + pathResult, + path, + options = merge(chart.options.connectors, + series.options.connectors, + fromPoint.options.connectors, + connection.options), + attribs = {}; + // Set path attribs + if (!chart.styledMode) { + attribs.stroke = options.lineColor || fromPoint.color; + attribs['stroke-width'] = options.lineWidth; + if (options.dashStyle) { + attribs.dashstyle = options.dashStyle; + } + } + attribs['class'] = // eslint-disable-line dot-notation + 'highcharts-point-connecting-path ' + + 'highcharts-color-' + fromPoint.colorIndex; + options = merge(attribs, options); + // Set common marker options + if (!defined(options.marker.radius)) { + options.marker.radius = min(max(Math.ceil((options.algorithmMargin || 8) / 2) - 1, 1), 5); + } + // Get the path + pathResult = connection.getPath(options); + path = pathResult.path; + // Always update obstacle storage with obstacles from this path. + // We don't know if future calls will need this for their algorithm. + if (pathResult.obstacles) { + pathfinder.lineObstacles = + pathfinder.lineObstacles || []; + pathfinder.lineObstacles = + pathfinder.lineObstacles.concat(pathResult.obstacles); + } + // Add the calculated path to the pathfinder group + connection.renderPath(path, attribs, series.options.animation); + // Render the markers + connection.addMarker('start', merge(options.marker, options.startMarker), path); + connection.addMarker('end', merge(options.marker, options.endMarker), path); + }; + /** + * Destroy connection by destroying the added graphics elements. + * + * @function Highcharts.Connection#destroy + */ + Connection.prototype.destroy = function () { + if (this.graphics) { + objectEach(this.graphics, function (val) { + val.destroy(); + }); + delete this.graphics; + } + }; + return Connection; + }()); + // Add to Highcharts namespace + H.Connection = Connection; + // Add pathfinding capabilities to Points + extend(Point.prototype, /** @lends Point.prototype */ { + /** + * Get coordinates of anchor point for pathfinder connection. + * + * @private + * @function Highcharts.Point#getPathfinderAnchorPoint + * + * @param {Highcharts.ConnectorsMarkerOptions} markerOptions + * Connection options for position on point. + * + * @return {Highcharts.PositionObject} + * An object with x/y properties for the position. Coordinates are + * in plot values, not relative to point. + */ + getPathfinderAnchorPoint: function (markerOptions) { + var bb = getPointBB(this), + x, + y; + switch (markerOptions.align) { // eslint-disable-line default-case + case 'right': + x = 'xMax'; + break; + case 'left': + x = 'xMin'; + } + switch (markerOptions.verticalAlign) { // eslint-disable-line default-case + case 'top': + y = 'yMin'; + break; + case 'bottom': + y = 'yMax'; + } + return { + x: x ? bb[x] : (bb.xMin + bb.xMax) / 2, + y: y ? bb[y] : (bb.yMin + bb.yMax) / 2 + }; + }, + /** + * Utility to get the angle from one point to another. + * + * @private + * @function Highcharts.Point#getRadiansToVector + * + * @param {Highcharts.PositionObject} v1 + * The first vector, as an object with x/y properties. + * + * @param {Highcharts.PositionObject} v2 + * The second vector, as an object with x/y properties. + * + * @return {number} + * The angle in degrees + */ + getRadiansToVector: function (v1, v2) { + var box; + if (!defined(v2)) { + box = getPointBB(this); + if (box) { + v2 = { + x: (box.xMin + box.xMax) / 2, + y: (box.yMin + box.yMax) / 2 + }; + } + } + return Math.atan2(v2.y - v1.y, v1.x - v2.x); + }, + /** + * Utility to get the position of the marker, based on the path angle and + * the marker's radius. + * + * @private + * @function Highcharts.Point#getMarkerVector + * + * @param {number} radians + * The angle in radians from the point center to another vector. + * + * @param {number} markerRadius + * The radius of the marker, to calculate the additional distance to + * the center of the marker. + * + * @param {object} anchor + * The anchor point of the path and marker as an object with x/y + * properties. + * + * @return {object} + * The marker vector as an object with x/y properties. + */ + getMarkerVector: function (radians, markerRadius, anchor) { + var twoPI = Math.PI * 2.0, + theta = radians, + bb = getPointBB(this), + rectWidth = bb.xMax - bb.xMin, + rectHeight = bb.yMax - bb.yMin, + rAtan = Math.atan2(rectHeight, + rectWidth), + tanTheta = 1, + leftOrRightRegion = false, + rectHalfWidth = rectWidth / 2.0, + rectHalfHeight = rectHeight / 2.0, + rectHorizontalCenter = bb.xMin + rectHalfWidth, + rectVerticalCenter = bb.yMin + rectHalfHeight, + edgePoint = { + x: rectHorizontalCenter, + y: rectVerticalCenter + }, + markerPoint = {}, + xFactor = 1, + yFactor = 1; + while (theta < -Math.PI) { + theta += twoPI; + } + while (theta > Math.PI) { + theta -= twoPI; + } + tanTheta = Math.tan(theta); + if ((theta > -rAtan) && (theta <= rAtan)) { + // Right side + yFactor = -1; + leftOrRightRegion = true; + } + else if (theta > rAtan && theta <= (Math.PI - rAtan)) { + // Top side + yFactor = -1; + } + else if (theta > (Math.PI - rAtan) || theta <= -(Math.PI - rAtan)) { + // Left side + xFactor = -1; + leftOrRightRegion = true; + } + else { + // Bottom side + xFactor = -1; + } + // Correct the edgePoint according to the placement of the marker + if (leftOrRightRegion) { + edgePoint.x += xFactor * (rectHalfWidth); + edgePoint.y += yFactor * (rectHalfWidth) * tanTheta; + } + else { + edgePoint.x += xFactor * (rectHeight / (2.0 * tanTheta)); + edgePoint.y += yFactor * (rectHalfHeight); + } + if (anchor.x !== rectHorizontalCenter) { + edgePoint.x = anchor.x; + } + if (anchor.y !== rectVerticalCenter) { + edgePoint.y = anchor.y; + } + markerPoint.x = edgePoint.x + (markerRadius * Math.cos(theta)); + markerPoint.y = edgePoint.y - (markerRadius * Math.sin(theta)); + return markerPoint; + } + }); + /** + * Warn if using legacy options. Copy the options over. Note that this will + * still break if using the legacy options in chart.update, addSeries etc. + * @private + */ + function warnLegacy(chart) { + if (chart.options.pathfinder || + chart.series.reduce(function (acc, series) { + if (series.options) { + merge(true, (series.options.connectors = series.options.connectors || + {}), series.options.pathfinder); + } + return acc || series.options && series.options.pathfinder; + }, false)) { + merge(true, (chart.options.connectors = chart.options.connectors || {}), chart.options.pathfinder); + error('WARNING: Pathfinder options have been renamed. ' + + 'Use "chart.connectors" or "series.connectors" instead.'); + } + } + + return Connection; + }); + _registerModule(_modules, 'Gantt/PathfinderAlgorithms.js', [_modules['Core/Utilities.js']], function (U) { + /* * + * + * (c) 2016 Highsoft AS + * Author: Øystein Moseng + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend, + pick = U.pick; + var min = Math.min, + max = Math.max, + abs = Math.abs; + /** + * Get index of last obstacle before xMin. Employs a type of binary search, and + * thus requires that obstacles are sorted by xMin value. + * + * @private + * @function findLastObstacleBefore + * + * @param {Array} obstacles + * Array of obstacles to search in. + * + * @param {number} xMin + * The xMin threshold. + * + * @param {number} [startIx] + * Starting index to search from. Must be within array range. + * + * @return {number} + * The index of the last obstacle element before xMin. + */ + function findLastObstacleBefore(obstacles, xMin, startIx) { + var left = startIx || 0, // left limit + right = obstacles.length - 1, // right limit + min = xMin - 0.0000001, // Make sure we include all obstacles at xMin + cursor, + cmp; + while (left <= right) { + cursor = (right + left) >> 1; + cmp = min - obstacles[cursor].xMin; + if (cmp > 0) { + left = cursor + 1; + } + else if (cmp < 0) { + right = cursor - 1; + } + else { + return cursor; + } + } + return left > 0 ? left - 1 : 0; + } + /** + * Test if a point lays within an obstacle. + * + * @private + * @function pointWithinObstacle + * + * @param {object} obstacle + * Obstacle to test. + * + * @param {Highcharts.Point} point + * Point with x/y props. + * + * @return {boolean} + * Whether point is within the obstacle or not. + */ + function pointWithinObstacle(obstacle, point) { + return (point.x <= obstacle.xMax && + point.x >= obstacle.xMin && + point.y <= obstacle.yMax && + point.y >= obstacle.yMin); + } + /** + * Find the index of an obstacle that wraps around a point. + * Returns -1 if not found. + * + * @private + * @function findObstacleFromPoint + * + * @param {Array} obstacles + * Obstacles to test. + * + * @param {Highcharts.Point} point + * Point with x/y props. + * + * @return {number} + * Ix of the obstacle in the array, or -1 if not found. + */ + function findObstacleFromPoint(obstacles, point) { + var i = findLastObstacleBefore(obstacles, + point.x + 1) + 1; + while (i--) { + if (obstacles[i].xMax >= point.x && + // optimization using lazy evaluation + pointWithinObstacle(obstacles[i], point)) { + return i; + } + } + return -1; + } + /** + * Get SVG path array from array of line segments. + * + * @private + * @function pathFromSegments + * + * @param {Array} segments + * The segments to build the path from. + * + * @return {Highcharts.SVGPathArray} + * SVG path array as accepted by the SVG Renderer. + */ + function pathFromSegments(segments) { + var path = []; + if (segments.length) { + path.push(['M', segments[0].start.x, segments[0].start.y]); + for (var i = 0; i < segments.length; ++i) { + path.push(['L', segments[i].end.x, segments[i].end.y]); + } + } + return path; + } + /** + * Limits obstacle max/mins in all directions to bounds. Modifies input + * obstacle. + * + * @private + * @function limitObstacleToBounds + * + * @param {object} obstacle + * Obstacle to limit. + * + * @param {object} bounds + * Bounds to use as limit. + * + * @return {void} + */ + function limitObstacleToBounds(obstacle, bounds) { + obstacle.yMin = max(obstacle.yMin, bounds.yMin); + obstacle.yMax = min(obstacle.yMax, bounds.yMax); + obstacle.xMin = max(obstacle.xMin, bounds.xMin); + obstacle.xMax = min(obstacle.xMax, bounds.xMax); + } + /** + * Get an SVG path from a starting coordinate to an ending coordinate. + * Draws a straight line. + * + * @function Highcharts.Pathfinder.algorithms.straight + * + * @param {Highcharts.PositionObject} start + * Starting coordinate, object with x/y props. + * + * @param {Highcharts.PositionObject} end + * Ending coordinate, object with x/y props. + * + * @return {object} + * An object with the SVG path in Array form as accepted by the SVG + * renderer, as well as an array of new obstacles making up this + * path. + */ + function straight(start, end) { + return { + path: [ + ['M', start.x, start.y], + ['L', end.x, end.y] + ], + obstacles: [{ start: start, end: end }] + }; + } + /** + * Find a path from a starting coordinate to an ending coordinate, using + * right angles only, and taking only starting/ending obstacle into + * consideration. + * + * @function Highcharts.Pathfinder.algorithms.simpleConnect + * + * @param {Highcharts.PositionObject} start + * Starting coordinate, object with x/y props. + * + * @param {Highcharts.PositionObject} end + * Ending coordinate, object with x/y props. + * + * @param {object} options + * Options for the algorithm: + * - chartObstacles: Array of chart obstacles to avoid + * - startDirectionX: Optional. True if starting in the X direction. + * If not provided, the algorithm starts in the direction that is + * the furthest between start/end. + * + * @return {object} + * An object with the SVG path in Array form as accepted by the SVG + * renderer, as well as an array of new obstacles making up this + * path. + */ + var simpleConnect = extend(function (start, + end, + options) { + var segments = [], + endSegment, + dir = pick(options.startDirectionX, + abs(end.x - start.x) > abs(end.y - start.y)) ? 'x' : 'y', + chartObstacles = options.chartObstacles, + startObstacleIx = findObstacleFromPoint(chartObstacles, + start), + endObstacleIx = findObstacleFromPoint(chartObstacles, + end), + startObstacle, + endObstacle, + prevWaypoint, + waypoint, + waypoint2, + useMax, + endPoint; + // eslint-disable-next-line valid-jsdoc + /** + * Return a clone of a point with a property set from a target object, + * optionally with an offset + * @private + */ + function copyFromPoint(from, fromKey, to, toKey, offset) { + var point = { + x: from.x, + y: from.y + }; + point[fromKey] = to[toKey || fromKey] + (offset || 0); + return point; + } + // eslint-disable-next-line valid-jsdoc + /** + * Return waypoint outside obstacle. + * @private + */ + function getMeOut(obstacle, point, direction) { + var useMax = abs(point[direction] - obstacle[direction + 'Min']) > + abs(point[direction] - obstacle[direction + 'Max']); + return copyFromPoint(point, direction, obstacle, direction + (useMax ? 'Max' : 'Min'), useMax ? 1 : -1); + } + // Pull out end point + if (endObstacleIx > -1) { + endObstacle = chartObstacles[endObstacleIx]; + waypoint = getMeOut(endObstacle, end, dir); + endSegment = { + start: waypoint, + end: end + }; + endPoint = waypoint; + } + else { + endPoint = end; + } + // If an obstacle envelops the start point, add a segment to get out, + // and around it. + if (startObstacleIx > -1) { + startObstacle = chartObstacles[startObstacleIx]; + waypoint = getMeOut(startObstacle, start, dir); + segments.push({ + start: start, + end: waypoint + }); + // If we are going back again, switch direction to get around start + // obstacle. + if ( + // Going towards max from start: + waypoint[dir] >= start[dir] === + // Going towards min to end: + waypoint[dir] >= endPoint[dir]) { + dir = dir === 'y' ? 'x' : 'y'; + useMax = start[dir] < end[dir]; + segments.push({ + start: waypoint, + end: copyFromPoint(waypoint, dir, startObstacle, dir + (useMax ? 'Max' : 'Min'), useMax ? 1 : -1) + }); + // Switch direction again + dir = dir === 'y' ? 'x' : 'y'; + } + } + // We are around the start obstacle. Go towards the end in one + // direction. + prevWaypoint = segments.length ? + segments[segments.length - 1].end : + start; + waypoint = copyFromPoint(prevWaypoint, dir, endPoint); + segments.push({ + start: prevWaypoint, + end: waypoint + }); + // Final run to end point in the other direction + dir = dir === 'y' ? 'x' : 'y'; + waypoint2 = copyFromPoint(waypoint, dir, endPoint); + segments.push({ + start: waypoint, + end: waypoint2 + }); + // Finally add the endSegment + segments.push(endSegment); + return { + path: pathFromSegments(segments), + obstacles: segments + }; + }, { + requiresObstacles: true + }); + /** + * Find a path from a starting coordinate to an ending coordinate, taking + * obstacles into consideration. Might not always find the optimal path, + * but is fast, and usually good enough. + * + * @function Highcharts.Pathfinder.algorithms.fastAvoid + * + * @param {Highcharts.PositionObject} start + * Starting coordinate, object with x/y props. + * + * @param {Highcharts.PositionObject} end + * Ending coordinate, object with x/y props. + * + * @param {object} options + * Options for the algorithm. + * - chartObstacles: Array of chart obstacles to avoid + * - lineObstacles: Array of line obstacles to jump over + * - obstacleMetrics: Object with metrics of chartObstacles cached + * - hardBounds: Hard boundaries to not cross + * - obstacleOptions: Options for the obstacles, including margin + * - startDirectionX: Optional. True if starting in the X direction. + * If not provided, the algorithm starts in the + * direction that is the furthest between + * start/end. + * + * @return {object} + * An object with the SVG path in Array form as accepted by the SVG + * renderer, as well as an array of new obstacles making up this + * path. + */ + var fastAvoid = extend(function (start, + end, + options) { + /* + Algorithm rules/description + - Find initial direction + - Determine soft/hard max for each direction. + - Move along initial direction until obstacle. + - Change direction. + - If hitting obstacle, + first try to change length of previous line + before changing direction again. + + Soft min/max x = start/destination x +/- widest obstacle + margin + Soft min/max y = start/destination y +/- tallest obstacle + margin + + @todo: + - Make retrospective, + try changing prev segment to reduce + corners + - Fix logic for breaking out of end-points - not always picking + the best direction currently + - When going around the end obstacle we should not always go the + shortest route, + rather pick the one closer to the end point + */ + var dirIsX = pick(options.startDirectionX, + abs(end.x - start.x) > abs(end.y - start.y)), + dir = dirIsX ? 'x' : 'y', + segments, + useMax, + extractedEndPoint, + endSegments = [], + forceObstacleBreak = false, // Used in clearPathTo to keep track of + // when to force break through an obstacle. + // Boundaries to stay within. If beyond soft boundary, prefer to + // change direction ASAP. If at hard max, always change immediately. + metrics = options.obstacleMetrics, + softMinX = min(start.x, + end.x) - metrics.maxWidth - 10, + softMaxX = max(start.x, + end.x) + metrics.maxWidth + 10, + softMinY = min(start.y, + end.y) - metrics.maxHeight - 10, + softMaxY = max(start.y, + end.y) + metrics.maxHeight + 10, + // Obstacles + chartObstacles = options.chartObstacles, + startObstacleIx = findLastObstacleBefore(chartObstacles, + softMinX), + endObstacleIx = findLastObstacleBefore(chartObstacles, + softMaxX); + // eslint-disable-next-line valid-jsdoc + /** + * How far can you go between two points before hitting an obstacle? + * Does not work for diagonal lines (because it doesn't have to). + * @private + */ + function pivotPoint(fromPoint, toPoint, directionIsX) { + var firstPoint, + lastPoint, + highestPoint, + lowestPoint, + i, + searchDirection = fromPoint.x < toPoint.x ? 1 : -1; + if (fromPoint.x < toPoint.x) { + firstPoint = fromPoint; + lastPoint = toPoint; + } + else { + firstPoint = toPoint; + lastPoint = fromPoint; + } + if (fromPoint.y < toPoint.y) { + lowestPoint = fromPoint; + highestPoint = toPoint; + } + else { + lowestPoint = toPoint; + highestPoint = fromPoint; + } + // Go through obstacle range in reverse if toPoint is before + // fromPoint in the X-dimension. + i = searchDirection < 0 ? + // Searching backwards, start at last obstacle before last point + min(findLastObstacleBefore(chartObstacles, lastPoint.x), chartObstacles.length - 1) : + // Forwards. Since we're not sorted by xMax, we have to look + // at all obstacles. + 0; + // Go through obstacles in this X range + while (chartObstacles[i] && (searchDirection > 0 && chartObstacles[i].xMin <= lastPoint.x || + searchDirection < 0 && chartObstacles[i].xMax >= firstPoint.x)) { + // If this obstacle is between from and to points in a straight + // line, pivot at the intersection. + if (chartObstacles[i].xMin <= lastPoint.x && + chartObstacles[i].xMax >= firstPoint.x && + chartObstacles[i].yMin <= highestPoint.y && + chartObstacles[i].yMax >= lowestPoint.y) { + if (directionIsX) { + return { + y: fromPoint.y, + x: fromPoint.x < toPoint.x ? + chartObstacles[i].xMin - 1 : + chartObstacles[i].xMax + 1, + obstacle: chartObstacles[i] + }; + } + // else ... + return { + x: fromPoint.x, + y: fromPoint.y < toPoint.y ? + chartObstacles[i].yMin - 1 : + chartObstacles[i].yMax + 1, + obstacle: chartObstacles[i] + }; + } + i += searchDirection; + } + return toPoint; + } + /** + * Decide in which direction to dodge or get out of an obstacle. + * Considers desired direction, which way is shortest, soft and hard + * bounds. + * + * (? Returns a string, either xMin, xMax, yMin or yMax.) + * + * @private + * @function + * + * @param {object} obstacle + * Obstacle to dodge/escape. + * + * @param {object} fromPoint + * Point with x/y props that's dodging/escaping. + * + * @param {object} toPoint + * Goal point. + * + * @param {boolean} dirIsX + * Dodge in X dimension. + * + * @param {object} bounds + * Hard and soft boundaries. + * + * @return {boolean} + * Use max or not. + */ + function getDodgeDirection(obstacle, fromPoint, toPoint, dirIsX, bounds) { + var softBounds = bounds.soft, hardBounds = bounds.hard, dir = dirIsX ? 'x' : 'y', toPointMax = { x: fromPoint.x, y: fromPoint.y }, toPointMin = { x: fromPoint.x, y: fromPoint.y }, minPivot, maxPivot, maxOutOfSoftBounds = obstacle[dir + 'Max'] >= + softBounds[dir + 'Max'], minOutOfSoftBounds = obstacle[dir + 'Min'] <= + softBounds[dir + 'Min'], maxOutOfHardBounds = obstacle[dir + 'Max'] >= + hardBounds[dir + 'Max'], minOutOfHardBounds = obstacle[dir + 'Min'] <= + hardBounds[dir + 'Min'], + // Find out if we should prefer one direction over the other if + // we can choose freely + minDistance = abs(obstacle[dir + 'Min'] - fromPoint[dir]), maxDistance = abs(obstacle[dir + 'Max'] - fromPoint[dir]), + // If it's a small difference, pick the one leading towards dest + // point. Otherwise pick the shortest distance + useMax = abs(minDistance - maxDistance) < 10 ? + fromPoint[dir] < toPoint[dir] : + maxDistance < minDistance; + // Check if we hit any obstacles trying to go around in either + // direction. + toPointMin[dir] = obstacle[dir + 'Min']; + toPointMax[dir] = obstacle[dir + 'Max']; + minPivot = pivotPoint(fromPoint, toPointMin, dirIsX)[dir] !== + toPointMin[dir]; + maxPivot = pivotPoint(fromPoint, toPointMax, dirIsX)[dir] !== + toPointMax[dir]; + useMax = minPivot ? + (maxPivot ? useMax : true) : + (maxPivot ? false : useMax); + // useMax now contains our preferred choice, bounds not taken into + // account. If both or neither direction is out of bounds we want to + // use this. + // Deal with soft bounds + useMax = minOutOfSoftBounds ? + (maxOutOfSoftBounds ? useMax : true) : // Out on min + (maxOutOfSoftBounds ? false : useMax); // Not out on min + // Deal with hard bounds + useMax = minOutOfHardBounds ? + (maxOutOfHardBounds ? useMax : true) : // Out on min + (maxOutOfHardBounds ? false : useMax); // Not out on min + return useMax; + } + // eslint-disable-next-line valid-jsdoc + /** + * Find a clear path between point. + * @private + */ + function clearPathTo(fromPoint, toPoint, dirIsX) { + // Don't waste time if we've hit goal + if (fromPoint.x === toPoint.x && fromPoint.y === toPoint.y) { + return []; + } + var dir = dirIsX ? 'x' : 'y', + pivot, + segments, + waypoint, + waypointUseMax, + envelopingObstacle, + secondEnvelopingObstacle, + envelopWaypoint, + obstacleMargin = options.obstacleOptions.margin, + bounds = { + soft: { + xMin: softMinX, + xMax: softMaxX, + yMin: softMinY, + yMax: softMaxY + }, + hard: options.hardBounds + }; + // If fromPoint is inside an obstacle we have a problem. Break out + // by just going to the outside of this obstacle. We prefer to go to + // the nearest edge in the chosen direction. + envelopingObstacle = + findObstacleFromPoint(chartObstacles, fromPoint); + if (envelopingObstacle > -1) { + envelopingObstacle = chartObstacles[envelopingObstacle]; + waypointUseMax = getDodgeDirection(envelopingObstacle, fromPoint, toPoint, dirIsX, bounds); + // Cut obstacle to hard bounds to make sure we stay within + limitObstacleToBounds(envelopingObstacle, options.hardBounds); + envelopWaypoint = dirIsX ? { + y: fromPoint.y, + x: envelopingObstacle[waypointUseMax ? 'xMax' : 'xMin'] + + (waypointUseMax ? 1 : -1) + } : { + x: fromPoint.x, + y: envelopingObstacle[waypointUseMax ? 'yMax' : 'yMin'] + + (waypointUseMax ? 1 : -1) + }; + // If we crashed into another obstacle doing this, we put the + // waypoint between them instead + secondEnvelopingObstacle = findObstacleFromPoint(chartObstacles, envelopWaypoint); + if (secondEnvelopingObstacle > -1) { + secondEnvelopingObstacle = chartObstacles[secondEnvelopingObstacle]; + // Cut obstacle to hard bounds + limitObstacleToBounds(secondEnvelopingObstacle, options.hardBounds); + // Modify waypoint to lay between obstacles + envelopWaypoint[dir] = waypointUseMax ? max(envelopingObstacle[dir + 'Max'] - obstacleMargin + 1, (secondEnvelopingObstacle[dir + 'Min'] + + envelopingObstacle[dir + 'Max']) / 2) : + min((envelopingObstacle[dir + 'Min'] + obstacleMargin - 1), ((secondEnvelopingObstacle[dir + 'Max'] + + envelopingObstacle[dir + 'Min']) / 2)); + // We are not going anywhere. If this happens for the first + // time, do nothing. Otherwise, try to go to the extreme of + // the obstacle pair in the current direction. + if (fromPoint.x === envelopWaypoint.x && + fromPoint.y === envelopWaypoint.y) { + if (forceObstacleBreak) { + envelopWaypoint[dir] = waypointUseMax ? + max(envelopingObstacle[dir + 'Max'], secondEnvelopingObstacle[dir + 'Max']) + 1 : + min(envelopingObstacle[dir + 'Min'], secondEnvelopingObstacle[dir + 'Min']) - 1; + } + // Toggle on if off, and the opposite + forceObstacleBreak = !forceObstacleBreak; + } + else { + // This point is not identical to previous. + // Clear break trigger. + forceObstacleBreak = false; + } + } + segments = [{ + start: fromPoint, + end: envelopWaypoint + }]; + } + else { // If not enveloping, use standard pivot calculation + pivot = pivotPoint(fromPoint, { + x: dirIsX ? toPoint.x : fromPoint.x, + y: dirIsX ? fromPoint.y : toPoint.y + }, dirIsX); + segments = [{ + start: fromPoint, + end: { + x: pivot.x, + y: pivot.y + } + }]; + // Pivot before goal, use a waypoint to dodge obstacle + if (pivot[dirIsX ? 'x' : 'y'] !== toPoint[dirIsX ? 'x' : 'y']) { + // Find direction of waypoint + waypointUseMax = getDodgeDirection(pivot.obstacle, pivot, toPoint, !dirIsX, bounds); + // Cut waypoint to hard bounds + limitObstacleToBounds(pivot.obstacle, options.hardBounds); + waypoint = { + x: dirIsX ? + pivot.x : + pivot.obstacle[waypointUseMax ? 'xMax' : 'xMin'] + + (waypointUseMax ? 1 : -1), + y: dirIsX ? + pivot.obstacle[waypointUseMax ? 'yMax' : 'yMin'] + + (waypointUseMax ? 1 : -1) : + pivot.y + }; + // We're changing direction here, store that to make sure we + // also change direction when adding the last segment array + // after handling waypoint. + dirIsX = !dirIsX; + segments = segments.concat(clearPathTo({ + x: pivot.x, + y: pivot.y + }, waypoint, dirIsX)); + } + } + // Get segments for the other direction too + // Recursion is our friend + segments = segments.concat(clearPathTo(segments[segments.length - 1].end, toPoint, !dirIsX)); + return segments; + } + // eslint-disable-next-line valid-jsdoc + /** + * Extract point to outside of obstacle in whichever direction is + * closest. Returns new point outside obstacle. + * @private + */ + function extractFromObstacle(obstacle, point, goalPoint) { + var dirIsX = min(obstacle.xMax - point.x, + point.x - obstacle.xMin) < + min(obstacle.yMax - point.y, + point.y - obstacle.yMin), + bounds = { + soft: options.hardBounds, + hard: options.hardBounds + }, + useMax = getDodgeDirection(obstacle, + point, + goalPoint, + dirIsX, + bounds); + return dirIsX ? { + y: point.y, + x: obstacle[useMax ? 'xMax' : 'xMin'] + (useMax ? 1 : -1) + } : { + x: point.x, + y: obstacle[useMax ? 'yMax' : 'yMin'] + (useMax ? 1 : -1) + }; + } + // Cut the obstacle array to soft bounds for optimization in large + // datasets. + chartObstacles = + chartObstacles.slice(startObstacleIx, endObstacleIx + 1); + // If an obstacle envelops the end point, move it out of there and add + // a little segment to where it was. + if ((endObstacleIx = findObstacleFromPoint(chartObstacles, end)) > -1) { + extractedEndPoint = extractFromObstacle(chartObstacles[endObstacleIx], end, start); + endSegments.push({ + end: end, + start: extractedEndPoint + }); + end = extractedEndPoint; + } + // If it's still inside one or more obstacles, get out of there by + // force-moving towards the start point. + while ((endObstacleIx = findObstacleFromPoint(chartObstacles, end)) > -1) { + useMax = end[dir] - start[dir] < 0; + extractedEndPoint = { + x: end.x, + y: end.y + }; + extractedEndPoint[dir] = chartObstacles[endObstacleIx][useMax ? dir + 'Max' : dir + 'Min'] + (useMax ? 1 : -1); + endSegments.push({ + end: end, + start: extractedEndPoint + }); + end = extractedEndPoint; + } + // Find the path + segments = clearPathTo(start, end, dirIsX); + // Add the end-point segments + segments = segments.concat(endSegments.reverse()); + return { + path: pathFromSegments(segments), + obstacles: segments + }; + }, { + requiresObstacles: true + }); + // Define the available pathfinding algorithms. + // Algorithms take up to 3 arguments: starting point, ending point, and an + // options object. + var algorithms = { + fastAvoid: fastAvoid, + straight: straight, + simpleConnect: simpleConnect + }; + + return algorithms; + }); + _registerModule(_modules, 'Gantt/Pathfinder.js', [_modules['Gantt/Connection.js'], _modules['Core/Chart/Chart.js'], _modules['Core/Globals.js'], _modules['Core/Options.js'], _modules['Core/Series/Point.js'], _modules['Core/Utilities.js'], _modules['Gantt/PathfinderAlgorithms.js']], function (Connection, Chart, H, O, Point, U, pathfinderAlgorithms) { + /* * + * + * (c) 2016 Highsoft AS + * Authors: Øystein Moseng, Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * The default pathfinder algorithm to use for a chart. It is possible to define + * your own algorithms by adding them to the + * `Highcharts.Pathfinder.prototype.algorithms` + * object before the chart has been created. + * + * The default algorithms are as follows: + * + * `straight`: Draws a straight line between the connecting + * points. Does not avoid other points when drawing. + * + * `simpleConnect`: Finds a path between the points using right angles + * only. Takes only starting/ending points into + * account, and will not avoid other points. + * + * `fastAvoid`: Finds a path between the points using right angles + * only. Will attempt to avoid other points, but its + * focus is performance over accuracy. Works well with + * less dense datasets. + * + * @typedef {"fastAvoid"|"simpleConnect"|"straight"|string} Highcharts.PathfinderTypeValue + */ + ''; // detach doclets above + var defaultOptions = O.defaultOptions; + var addEvent = U.addEvent, + defined = U.defined, + error = U.error, + extend = U.extend, + merge = U.merge, + objectEach = U.objectEach, + pick = U.pick, + splat = U.splat; + var deg2rad = H.deg2rad, + max = Math.max, + min = Math.min; + /* + @todo: + - Document how to write your own algorithms + - Consider adding a Point.pathTo method that wraps creating a connection + and rendering it + */ + // Set default Pathfinder options + extend(defaultOptions, { + /** + * The Pathfinder module allows you to define connections between any two + * points, represented as lines - optionally with markers for the start + * and/or end points. Multiple algorithms are available for calculating how + * the connecting lines are drawn. + * + * Connector functionality requires Highcharts Gantt to be loaded. In Gantt + * charts, the connectors are used to draw dependencies between tasks. + * + * @see [dependency](series.gantt.data.dependency) + * + * @sample gantt/pathfinder/demo + * Pathfinder connections + * + * @declare Highcharts.ConnectorsOptions + * @product gantt + * @optionparent connectors + */ + connectors: { + /** + * Enable connectors for this chart. Requires Highcharts Gantt. + * + * @type {boolean} + * @default true + * @since 6.2.0 + * @apioption connectors.enabled + */ + /** + * Set the default dash style for this chart's connecting lines. + * + * @type {string} + * @default solid + * @since 6.2.0 + * @apioption connectors.dashStyle + */ + /** + * Set the default color for this chart's Pathfinder connecting lines. + * Defaults to the color of the point being connected. + * + * @type {Highcharts.ColorString} + * @since 6.2.0 + * @apioption connectors.lineColor + */ + /** + * Set the default pathfinder margin to use, in pixels. Some Pathfinder + * algorithms attempt to avoid obstacles, such as other points in the + * chart. These algorithms use this margin to determine how close lines + * can be to an obstacle. The default is to compute this automatically + * from the size of the obstacles in the chart. + * + * To draw connecting lines close to existing points, set this to a low + * number. For more space around existing points, set this number + * higher. + * + * @sample gantt/pathfinder/algorithm-margin + * Small algorithmMargin + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.algorithmMargin + */ + /** + * Set the default pathfinder algorithm to use for this chart. It is + * possible to define your own algorithms by adding them to the + * Highcharts.Pathfinder.prototype.algorithms object before the chart + * has been created. + * + * The default algorithms are as follows: + * + * `straight`: Draws a straight line between the connecting + * points. Does not avoid other points when drawing. + * + * `simpleConnect`: Finds a path between the points using right angles + * only. Takes only starting/ending points into + * account, and will not avoid other points. + * + * `fastAvoid`: Finds a path between the points using right angles + * only. Will attempt to avoid other points, but its + * focus is performance over accuracy. Works well with + * less dense datasets. + * + * Default value: `straight` is used as default for most series types, + * while `simpleConnect` is used as default for Gantt series, to show + * dependencies between points. + * + * @sample gantt/pathfinder/demo + * Different types used + * + * @type {Highcharts.PathfinderTypeValue} + * @default undefined + * @since 6.2.0 + */ + type: 'straight', + /** + * Set the default pixel width for this chart's Pathfinder connecting + * lines. + * + * @since 6.2.0 + */ + lineWidth: 1, + /** + * Marker options for this chart's Pathfinder connectors. Note that + * this option is overridden by the `startMarker` and `endMarker` + * options. + * + * @declare Highcharts.ConnectorsMarkerOptions + * @since 6.2.0 + */ + marker: { + /** + * Set the radius of the connector markers. The default is + * automatically computed based on the algorithmMargin setting. + * + * Setting marker.width and marker.height will override this + * setting. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.radius + */ + /** + * Set the width of the connector markers. If not supplied, this + * is inferred from the marker radius. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.width + */ + /** + * Set the height of the connector markers. If not supplied, this + * is inferred from the marker radius. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.height + */ + /** + * Set the color of the connector markers. By default this is the + * same as the connector color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 6.2.0 + * @apioption connectors.marker.color + */ + /** + * Set the line/border color of the connector markers. By default + * this is the same as the marker color. + * + * @type {Highcharts.ColorString} + * @since 6.2.0 + * @apioption connectors.marker.lineColor + */ + /** + * Enable markers for the connectors. + */ + enabled: false, + /** + * Horizontal alignment of the markers relative to the points. + * + * @type {Highcharts.AlignValue} + */ + align: 'center', + /** + * Vertical alignment of the markers relative to the points. + * + * @type {Highcharts.VerticalAlignValue} + */ + verticalAlign: 'middle', + /** + * Whether or not to draw the markers inside the points. + */ + inside: false, + /** + * Set the line/border width of the pathfinder markers. + */ + lineWidth: 1 + }, + /** + * Marker options specific to the start markers for this chart's + * Pathfinder connectors. Overrides the generic marker options. + * + * @declare Highcharts.ConnectorsStartMarkerOptions + * @extends connectors.marker + * @since 6.2.0 + */ + startMarker: { + /** + * Set the symbol of the connector start markers. + */ + symbol: 'diamond' + }, + /** + * Marker options specific to the end markers for this chart's + * Pathfinder connectors. Overrides the generic marker options. + * + * @declare Highcharts.ConnectorsEndMarkerOptions + * @extends connectors.marker + * @since 6.2.0 + */ + endMarker: { + /** + * Set the symbol of the connector end markers. + */ + symbol: 'arrow-filled' + } + } + }); + /** + * Override Pathfinder connector options for a series. Requires Highcharts Gantt + * to be loaded. + * + * @declare Highcharts.SeriesConnectorsOptionsObject + * @extends connectors + * @since 6.2.0 + * @excluding enabled, algorithmMargin + * @product gantt + * @apioption plotOptions.series.connectors + */ + /** + * Connect to a point. This option can be either a string, referring to the ID + * of another point, or an object, or an array of either. If the option is an + * array, each element defines a connection. + * + * @sample gantt/pathfinder/demo + * Different connection types + * + * @declare Highcharts.XrangePointConnectorsOptionsObject + * @type {string|Array|*} + * @extends plotOptions.series.connectors + * @since 6.2.0 + * @excluding enabled + * @product gantt + * @requires highcharts-gantt + * @apioption series.xrange.data.connect + */ + /** + * The ID of the point to connect to. + * + * @type {string} + * @since 6.2.0 + * @product gantt + * @apioption series.xrange.data.connect.to + */ + /** + * Get point bounding box using plotX/plotY and shapeArgs. If using + * graphic.getBBox() directly, the bbox will be affected by animation. + * + * @private + * @function + * + * @param {Highcharts.Point} point + * The point to get BB of. + * + * @return {Highcharts.Dictionary|null} + * Result xMax, xMin, yMax, yMin. + */ + function getPointBB(point) { + var shapeArgs = point.shapeArgs, + bb; + // Prefer using shapeArgs (columns) + if (shapeArgs) { + return { + xMin: shapeArgs.x, + xMax: shapeArgs.x + shapeArgs.width, + yMin: shapeArgs.y, + yMax: shapeArgs.y + shapeArgs.height + }; + } + // Otherwise use plotX/plotY and bb + bb = point.graphic && point.graphic.getBBox(); + return bb ? { + xMin: point.plotX - bb.width / 2, + xMax: point.plotX + bb.width / 2, + yMin: point.plotY - bb.height / 2, + yMax: point.plotY + bb.height / 2 + } : null; + } + /** + * Calculate margin to place around obstacles for the pathfinder in pixels. + * Returns a minimum of 1 pixel margin. + * + * @private + * @function + * + * @param {Array} obstacles + * Obstacles to calculate margin from. + * + * @return {number} + * The calculated margin in pixels. At least 1. + */ + function calculateObstacleMargin(obstacles) { + var len = obstacles.length, + i = 0, + j, + obstacleDistance, + distances = [], + // Compute smallest distance between two rectangles + distance = function (a, + b, + bbMargin) { + // Count the distance even if we are slightly off + var margin = pick(bbMargin, 10), + yOverlap = a.yMax + margin > b.yMin - margin && + a.yMin - margin < b.yMax + margin, + xOverlap = a.xMax + margin > b.xMin - margin && + a.xMin - margin < b.xMax + margin, + xDistance = yOverlap ? (a.xMin > b.xMax ? a.xMin - b.xMax : b.xMin - a.xMax) : Infinity, + yDistance = xOverlap ? (a.yMin > b.yMax ? a.yMin - b.yMax : b.yMin - a.yMax) : Infinity; + // If the rectangles collide, try recomputing with smaller margin. + // If they collide anyway, discard the obstacle. + if (xOverlap && yOverlap) { + return (margin ? + distance(a, b, Math.floor(margin / 2)) : + Infinity); + } + return min(xDistance, yDistance); + }; + // Go over all obstacles and compare them to the others. + for (; i < len; ++i) { + // Compare to all obstacles ahead. We will already have compared this + // obstacle to the ones before. + for (j = i + 1; j < len; ++j) { + obstacleDistance = distance(obstacles[i], obstacles[j]); + // TODO: Magic number 80 + if (obstacleDistance < 80) { // Ignore large distances + distances.push(obstacleDistance); + } + } + } + // Ensure we always have at least one value, even in very spaceous charts + distances.push(80); + return max(Math.floor(distances.sort(function (a, b) { + return (a - b); + })[ + // Discard first 10% of the relevant distances, and then grab + // the smallest one. + Math.floor(distances.length / 10)] / 2 - 1 // Divide the distance by 2 and subtract 1. + ), 1 // 1 is the minimum margin + ); + } + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The Pathfinder class. + * + * @private + * @class + * @name Highcharts.Pathfinder + * + * @param {Highcharts.Chart} chart + * The chart to operate on. + */ + var Pathfinder = /** @class */ (function () { + function Pathfinder(chart) { + /* * + * + * Properties + * + * */ + this.chart = void 0; + this.chartObstacles = void 0; + this.chartObstacleMetrics = void 0; + this.connections = void 0; + this.group = void 0; + this.lineObstacles = void 0; + this.init(chart); + } + /** + * @name Highcharts.Pathfinder#algorithms + * @type {Highcharts.Dictionary} + */ + /** + * Initialize the Pathfinder object. + * + * @function Highcharts.Pathfinder#init + * + * @param {Highcharts.Chart} chart + * The chart context. + */ + Pathfinder.prototype.init = function (chart) { + // Initialize pathfinder with chart context + this.chart = chart; + // Init connection reference list + this.connections = []; + // Recalculate paths/obstacles on chart redraw + addEvent(chart, 'redraw', function () { + this.pathfinder.update(); + }); + }; + /** + * Update Pathfinder connections from scratch. + * + * @function Highcharts.Pathfinder#update + * + * @param {boolean} [deferRender] + * Whether or not to defer rendering of connections until + * series.afterAnimate event has fired. Used on first render. + */ + Pathfinder.prototype.update = function (deferRender) { + var chart = this.chart, + pathfinder = this, + oldConnections = pathfinder.connections; + // Rebuild pathfinder connections from options + pathfinder.connections = []; + chart.series.forEach(function (series) { + if (series.visible && !series.options.isInternal) { + series.points.forEach(function (point) { + var to, + connects = (point.options && + point.options.connect && + splat(point.options.connect)); + if (point.visible && point.isInside !== false && connects) { + connects.forEach(function (connect) { + to = chart.get(typeof connect === 'string' ? + connect : connect.to); + if (to instanceof Point && + to.series.visible && + to.visible && + to.isInside !== false) { + // Add new connection + pathfinder.connections.push(new Connection(point, // from + to, typeof connect === 'string' ? + {} : + connect)); + } + }); + } + }); + } + }); + // Clear connections that should not be updated, and move old info over + // to new connections. + for (var j = 0, k, found, lenOld = oldConnections.length, lenNew = pathfinder.connections.length; j < lenOld; ++j) { + found = false; + for (k = 0; k < lenNew; ++k) { + if (oldConnections[j].fromPoint === + pathfinder.connections[k].fromPoint && + oldConnections[j].toPoint === + pathfinder.connections[k].toPoint) { + pathfinder.connections[k].graphics = + oldConnections[j].graphics; + found = true; + break; + } + } + if (!found) { + oldConnections[j].destroy(); + } + } + // Clear obstacles to force recalculation. This must be done on every + // redraw in case positions have changed. Recalculation is handled in + // Connection.getPath on demand. + delete this.chartObstacles; + delete this.lineObstacles; + // Draw the pending connections + pathfinder.renderConnections(deferRender); + }; + /** + * Draw the chart's connecting paths. + * + * @function Highcharts.Pathfinder#renderConnections + * + * @param {boolean} [deferRender] + * Whether or not to defer render until series animation is finished. + * Used on first render. + */ + Pathfinder.prototype.renderConnections = function (deferRender) { + if (deferRender) { + // Render after series are done animating + this.chart.series.forEach(function (series) { + var render = function () { + // Find pathfinder connections belonging to this series + // that haven't rendered, and render them now. + var pathfinder = series.chart.pathfinder, + conns = pathfinder && pathfinder.connections || []; + conns.forEach(function (connection) { + if (connection.fromPoint && + connection.fromPoint.series === series) { + connection.render(); + } + }); + if (series.pathfinderRemoveRenderEvent) { + series.pathfinderRemoveRenderEvent(); + delete series.pathfinderRemoveRenderEvent; + } + }; + if (series.options.animation === false) { + render(); + } + else { + series.pathfinderRemoveRenderEvent = addEvent(series, 'afterAnimate', render); + } + }); + } + else { + // Go through connections and render them + this.connections.forEach(function (connection) { + connection.render(); + }); + } + }; + /** + * Get obstacles for the points in the chart. Does not include connecting + * lines from Pathfinder. Applies algorithmMargin to the obstacles. + * + * @function Highcharts.Pathfinder#getChartObstacles + * + * @param {object} options + * Options for the calculation. Currenlty only + * options.algorithmMargin. + * + * @return {Array} + * An array of calculated obstacles. Each obstacle is defined as an + * object with xMin, xMax, yMin and yMax properties. + */ + Pathfinder.prototype.getChartObstacles = function (options) { + var obstacles = [], + series = this.chart.series, + margin = pick(options.algorithmMargin, 0), + calculatedMargin; + for (var i = 0, sLen = series.length; i < sLen; ++i) { + if (series[i].visible && !series[i].options.isInternal) { + for (var j = 0, pLen = series[i].points.length, bb, point; j < pLen; ++j) { + point = series[i].points[j]; + if (point.visible) { + bb = getPointBB(point); + if (bb) { + obstacles.push({ + xMin: bb.xMin - margin, + xMax: bb.xMax + margin, + yMin: bb.yMin - margin, + yMax: bb.yMax + margin + }); + } + } + } + } + } + // Sort obstacles by xMin for optimization + obstacles = obstacles.sort(function (a, b) { + return a.xMin - b.xMin; + }); + // Add auto-calculated margin if the option is not defined + if (!defined(options.algorithmMargin)) { + calculatedMargin = + options.algorithmMargin = + calculateObstacleMargin(obstacles); + obstacles.forEach(function (obstacle) { + obstacle.xMin -= calculatedMargin; + obstacle.xMax += calculatedMargin; + obstacle.yMin -= calculatedMargin; + obstacle.yMax += calculatedMargin; + }); + } + return obstacles; + }; + /** + * Utility function to get metrics for obstacles: + * - Widest obstacle width + * - Tallest obstacle height + * + * @function Highcharts.Pathfinder#getObstacleMetrics + * + * @param {Array} obstacles + * An array of obstacles to inspect. + * + * @return {object} + * The calculated metrics, as an object with maxHeight and maxWidth + * properties. + */ + Pathfinder.prototype.getObstacleMetrics = function (obstacles) { + var maxWidth = 0, + maxHeight = 0, + width, + height, + i = obstacles.length; + while (i--) { + width = obstacles[i].xMax - obstacles[i].xMin; + height = obstacles[i].yMax - obstacles[i].yMin; + if (maxWidth < width) { + maxWidth = width; + } + if (maxHeight < height) { + maxHeight = height; + } + } + return { + maxHeight: maxHeight, + maxWidth: maxWidth + }; + }; + /** + * Utility to get which direction to start the pathfinding algorithm + * (X vs Y), calculated from a set of marker options. + * + * @function Highcharts.Pathfinder#getAlgorithmStartDirection + * + * @param {Highcharts.ConnectorsMarkerOptions} markerOptions + * Marker options to calculate from. + * + * @return {boolean} + * Returns true for X, false for Y, and undefined for autocalculate. + */ + Pathfinder.prototype.getAlgorithmStartDirection = function (markerOptions) { + var xCenter = markerOptions.align !== 'left' && + markerOptions.align !== 'right', yCenter = markerOptions.verticalAlign !== 'top' && + markerOptions.verticalAlign !== 'bottom', undef; + return xCenter ? + (yCenter ? undef : false) : // x is centered + (yCenter ? true : undef); // x is off-center + }; + return Pathfinder; + }()); + Pathfinder.prototype.algorithms = pathfinderAlgorithms; + // Add to Highcharts namespace + H.Pathfinder = Pathfinder; + // Add pathfinding capabilities to Points + extend(Point.prototype, /** @lends Point.prototype */ { + /** + * Get coordinates of anchor point for pathfinder connection. + * + * @private + * @function Highcharts.Point#getPathfinderAnchorPoint + * + * @param {Highcharts.ConnectorsMarkerOptions} markerOptions + * Connection options for position on point. + * + * @return {Highcharts.PositionObject} + * An object with x/y properties for the position. Coordinates are + * in plot values, not relative to point. + */ + getPathfinderAnchorPoint: function (markerOptions) { + var bb = getPointBB(this), + x, + y; + switch (markerOptions.align) { // eslint-disable-line default-case + case 'right': + x = 'xMax'; + break; + case 'left': + x = 'xMin'; + } + switch (markerOptions.verticalAlign) { // eslint-disable-line default-case + case 'top': + y = 'yMin'; + break; + case 'bottom': + y = 'yMax'; + } + return { + x: x ? bb[x] : (bb.xMin + bb.xMax) / 2, + y: y ? bb[y] : (bb.yMin + bb.yMax) / 2 + }; + }, + /** + * Utility to get the angle from one point to another. + * + * @private + * @function Highcharts.Point#getRadiansToVector + * + * @param {Highcharts.PositionObject} v1 + * The first vector, as an object with x/y properties. + * + * @param {Highcharts.PositionObject} v2 + * The second vector, as an object with x/y properties. + * + * @return {number} + * The angle in degrees + */ + getRadiansToVector: function (v1, v2) { + var box; + if (!defined(v2)) { + box = getPointBB(this); + if (box) { + v2 = { + x: (box.xMin + box.xMax) / 2, + y: (box.yMin + box.yMax) / 2 + }; + } + } + return Math.atan2(v2.y - v1.y, v1.x - v2.x); + }, + /** + * Utility to get the position of the marker, based on the path angle and + * the marker's radius. + * + * @private + * @function Highcharts.Point#getMarkerVector + * + * @param {number} radians + * The angle in radians from the point center to another vector. + * + * @param {number} markerRadius + * The radius of the marker, to calculate the additional distance to + * the center of the marker. + * + * @param {object} anchor + * The anchor point of the path and marker as an object with x/y + * properties. + * + * @return {object} + * The marker vector as an object with x/y properties. + */ + getMarkerVector: function (radians, markerRadius, anchor) { + var twoPI = Math.PI * 2.0, + theta = radians, + bb = getPointBB(this), + rectWidth = bb.xMax - bb.xMin, + rectHeight = bb.yMax - bb.yMin, + rAtan = Math.atan2(rectHeight, + rectWidth), + tanTheta = 1, + leftOrRightRegion = false, + rectHalfWidth = rectWidth / 2.0, + rectHalfHeight = rectHeight / 2.0, + rectHorizontalCenter = bb.xMin + rectHalfWidth, + rectVerticalCenter = bb.yMin + rectHalfHeight, + edgePoint = { + x: rectHorizontalCenter, + y: rectVerticalCenter + }, + markerPoint = {}, + xFactor = 1, + yFactor = 1; + while (theta < -Math.PI) { + theta += twoPI; + } + while (theta > Math.PI) { + theta -= twoPI; + } + tanTheta = Math.tan(theta); + if ((theta > -rAtan) && (theta <= rAtan)) { + // Right side + yFactor = -1; + leftOrRightRegion = true; + } + else if (theta > rAtan && theta <= (Math.PI - rAtan)) { + // Top side + yFactor = -1; + } + else if (theta > (Math.PI - rAtan) || theta <= -(Math.PI - rAtan)) { + // Left side + xFactor = -1; + leftOrRightRegion = true; + } + else { + // Bottom side + xFactor = -1; + } + // Correct the edgePoint according to the placement of the marker + if (leftOrRightRegion) { + edgePoint.x += xFactor * (rectHalfWidth); + edgePoint.y += yFactor * (rectHalfWidth) * tanTheta; + } + else { + edgePoint.x += xFactor * (rectHeight / (2.0 * tanTheta)); + edgePoint.y += yFactor * (rectHalfHeight); + } + if (anchor.x !== rectHorizontalCenter) { + edgePoint.x = anchor.x; + } + if (anchor.y !== rectVerticalCenter) { + edgePoint.y = anchor.y; + } + markerPoint.x = edgePoint.x + (markerRadius * Math.cos(theta)); + markerPoint.y = edgePoint.y - (markerRadius * Math.sin(theta)); + return markerPoint; + } + }); + /** + * Warn if using legacy options. Copy the options over. Note that this will + * still break if using the legacy options in chart.update, addSeries etc. + * @private + */ + function warnLegacy(chart) { + if (chart.options.pathfinder || + chart.series.reduce(function (acc, series) { + if (series.options) { + merge(true, (series.options.connectors = series.options.connectors || + {}), series.options.pathfinder); + } + return acc || series.options && series.options.pathfinder; + }, false)) { + merge(true, (chart.options.connectors = chart.options.connectors || {}), chart.options.pathfinder); + error('WARNING: Pathfinder options have been renamed. ' + + 'Use "chart.connectors" or "series.connectors" instead.'); + } + } + // Initialize Pathfinder for charts + Chart.prototype.callbacks.push(function (chart) { + var options = chart.options; + if (options.connectors.enabled !== false) { + warnLegacy(chart); + this.pathfinder = new Pathfinder(this); + this.pathfinder.update(true); // First draw, defer render + } + }); + + return Pathfinder; + }); + _registerModule(_modules, 'Series/XRangeSeries.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Globals.js'], _modules['Core/Color.js'], _modules['Core/Series/Point.js'], _modules['Core/Utilities.js']], function (Axis, H, Color, Point, U) { + /* * + * + * X-range series module + * + * (c) 2010-2020 Torstein Honsi, Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var color = Color.parse; + var addEvent = U.addEvent, + clamp = U.clamp, + correctFloat = U.correctFloat, + defined = U.defined, + find = U.find, + isNumber = U.isNumber, + isObject = U.isObject, + merge = U.merge, + pick = U.pick, + seriesType = U.seriesType; + /* * + * @interface Highcharts.PointOptionsObject in parts/Point.ts + */ /** + * The ending X value of the range point. + * @name Highcharts.PointOptionsObject#x2 + * @type {number|undefined} + * @requires modules/xrange + */ + var columnType = H.seriesTypes.column, + seriesTypes = H.seriesTypes, + Series = H.Series; + /** + * Return color of a point based on its category. + * + * @private + * @function getColorByCategory + * + * @param {object} series + * The series which the point belongs to. + * + * @param {object} point + * The point to calculate its color for. + * + * @return {object} + * Returns an object containing the properties color and colorIndex. + */ + function getColorByCategory(series, point) { + var colors = series.options.colors || series.chart.options.colors, + colorCount = colors ? + colors.length : + series.chart.options.chart.colorCount, + colorIndex = point.y % colorCount, + color = colors && colors[colorIndex]; + return { + colorIndex: colorIndex, + color: color + }; + } + /** + * @private + * @class + * @name Highcharts.seriesTypes.xrange + * + * @augments Highcharts.Series + */ + seriesType('xrange', 'column' + /** + * The X-range series displays ranges on the X axis, typically time + * intervals with a start and end date. + * + * @sample {highcharts} highcharts/demo/x-range/ + * X-range + * @sample {highcharts} highcharts/css/x-range/ + * Styled mode X-range + * @sample {highcharts} highcharts/chart/inverted-xrange/ + * Inverted X-range + * + * @extends plotOptions.column + * @since 6.0.0 + * @product highcharts highstock gantt + * @excluding boostThreshold, crisp, cropThreshold, depth, edgeColor, + * edgeWidth, findNearestPointBy, getExtremesFromAll, + * negativeColor, pointInterval, pointIntervalUnit, + * pointPlacement, pointRange, pointStart, softThreshold, + * stacking, threshold, data, dataSorting, boostBlending + * @requires modules/xrange + * @optionparent plotOptions.xrange + */ + , { + /** + * A partial fill for each point, typically used to visualize how much + * of a task is performed. The partial fill object can be set either on + * series or point level. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range with partial fill + * + * @product highcharts highstock gantt + * @apioption plotOptions.xrange.partialFill + */ + /** + * The fill color to be used for partial fills. Defaults to a darker + * shade of the point color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock gantt + * @apioption plotOptions.xrange.partialFill.fill + */ + /** + * A partial fill for each point, typically used to visualize how much + * of a task is performed. See [completed](series.gantt.data.completed). + * + * @sample gantt/demo/progress-indicator + * Gantt with progress indicator + * + * @product gantt + * @apioption plotOptions.gantt.partialFill + */ + /** + * In an X-range series, this option makes all points of the same Y-axis + * category the same color. + */ + colorByPoint: true, + dataLabels: { + formatter: function () { + var point = this.point, + amount = point.partialFill; + if (isObject(amount)) { + amount = amount.amount; + } + if (isNumber(amount) && amount > 0) { + return correctFloat(amount * 100) + '%'; + } + }, + inside: true, + verticalAlign: 'middle' + }, + tooltip: { + headerFormat: '{point.x} - {point.x2}
    ', + pointFormat: '\u25CF {series.name}: {point.yCategory}
    ' + }, + borderRadius: 3, + pointRange: 0 + }, { + type: 'xrange', + parallelArrays: ['x', 'x2', 'y'], + requireSorting: false, + animate: seriesTypes.line.prototype.animate, + cropShoulder: 1, + getExtremesFromAll: true, + autoIncrement: H.noop, + buildKDTree: H.noop, + /* eslint-disable valid-jsdoc */ + /** + * @private + * @function Highcarts.seriesTypes.xrange#init + * @return {void} + */ + init: function () { + seriesTypes.column.prototype.init.apply(this, arguments); + this.options.stacking = void 0; // #13161 + }, + /** + * Borrow the column series metrics, but with swapped axes. This gives + * free access to features like groupPadding, grouping, pointWidth etc. + * + * @private + * @function Highcharts.Series#getColumnMetrics + * + * @return {Highcharts.ColumnMetricsObject} + */ + getColumnMetrics: function () { + var metrics, + chart = this.chart; + /** + * @private + */ + function swapAxes() { + chart.series.forEach(function (s) { + var xAxis = s.xAxis; + s.xAxis = s.yAxis; + s.yAxis = xAxis; + }); + } + swapAxes(); + metrics = columnType.prototype.getColumnMetrics.call(this); + swapAxes(); + return metrics; + }, + /** + * Override cropData to show a point where x or x2 is outside visible + * range, but one of them is inside. + * + * @private + * @function Highcharts.Series#cropData + * + * @param {Array} xData + * + * @param {Array} yData + * + * @param {number} min + * + * @param {number} max + * + * @param {number} [cropShoulder] + * + * @return {*} + */ + cropData: function (xData, yData, min, max) { + // Replace xData with x2Data to find the appropriate cropStart + var cropData = Series.prototype.cropData, + crop = cropData.call(this, + this.x2Data, + yData, + min, + max); + // Re-insert the cropped xData + crop.xData = xData.slice(crop.start, crop.end); + return crop; + }, + /** + * Finds the index of an existing point that matches the given point + * options. + * + * @private + * @function Highcharts.Series#findPointIndex + * @param {object} options The options of the point. + * @returns {number|undefined} Returns index of a matching point, + * returns undefined if no match is found. + */ + findPointIndex: function (options) { + var _a = this, + cropped = _a.cropped, + cropStart = _a.cropStart, + points = _a.points; + var id = options.id; + var pointIndex; + if (id) { + var point = find(points, + function (point) { + return point.id === id; + }); + pointIndex = point ? point.index : void 0; + } + if (typeof pointIndex === 'undefined') { + var point = find(points, + function (point) { + return (point.x === options.x && + point.x2 === options.x2 && + !point.touched); + }); + pointIndex = point ? point.index : void 0; + } + // Reduce pointIndex if data is cropped + if (cropped && + isNumber(pointIndex) && + isNumber(cropStart) && + pointIndex >= cropStart) { + pointIndex -= cropStart; + } + return pointIndex; + }, + /** + * @private + * @function Highcharts.Series#translatePoint + * + * @param {Highcharts.Point} point + */ + translatePoint: function (point) { + var series = this, + xAxis = series.xAxis, + yAxis = series.yAxis, + metrics = series.columnMetrics, + options = series.options, + minPointLength = options.minPointLength || 0, + plotX = point.plotX, + posX = pick(point.x2, + point.x + (point.len || 0)), + plotX2 = xAxis.translate(posX, 0, 0, 0, 1), + length = Math.abs(plotX2 - plotX), + widthDifference, + shapeArgs, + partialFill, + inverted = this.chart.inverted, + borderWidth = pick(options.borderWidth, 1), + crisper = borderWidth % 2 / 2, + yOffset = metrics.offset, + pointHeight = Math.round(metrics.width), + dlLeft, + dlRight, + dlWidth, + clipRectWidth, + tooltipYOffset; + if (minPointLength) { + widthDifference = minPointLength - length; + if (widthDifference < 0) { + widthDifference = 0; + } + plotX -= widthDifference / 2; + plotX2 += widthDifference / 2; + } + plotX = Math.max(plotX, -10); + plotX2 = clamp(plotX2, -10, xAxis.len + 10); + // Handle individual pointWidth + if (defined(point.options.pointWidth)) { + yOffset -= ((Math.ceil(point.options.pointWidth) - pointHeight) / 2); + pointHeight = Math.ceil(point.options.pointWidth); + } + // Apply pointPlacement to the Y axis + if (options.pointPlacement && + isNumber(point.plotY) && + yAxis.categories) { + point.plotY = yAxis.translate(point.y, 0, 1, 0, 1, options.pointPlacement); + } + point.shapeArgs = { + x: Math.floor(Math.min(plotX, plotX2)) + crisper, + y: Math.floor(point.plotY + yOffset) + crisper, + width: Math.round(Math.abs(plotX2 - plotX)), + height: pointHeight, + r: series.options.borderRadius + }; + // Align data labels inside the shape and inside the plot area + dlLeft = point.shapeArgs.x; + dlRight = dlLeft + point.shapeArgs.width; + if (dlLeft < 0 || dlRight > xAxis.len) { + dlLeft = clamp(dlLeft, 0, xAxis.len); + dlRight = clamp(dlRight, 0, xAxis.len); + dlWidth = dlRight - dlLeft; + point.dlBox = merge(point.shapeArgs, { + x: dlLeft, + width: dlRight - dlLeft, + centerX: dlWidth ? dlWidth / 2 : null + }); + } + else { + point.dlBox = null; + } + // Tooltip position + var tooltipPos = point.tooltipPos; + var xIndex = !inverted ? 0 : 1; + var yIndex = !inverted ? 1 : 0; + tooltipYOffset = series.columnMetrics ? + series.columnMetrics.offset : -metrics.width / 2; + // Limit position by the correct axis size (#9727) + tooltipPos[xIndex] = clamp(tooltipPos[xIndex] + ((!inverted ? 1 : -1) * (xAxis.reversed ? -1 : 1) * + (length / 2)), 0, xAxis.len - 1); + tooltipPos[yIndex] = clamp(tooltipPos[yIndex] + ((inverted ? -1 : 1) * tooltipYOffset), 0, yAxis.len - 1); + // Add a partShapeArgs to the point, based on the shapeArgs property + partialFill = point.partialFill; + if (partialFill) { + // Get the partial fill amount + if (isObject(partialFill)) { + partialFill = partialFill.amount; + } + // If it was not a number, assume 0 + if (!isNumber(partialFill)) { + partialFill = 0; + } + shapeArgs = point.shapeArgs; + point.partShapeArgs = { + x: shapeArgs.x, + y: shapeArgs.y, + width: shapeArgs.width, + height: shapeArgs.height, + r: series.options.borderRadius + }; + clipRectWidth = Math.max(Math.round(length * partialFill + point.plotX - + plotX), 0); + point.clipRectArgs = { + x: xAxis.reversed ? // #10717 + shapeArgs.x + length - clipRectWidth : + shapeArgs.x, + y: shapeArgs.y, + width: clipRectWidth, + height: shapeArgs.height + }; + } + }, + /** + * @private + * @function Highcharts.Series#translate + */ + translate: function () { + columnType.prototype.translate.apply(this, arguments); + this.points.forEach(function (point) { + this.translatePoint(point); + }, this); + }, + /** + * Draws a single point in the series. Needed for partial fill. + * + * This override turns point.graphic into a group containing the + * original graphic and an overlay displaying the partial fill. + * + * @private + * @function Highcharts.Series#drawPoint + * + * @param {Highcharts.Point} point + * An instance of Point in the series. + * + * @param {"animate"|"attr"} verb + * 'animate' (animates changes) or 'attr' (sets options) + */ + drawPoint: function (point, verb) { + var series = this, + seriesOpts = series.options, + renderer = series.chart.renderer, + graphic = point.graphic, + type = point.shapeType, + shapeArgs = point.shapeArgs, + partShapeArgs = point.partShapeArgs, + clipRectArgs = point.clipRectArgs, + pfOptions = point.partialFill, + cutOff = seriesOpts.stacking && !seriesOpts.borderRadius, + pointState = point.state, + stateOpts = (seriesOpts.states[pointState || 'normal'] || + {}), + pointStateVerb = typeof pointState === 'undefined' ? + 'attr' : verb, + pointAttr = series.pointAttribs(point, + pointState), + animation = pick(series.chart.options.chart.animation, + stateOpts.animation), + fill; + if (!point.isNull && point.visible !== false) { + // Original graphic + if (graphic) { // update + graphic.rect[verb](shapeArgs); + } + else { + point.graphic = graphic = renderer.g('point') + .addClass(point.getClassName()) + .add(point.group || series.group); + graphic.rect = renderer[type](merge(shapeArgs)) + .addClass(point.getClassName()) + .addClass('highcharts-partfill-original') + .add(graphic); + } + // Partial fill graphic + if (partShapeArgs) { + if (graphic.partRect) { + graphic.partRect[verb](merge(partShapeArgs)); + graphic.partialClipRect[verb](merge(clipRectArgs)); + } + else { + graphic.partialClipRect = renderer.clipRect(clipRectArgs.x, clipRectArgs.y, clipRectArgs.width, clipRectArgs.height); + graphic.partRect = + renderer[type](partShapeArgs) + .addClass('highcharts-partfill-overlay') + .add(graphic) + .clip(graphic.partialClipRect); + } + } + // Presentational + if (!series.chart.styledMode) { + graphic + .rect[verb](pointAttr, animation) + .shadow(seriesOpts.shadow, null, cutOff); + if (partShapeArgs) { + // Ensure pfOptions is an object + if (!isObject(pfOptions)) { + pfOptions = {}; + } + if (isObject(seriesOpts.partialFill)) { + pfOptions = merge(pfOptions, seriesOpts.partialFill); + } + fill = (pfOptions.fill || + color(pointAttr.fill).brighten(-0.3).get() || + color(point.color || series.color) + .brighten(-0.3).get()); + pointAttr.fill = fill; + graphic + .partRect[pointStateVerb](pointAttr, animation) + .shadow(seriesOpts.shadow, null, cutOff); + } + } + } + else if (graphic) { + point.graphic = graphic.destroy(); // #1269 + } + }, + /** + * @private + * @function Highcharts.Series#drawPoints + */ + drawPoints: function () { + var series = this, + verb = series.getAnimationVerb(); + // Draw the columns + series.points.forEach(function (point) { + series.drawPoint(point, verb); + }); + }, + /** + * Returns "animate", or "attr" if the number of points is above the + * animation limit. + * + * @private + * @function Highcharts.Series#getAnimationVerb + * + * @return {string} + */ + getAnimationVerb: function () { + return (this.chart.pointCount < (this.options.animationLimit || 250) ? + 'animate' : + 'attr'); + } + /* + // Override to remove stroke from points. For partial fill. + pointAttribs: function () { + var series = this, + retVal = columnType.prototype.pointAttribs + .apply(series, + arguments); + + //retVal['stroke-width'] = 0; + return retVal; + } + //*/ + /* eslint-enable valid-jsdoc */ + }, { + /** + * The ending X value of the range point. + * @name Highcharts.Point#x2 + * @type {number|undefined} + * @requires modules/xrange + */ + /** + * Extend applyOptions so that `colorByPoint` for x-range means that one + * color is applied per Y axis category. + * + * @private + * @function Highcharts.Point#applyOptions + * + * @return {Highcharts.Series} + */ + /* eslint-disable valid-jsdoc */ + /** + * @private + */ + resolveColor: function () { + var series = this.series, + colorByPoint; + if (series.options.colorByPoint && !this.options.color) { + colorByPoint = getColorByCategory(series, this); + if (!series.chart.styledMode) { + this.color = colorByPoint.color; + } + if (!this.options.colorIndex) { + this.colorIndex = colorByPoint.colorIndex; + } + } + else if (!this.color) { + this.color = series.color; + } + }, + /** + * Extend init to have y default to 0. + * + * @private + * @function Highcharts.Point#init + * + * @return {Highcharts.Point} + */ + init: function () { + Point.prototype.init.apply(this, arguments); + if (!this.y) { + this.y = 0; + } + return this; + }, + /** + * @private + * @function Highcharts.Point#setState + */ + setState: function () { + Point.prototype.setState.apply(this, arguments); + this.series.drawPoint(this, this.series.getAnimationVerb()); + }, + /** + * @private + * @function Highcharts.Point#getLabelConfig + * + * @return {Highcharts.PointLabelObject} + */ + // Add x2 and yCategory to the available properties for tooltip formats + getLabelConfig: function () { + var point = this, + cfg = Point.prototype.getLabelConfig.call(point), + yCats = point.series.yAxis.categories; + cfg.x2 = point.x2; + cfg.yCategory = point.yCategory = yCats && yCats[point.y]; + return cfg; + }, + tooltipDateKeys: ['x', 'x2'], + /** + * @private + * @function Highcharts.Point#isValid + * + * @return {boolean} + */ + isValid: function () { + return typeof this.x === 'number' && + typeof this.x2 === 'number'; + } + /* eslint-enable valid-jsdoc */ + }); + /** + * Max x2 should be considered in xAxis extremes + */ + addEvent(Axis, 'afterGetSeriesExtremes', function () { + var axis = this, // eslint-disable-line no-invalid-this + axisSeries = axis.series, + dataMax, + modMax; + if (axis.isXAxis) { + dataMax = pick(axis.dataMax, -Number.MAX_VALUE); + axisSeries.forEach(function (series) { + if (series.x2Data) { + series.x2Data + .forEach(function (val) { + if (val > dataMax) { + dataMax = val; + modMax = true; + } + }); + } + }); + if (modMax) { + axis.dataMax = dataMax; + } + } + }); + /** + * An `xrange` series. If the [type](#series.xrange.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.xrange + * @excluding boostThreshold, crisp, cropThreshold, depth, edgeColor, edgeWidth, + * findNearestPointBy, getExtremesFromAll, negativeColor, + * pointInterval, pointIntervalUnit, pointPlacement, pointRange, + * pointStart, softThreshold, stacking, threshold, dataSorting, + * boostBlending + * @product highcharts highstock gantt + * @requires modules/xrange + * @apioption series.xrange + */ + /** + * An array of data points for the series. For the `xrange` series type, + * points can be given in the following ways: + * + * 1. An array of objects with named values. The objects are point configuration + * objects as seen below. + * ```js + * data: [{ + * x: Date.UTC(2017, 0, 1), + * x2: Date.UTC(2017, 0, 3), + * name: "Test", + * y: 0, + * color: "#00FF00" + * }, { + * x: Date.UTC(2017, 0, 4), + * x2: Date.UTC(2017, 0, 5), + * name: "Deploy", + * y: 1, + * color: "#FF0000" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @declare Highcharts.XrangePointOptionsObject + * @type {Array<*>} + * @extends series.line.data + * @product highcharts highstock gantt + * @apioption series.xrange.data + */ + /** + * The starting X value of the range point. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.x + */ + /** + * The ending X value of the range point. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.x2 + */ + /** + * The Y value of the range point. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.y + */ + /** + * A partial fill for each point, typically used to visualize how much of + * a task is performed. The partial fill object can be set either on series + * or point level. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range with partial fill + * + * @declare Highcharts.XrangePointPartialFillOptionsObject + * @product highcharts highstock gantt + * @apioption series.xrange.data.partialFill + */ + /** + * The amount of the X-range point to be filled. Values can be 0-1 and are + * converted to percentages in the default data label formatter. + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.partialFill.amount + */ + /** + * The fill color to be used for partial fills. Defaults to a darker shade + * of the point color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock gantt + * @apioption series.xrange.data.partialFill.fill + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'Series/GanttSeries.js', [_modules['Core/Globals.js'], _modules['Core/Options.js'], _modules['Core/Utilities.js']], function (H, O, U) { + /* * + * + * (c) 2016-2020 Highsoft AS + * + * Author: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var dateFormat = O.dateFormat; + var isNumber = U.isNumber, + merge = U.merge, + pick = U.pick, + seriesType = U.seriesType, + splat = U.splat; + var seriesTypes = H.seriesTypes, + Series = H.Series, + parent = seriesTypes.xrange; + /** + * @private + * @class + * @name Highcharts.seriesTypes.gantt + * + * @augments Highcharts.Series + */ + seriesType('gantt', 'xrange' + /** + * A `gantt` series. If the [type](#series.gantt.type) option is not specified, + * it is inherited from [chart.type](#chart.type). + * + * @extends plotOptions.xrange + * @product gantt + * @requires highcharts-gantt + * @optionparent plotOptions.gantt + */ + , { + // options - default options merged with parent + grouping: false, + dataLabels: { + enabled: true + }, + tooltip: { + headerFormat: '{series.name}
    ', + pointFormat: null, + pointFormatter: function () { + var point = this, + series = point.series, + tooltip = series.chart.tooltip, + xAxis = series.xAxis, + formats = series.tooltipOptions.dateTimeLabelFormats, + startOfWeek = xAxis.options.startOfWeek, + ttOptions = series.tooltipOptions, + format = ttOptions.xDateFormat, + start, + end, + milestone = point.options.milestone, + retVal = '' + (point.name || point.yCategory) + ''; + if (ttOptions.pointFormat) { + return point.tooltipFormatter(ttOptions.pointFormat); + } + if (!format) { + format = splat(tooltip.getDateFormat(xAxis.closestPointRange, point.start, startOfWeek, formats))[0]; + } + start = dateFormat(format, point.start); + end = dateFormat(format, point.end); + retVal += '
    '; + if (!milestone) { + retVal += 'Start: ' + start + '
    '; + retVal += 'End: ' + end + '
    '; + } + else { + retVal += start + '
    '; + } + return retVal; + } + }, + connectors: { + type: 'simpleConnect', + /** + * @declare Highcharts.ConnectorsAnimationOptionsObject + */ + animation: { + reversed: true // Dependencies go from child to parent + }, + startMarker: { + enabled: true, + symbol: 'arrow-filled', + radius: 4, + fill: '#fa0', + align: 'left' + }, + endMarker: { + enabled: false, + align: 'right' + } + } + }, { + pointArrayMap: ['start', 'end', 'y'], + // Keyboard navigation, don't use nearest vertical mode + keyboardMoveVertical: false, + /* eslint-disable valid-jsdoc */ + /** + * Handle milestones, as they have no x2. + * @private + */ + translatePoint: function (point) { + var series = this, + shapeArgs, + size; + parent.prototype.translatePoint.call(series, point); + if (point.options.milestone) { + shapeArgs = point.shapeArgs; + size = shapeArgs.height; + point.shapeArgs = { + x: shapeArgs.x - (size / 2), + y: shapeArgs.y, + width: size, + height: size + }; + } + }, + /** + * Draws a single point in the series. + * + * This override draws the point as a diamond if point.options.milestone + * is true, and uses the original drawPoint() if it is false or not set. + * + * @requires highcharts-gantt + * + * @private + * @function Highcharts.seriesTypes.gantt#drawPoint + * + * @param {Highcharts.Point} point + * An instance of Point in the series + * + * @param {"animate"|"attr"} verb + * 'animate' (animates changes) or 'attr' (sets options) + * + * @return {void} + */ + drawPoint: function (point, verb) { + var series = this, + seriesOpts = series.options, + renderer = series.chart.renderer, + shapeArgs = point.shapeArgs, + plotY = point.plotY, + graphic = point.graphic, + state = point.selected && 'select', + cutOff = seriesOpts.stacking && !seriesOpts.borderRadius, + diamondShape; + if (point.options.milestone) { + if (isNumber(plotY) && point.y !== null && point.visible !== false) { + diamondShape = renderer.symbols.diamond(shapeArgs.x, shapeArgs.y, shapeArgs.width, shapeArgs.height); + if (graphic) { + graphic[verb]({ + d: diamondShape + }); + } + else { + point.graphic = graphic = renderer.path(diamondShape) + .addClass(point.getClassName(), true) + .add(point.group || series.group); + } + // Presentational + if (!series.chart.styledMode) { + point.graphic + .attr(series.pointAttribs(point, state)) + .shadow(seriesOpts.shadow, null, cutOff); + } + } + else if (graphic) { + point.graphic = graphic.destroy(); // #1269 + } + } + else { + parent.prototype.drawPoint.call(series, point, verb); + } + }, + setData: Series.prototype.setData, + /** + * @private + */ + setGanttPointAliases: function (options) { + /** + * Add a value to options if the value exists. + * @private + */ + function addIfExists(prop, val) { + if (typeof val !== 'undefined') { + options[prop] = val; + } + } + addIfExists('x', pick(options.start, options.x)); + addIfExists('x2', pick(options.end, options.x2)); + addIfExists('partialFill', pick(options.completed, options.partialFill)); + addIfExists('connect', pick(options.dependency, options.connect)); + } + /* eslint-enable valid-jsdoc */ + }, merge(parent.prototype.pointClass.prototype, { + // pointProps - point member overrides. We inherit from parent as well. + /* eslint-disable valid-jsdoc */ + /** + * Applies the options containing the x and y data and possible some + * extra properties. This is called on point init or from point.update. + * + * @private + * @function Highcharts.Point#applyOptions + * + * @param {object} options + * The point options + * + * @param {number} x + * The x value + * + * @return {Highcharts.Point} + * The Point instance + */ + applyOptions: function (options, x) { + var point = this, + retVal = merge(options); + H.seriesTypes.gantt.prototype.setGanttPointAliases(retVal); + retVal = parent.prototype.pointClass.prototype.applyOptions + .call(point, retVal, x); + return retVal; + }, + isValid: function () { + return ((typeof this.start === 'number' || + typeof this.x === 'number') && + (typeof this.end === 'number' || + typeof this.x2 === 'number' || + this.milestone)); + } + /* eslint-enable valid-jsdoc */ + })); + /** + * A `gantt` series. + * + * @extends series,plotOptions.gantt + * @excluding boostThreshold, connectors, dashStyle, findNearestPointBy, + * getExtremesFromAll, marker, negativeColor, pointInterval, + * pointIntervalUnit, pointPlacement, pointStart + * @product gantt + * @requires highcharts-gantt + * @apioption series.gantt + */ + /** + * Data for a Gantt series. + * + * @declare Highcharts.GanttPointOptionsObject + * @type {Array<*>} + * @extends series.xrange.data + * @excluding className, color, colorIndex, connect, dataLabels, events, + * partialFill, selected, x, x2 + * @product gantt + * @apioption series.gantt.data + */ + /** + * Whether the grid node belonging to this point should start as collapsed. Used + * in axes of type treegrid. + * + * @sample {gantt} gantt/treegrid-axis/collapsed/ + * Start as collapsed + * + * @type {boolean} + * @default false + * @product gantt + * @apioption series.gantt.data.collapsed + */ + /** + * The start time of a task. + * + * @type {number} + * @product gantt + * @apioption series.gantt.data.start + */ + /** + * The end time of a task. + * + * @type {number} + * @product gantt + * @apioption series.gantt.data.end + */ + /** + * The Y value of a task. + * + * @type {number} + * @product gantt + * @apioption series.gantt.data.y + */ + /** + * The name of a task. If a `treegrid` y-axis is used (default in Gantt charts), + * this will be picked up automatically, and used to calculate the y-value. + * + * @type {string} + * @product gantt + * @apioption series.gantt.data.name + */ + /** + * Progress indicator, how much of the task completed. If it is a number, the + * `fill` will be applied automatically. + * + * @sample {gantt} gantt/demo/progress-indicator + * Progress indicator + * + * @type {number|*} + * @extends series.xrange.data.partialFill + * @product gantt + * @apioption series.gantt.data.completed + */ + /** + * The amount of the progress indicator, ranging from 0 (not started) to 1 + * (finished). + * + * @type {number} + * @default 0 + * @apioption series.gantt.data.completed.amount + */ + /** + * The fill of the progress indicator. Defaults to a darkened variety of the + * main color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption series.gantt.data.completed.fill + */ + /** + * The ID of the point (task) that this point depends on in Gantt charts. + * Aliases [connect](series.xrange.data.connect). Can also be an object, + * specifying further connecting [options](series.gantt.connectors) between the + * points. Multiple connections can be specified by providing an array. + * + * @sample gantt/demo/project-management + * Dependencies + * @sample gantt/pathfinder/demo + * Different connection types + * + * @type {string|Array|*} + * @extends series.xrange.data.connect + * @since 6.2.0 + * @product gantt + * @apioption series.gantt.data.dependency + */ + /** + * Whether this point is a milestone. If so, only the `start` option is handled, + * while `end` is ignored. + * + * @sample gantt/gantt/milestones + * Milestones + * + * @type {boolean} + * @since 6.2.0 + * @product gantt + * @apioption series.gantt.data.milestone + */ + /** + * The ID of the parent point (task) of this point in Gantt charts. + * + * @sample gantt/demo/subtasks + * Gantt chart with subtasks + * + * @type {string} + * @since 6.2.0 + * @product gantt + * @apioption series.gantt.data.parent + */ + /** + * @excluding afterAnimate + * @apioption series.gantt.events + */ + ''; // adds doclets above to the transpiled file + + }); + _registerModule(_modules, 'Core/Chart/GanttChart.js', [_modules['Core/Chart/Chart.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (Chart, H, U) { + /* * + * + * (c) 2016-2020 Highsoft AS + * + * Author: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var getOptions = U.getOptions, + isArray = U.isArray, + merge = U.merge, + splat = U.splat; + /** + * Factory function for Gantt charts. + * + * @example + * // Render a chart in to div#container + * var chart = Highcharts.ganttChart('container', { + * title: { + * text: 'My chart' + * }, + * series: [{ + * data: ... + * }] + * }); + * + * @function Highcharts.ganttChart + * + * @param {string|Highcharts.HTMLDOMElement} renderTo + * The DOM element to render to, or its id. + * + * @param {Highcharts.Options} options + * The chart options structure. + * + * @param {Highcharts.ChartCallbackFunction} [callback] + * Function to run when the chart has loaded and and all external images + * are loaded. Defining a + * [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load) + * handler is equivalent. + * + * @return {Highcharts.Chart} + * Returns the Chart object. + */ + H.ganttChart = function (renderTo, options, callback) { + var hasRenderToArg = typeof renderTo === 'string' || renderTo.nodeName, + seriesOptions = options.series, + defaultOptions = getOptions(), + defaultLinkedTo, + userOptions = options; + options = arguments[hasRenderToArg ? 1 : 0]; + // If user hasn't defined axes as array, make it into an array and add a + // second axis by default. + if (!isArray(options.xAxis)) { + options.xAxis = [options.xAxis || {}, {}]; + } + // apply X axis options to both single and multi x axes + options.xAxis = options.xAxis.map(function (xAxisOptions, i) { + if (i === 1) { // Second xAxis + defaultLinkedTo = 0; + } + return merge(defaultOptions.xAxis, { + grid: { + enabled: true + }, + opposite: true, + linkedTo: defaultLinkedTo + }, xAxisOptions, // user options + { + type: 'datetime' + }); + }); + // apply Y axis options to both single and multi y axes + options.yAxis = (splat(options.yAxis || {})).map(function (yAxisOptions) { + return merge(defaultOptions.yAxis, // #3802 + { + grid: { + enabled: true + }, + staticScale: 50, + reversed: true, + // Set default type treegrid, but only if 'categories' is + // undefined + type: yAxisOptions.categories ? yAxisOptions.type : 'treegrid' + }, yAxisOptions // user options + ); + }); + options.series = null; + options = merge(true, { + chart: { + type: 'gantt' + }, + title: { + text: null + }, + legend: { + enabled: false + }, + navigator: { + series: { type: 'gantt' } + } + }, options, // user's options + // forced options + { + isGantt: true + }); + options.series = userOptions.series = seriesOptions; + (options.series || []).forEach(function (series) { + if (series.data) { + series.data.forEach(function (point) { + H.seriesTypes.gantt.prototype.setGanttPointAliases(point); + }); + } + }); + return hasRenderToArg ? + new Chart(renderTo, options, callback) : + new Chart(options, options); // @todo does not look correct + }; + + }); + _registerModule(_modules, 'Core/Axis/ScrollbarAxis.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + defined = U.defined, + pick = U.pick; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Creates scrollbars if enabled. + * + * @private + */ + var ScrollbarAxis = /** @class */ (function () { + function ScrollbarAxis() { + } + /** + * Attaches to axis events to create scrollbars if enabled. + * + * @private + * + * @param AxisClass + * Axis class to extend. + * + * @param ScrollbarClass + * Scrollbar class to use. + */ + ScrollbarAxis.compose = function (AxisClass, ScrollbarClass) { + // Wrap axis initialization and create scrollbar if enabled: + addEvent(AxisClass, 'afterInit', function () { + var axis = this; + if (axis.options && + axis.options.scrollbar && + axis.options.scrollbar.enabled) { + // Predefined options: + axis.options.scrollbar.vertical = !axis.horiz; + axis.options.startOnTick = axis.options.endOnTick = false; + axis.scrollbar = new ScrollbarClass(axis.chart.renderer, axis.options.scrollbar, axis.chart); + addEvent(axis.scrollbar, 'changed', function (e) { + var axisMin = pick(axis.options && axis.options.min, + axis.min), + axisMax = pick(axis.options && axis.options.max, + axis.max), + unitedMin = defined(axis.dataMin) ? + Math.min(axisMin, + axis.min, + axis.dataMin) : axisMin, + unitedMax = defined(axis.dataMax) ? + Math.max(axisMax, + axis.max, + axis.dataMax) : axisMax, + range = unitedMax - unitedMin, + to, + from; + // #12834, scroll when show/hide series, wrong extremes + if (!defined(axisMin) || !defined(axisMax)) { + return; + } + if ((axis.horiz && !axis.reversed) || + (!axis.horiz && axis.reversed)) { + to = unitedMin + range * this.to; + from = unitedMin + range * this.from; + } + else { + // y-values in browser are reversed, but this also + // applies for reversed horizontal axis: + to = unitedMin + range * (1 - this.from); + from = unitedMin + range * (1 - this.to); + } + if (pick(this.options.liveRedraw, H.svg && !H.isTouchDevice && !this.chart.isBoosting) || + // Mouseup always should change extremes + e.DOMType === 'mouseup' || + // Internal events + !defined(e.DOMType)) { + axis.setExtremes(from, to, true, e.DOMType !== 'mousemove', e); + } + else { + // When live redraw is disabled, don't change extremes + // Only change the position of the scollbar thumb + this.setRange(this.from, this.to); + } + }); + } + }); + // Wrap rendering axis, and update scrollbar if one is created: + addEvent(AxisClass, 'afterRender', function () { + var axis = this, + scrollMin = Math.min(pick(axis.options.min, + axis.min), + axis.min, + pick(axis.dataMin, + axis.min) // #6930 + ), + scrollMax = Math.max(pick(axis.options.max, + axis.max), + axis.max, + pick(axis.dataMax, + axis.max) // #6930 + ), + scrollbar = axis.scrollbar, + offset = axis.axisTitleMargin + (axis.titleOffset || 0), + scrollbarsOffsets = axis.chart.scrollbarsOffsets, + axisMargin = axis.options.margin || 0, + offsetsIndex, + from, + to; + if (scrollbar) { + if (axis.horiz) { + // Reserve space for labels/title + if (!axis.opposite) { + scrollbarsOffsets[1] += offset; + } + scrollbar.position(axis.left, axis.top + axis.height + 2 + scrollbarsOffsets[1] - + (axis.opposite ? axisMargin : 0), axis.width, axis.height); + // Next scrollbar should reserve space for margin (if set) + if (!axis.opposite) { + scrollbarsOffsets[1] += axisMargin; + } + offsetsIndex = 1; + } + else { + // Reserve space for labels/title + if (axis.opposite) { + scrollbarsOffsets[0] += offset; + } + scrollbar.position(axis.left + axis.width + 2 + scrollbarsOffsets[0] - + (axis.opposite ? 0 : axisMargin), axis.top, axis.width, axis.height); + // Next scrollbar should reserve space for margin (if set) + if (axis.opposite) { + scrollbarsOffsets[0] += axisMargin; + } + offsetsIndex = 0; + } + scrollbarsOffsets[offsetsIndex] += scrollbar.size + + scrollbar.options.margin; + if (isNaN(scrollMin) || + isNaN(scrollMax) || + !defined(axis.min) || + !defined(axis.max) || + axis.min === axis.max // #10733 + ) { + // default action: when extremes are the same or there is + // not extremes on the axis, but scrollbar exists, make it + // full size + scrollbar.setRange(0, 1); + } + else { + from = + (axis.min - scrollMin) / (scrollMax - scrollMin); + to = + (axis.max - scrollMin) / (scrollMax - scrollMin); + if ((axis.horiz && !axis.reversed) || + (!axis.horiz && axis.reversed)) { + scrollbar.setRange(from, to); + } + else { + // inverse vertical axis + scrollbar.setRange(1 - to, 1 - from); + } + } + } + }); + // Make space for a scrollbar: + addEvent(AxisClass, 'afterGetOffset', function () { + var axis = this, + index = axis.horiz ? 2 : 1, + scrollbar = axis.scrollbar; + if (scrollbar) { + axis.chart.scrollbarsOffsets = [0, 0]; // reset scrollbars offsets + axis.chart.axisOffset[index] += + scrollbar.size + scrollbar.options.margin; + } + }); + }; + return ScrollbarAxis; + }()); + + return ScrollbarAxis; + }); + _registerModule(_modules, 'Core/Scrollbar.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Globals.js'], _modules['Core/Axis/ScrollbarAxis.js'], _modules['Core/Utilities.js'], _modules['Core/Options.js']], function (Axis, H, ScrollbarAxis, U, O) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, + correctFloat = U.correctFloat, + defined = U.defined, + destroyObjectProperties = U.destroyObjectProperties, + fireEvent = U.fireEvent, + merge = U.merge, + pick = U.pick, + removeEvent = U.removeEvent; + var defaultOptions = O.defaultOptions; + var hasTouch = H.hasTouch, + isTouchDevice = H.isTouchDevice; + /** + * When we have vertical scrollbar, rifles and arrow in buttons should be + * rotated. The same method is used in Navigator's handles, to rotate them. + * + * @function Highcharts.swapXY + * + * @param {Highcharts.SVGPathArray} path + * Path to be rotated. + * + * @param {boolean} [vertical] + * If vertical scrollbar, swap x-y values. + * + * @return {Highcharts.SVGPathArray} + * Rotated path. + * + * @requires modules/stock + */ + var swapXY = H.swapXY = function (path, + vertical) { + if (vertical) { + path.forEach(function (seg) { + var len = seg.length; + var temp; + for (var i = 0; i < len; i += 2) { + temp = seg[i + 1]; + if (typeof temp === 'number') { + seg[i + 1] = seg[i + 2]; + seg[i + 2] = temp; + } + } + }); + } + return path; + }; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * A reusable scrollbar, internally used in Highstock's navigator and optionally + * on individual axes. + * + * @private + * @class + * @name Highcharts.Scrollbar + * @param {Highcharts.SVGRenderer} renderer + * @param {Highcharts.ScrollbarOptions} options + * @param {Highcharts.Chart} chart + */ + var Scrollbar = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Scrollbar(renderer, options, chart) { + /* * + * + * Properties + * + * */ + this._events = []; + this.chartX = 0; + this.chartY = 0; + this.from = 0; + this.group = void 0; + this.scrollbar = void 0; + this.scrollbarButtons = []; + this.scrollbarGroup = void 0; + this.scrollbarLeft = 0; + this.scrollbarRifles = void 0; + this.scrollbarStrokeWidth = 1; + this.scrollbarTop = 0; + this.size = 0; + this.to = 0; + this.track = void 0; + this.trackBorderWidth = 1; + this.userOptions = {}; + this.x = 0; + this.y = 0; + this.chart = chart; + this.options = options; + this.renderer = chart.renderer; + this.init(renderer, options, chart); + } + /* * + * + * Functions + * + * */ + /** + * Set up the mouse and touch events for the Scrollbar + * + * @private + * @function Highcharts.Scrollbar#addEvents + * @return {void} + */ + Scrollbar.prototype.addEvents = function () { + var buttonsOrder = this.options.inverted ? [1, 0] : [0, 1], + buttons = this.scrollbarButtons, + bar = this.scrollbarGroup.element, + track = this.track.element, + mouseDownHandler = this.mouseDownHandler.bind(this), + mouseMoveHandler = this.mouseMoveHandler.bind(this), + mouseUpHandler = this.mouseUpHandler.bind(this), + _events; + // Mouse events + _events = [ + [buttons[buttonsOrder[0]].element, 'click', this.buttonToMinClick.bind(this)], + [buttons[buttonsOrder[1]].element, 'click', this.buttonToMaxClick.bind(this)], + [track, 'click', this.trackClick.bind(this)], + [bar, 'mousedown', mouseDownHandler], + [bar.ownerDocument, 'mousemove', mouseMoveHandler], + [bar.ownerDocument, 'mouseup', mouseUpHandler] + ]; + // Touch events + if (hasTouch) { + _events.push([bar, 'touchstart', mouseDownHandler], [bar.ownerDocument, 'touchmove', mouseMoveHandler], [bar.ownerDocument, 'touchend', mouseUpHandler]); + } + // Add them all + _events.forEach(function (args) { + addEvent.apply(null, args); + }); + this._events = _events; + }; + Scrollbar.prototype.buttonToMaxClick = function (e) { + var scroller = this; + var range = (scroller.to - scroller.from) * pick(scroller.options.step, 0.2); + scroller.updatePosition(scroller.from + range, scroller.to + range); + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMEvent: e + }); + }; + Scrollbar.prototype.buttonToMinClick = function (e) { + var scroller = this; + var range = correctFloat(scroller.to - scroller.from) * + pick(scroller.options.step, 0.2); + scroller.updatePosition(correctFloat(scroller.from - range), correctFloat(scroller.to - range)); + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMEvent: e + }); + }; + /** + * Get normalized (0-1) cursor position over the scrollbar + * + * @private + * @function Highcharts.Scrollbar#cursorToScrollbarPosition + * + * @param {*} normalizedEvent + * normalized event, with chartX and chartY values + * + * @return {Highcharts.Dictionary} + * Local position {chartX, chartY} + */ + Scrollbar.prototype.cursorToScrollbarPosition = function (normalizedEvent) { + var scroller = this, + options = scroller.options, + minWidthDifference = options.minWidth > scroller.calculatedWidth ? + options.minWidth : + 0; // minWidth distorts translation + return { + chartX: (normalizedEvent.chartX - scroller.x - + scroller.xOffset) / + (scroller.barWidth - minWidthDifference), + chartY: (normalizedEvent.chartY - scroller.y - + scroller.yOffset) / + (scroller.barWidth - minWidthDifference) + }; + }; + /** + * Destroys allocated elements. + * + * @private + * @function Highcharts.Scrollbar#destroy + * @return {void} + */ + Scrollbar.prototype.destroy = function () { + var scroller = this.chart.scroller; + // Disconnect events added in addEvents + this.removeEvents(); + // Destroy properties + [ + 'track', + 'scrollbarRifles', + 'scrollbar', + 'scrollbarGroup', + 'group' + ].forEach(function (prop) { + if (this[prop] && this[prop].destroy) { + this[prop] = this[prop].destroy(); + } + }, this); + // #6421, chart may have more scrollbars + if (scroller && this === scroller.scrollbar) { + scroller.scrollbar = null; + // Destroy elements in collection + destroyObjectProperties(scroller.scrollbarButtons); + } + }; + /** + * Draw the scrollbar buttons with arrows + * + * @private + * @function Highcharts.Scrollbar#drawScrollbarButton + * @param {number} index + * 0 is left, 1 is right + * @return {void} + */ + Scrollbar.prototype.drawScrollbarButton = function (index) { + var scroller = this, + renderer = scroller.renderer, + scrollbarButtons = scroller.scrollbarButtons, + options = scroller.options, + size = scroller.size, + group, + tempElem; + group = renderer.g().add(scroller.group); + scrollbarButtons.push(group); + // Create a rectangle for the scrollbar button + tempElem = renderer.rect() + .addClass('highcharts-scrollbar-button') + .add(group); + // Presentational attributes + if (!this.chart.styledMode) { + tempElem.attr({ + stroke: options.buttonBorderColor, + 'stroke-width': options.buttonBorderWidth, + fill: options.buttonBackgroundColor + }); + } + // Place the rectangle based on the rendered stroke width + tempElem.attr(tempElem.crisp({ + x: -0.5, + y: -0.5, + width: size + 1, + height: size + 1, + r: options.buttonBorderRadius + }, tempElem.strokeWidth())); + // Button arrow + tempElem = renderer + .path(swapXY([[ + 'M', + size / 2 + (index ? -1 : 1), + size / 2 - 3 + ], [ + 'L', + size / 2 + (index ? -1 : 1), + size / 2 + 3 + ], [ + 'L', + size / 2 + (index ? 2 : -2), + size / 2 + ]], options.vertical)) + .addClass('highcharts-scrollbar-arrow') + .add(scrollbarButtons[index]); + if (!this.chart.styledMode) { + tempElem.attr({ + fill: options.buttonArrowColor + }); + } + }; + /** + * @private + * @function Highcharts.Scrollbar#init + * @param {Highcharts.SVGRenderer} renderer + * @param {Highcharts.ScrollbarOptions} options + * @param {Highcharts.Chart} chart + */ + Scrollbar.prototype.init = function (renderer, options, chart) { + this.scrollbarButtons = []; + this.renderer = renderer; + this.userOptions = options; + this.options = merge(Scrollbar.defaultOptions, options); + this.chart = chart; + // backward compatibility + this.size = pick(this.options.size, this.options.height); + // Init + if (options.enabled) { + this.render(); + this.addEvents(); + } + }; + Scrollbar.prototype.mouseDownHandler = function (e) { + var scroller = this; + var normalizedEvent = scroller.chart.pointer.normalize(e), + mousePosition = scroller.cursorToScrollbarPosition(normalizedEvent); + scroller.chartX = mousePosition.chartX; + scroller.chartY = mousePosition.chartY; + scroller.initPositions = [scroller.from, scroller.to]; + scroller.grabbedCenter = true; + }; + /** + * Event handler for the mouse move event. + * @private + */ + Scrollbar.prototype.mouseMoveHandler = function (e) { + var scroller = this; + var normalizedEvent = scroller.chart.pointer.normalize(e), + options = scroller.options, + direction = options.vertical ? 'chartY' : 'chartX', + initPositions = scroller.initPositions || [], + scrollPosition, + chartPosition, + change; + // In iOS, a mousemove event with e.pageX === 0 is fired when + // holding the finger down in the center of the scrollbar. This + // should be ignored. + if (scroller.grabbedCenter && + // #4696, scrollbar failed on Android + (!e.touches || e.touches[0][direction] !== 0)) { + chartPosition = scroller.cursorToScrollbarPosition(normalizedEvent)[direction]; + scrollPosition = scroller[direction]; + change = chartPosition - scrollPosition; + scroller.hasDragged = true; + scroller.updatePosition(initPositions[0] + change, initPositions[1] + change); + if (scroller.hasDragged) { + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMType: e.type, + DOMEvent: e + }); + } + } + }; + /** + * Event handler for the mouse up event. + * @private + */ + Scrollbar.prototype.mouseUpHandler = function (e) { + var scroller = this; + if (scroller.hasDragged) { + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMType: e.type, + DOMEvent: e + }); + } + scroller.grabbedCenter = + scroller.hasDragged = + scroller.chartX = + scroller.chartY = null; + }; + /** + * Position the scrollbar, method called from a parent with defined + * dimensions. + * + * @private + * @function Highcharts.Scrollbar#position + * @param {number} x + * x-position on the chart + * @param {number} y + * y-position on the chart + * @param {number} width + * width of the scrollbar + * @param {number} height + * height of the scorllbar + * @return {void} + */ + Scrollbar.prototype.position = function (x, y, width, height) { + var scroller = this, + options = scroller.options, + vertical = options.vertical, + xOffset = height, + yOffset = 0, + method = scroller.rendered ? 'animate' : 'attr'; + scroller.x = x; + scroller.y = y + this.trackBorderWidth; + scroller.width = width; // width with buttons + scroller.height = height; + scroller.xOffset = xOffset; + scroller.yOffset = yOffset; + // If Scrollbar is a vertical type, swap options: + if (vertical) { + scroller.width = scroller.yOffset = width = yOffset = scroller.size; + scroller.xOffset = xOffset = 0; + scroller.barWidth = height - width * 2; // width without buttons + scroller.x = x = x + scroller.options.margin; + } + else { + scroller.height = scroller.xOffset = height = xOffset = + scroller.size; + scroller.barWidth = width - height * 2; // width without buttons + scroller.y = scroller.y + scroller.options.margin; + } + // Set general position for a group: + scroller.group[method]({ + translateX: x, + translateY: scroller.y + }); + // Resize background/track: + scroller.track[method]({ + width: width, + height: height + }); + // Move right/bottom button ot it's place: + scroller.scrollbarButtons[1][method]({ + translateX: vertical ? 0 : width - xOffset, + translateY: vertical ? height - yOffset : 0 + }); + }; + /** + * Removes the event handlers attached previously with addEvents. + * + * @private + * @function Highcharts.Scrollbar#removeEvents + * @return {void} + */ + Scrollbar.prototype.removeEvents = function () { + this._events.forEach(function (args) { + removeEvent.apply(null, args); + }); + this._events.length = 0; + }; + /** + * Render scrollbar with all required items. + * + * @private + * @function Highcharts.Scrollbar#render + */ + Scrollbar.prototype.render = function () { + var scroller = this, + renderer = scroller.renderer, + options = scroller.options, + size = scroller.size, + styledMode = this.chart.styledMode, + group; + // Draw the scrollbar group + scroller.group = group = renderer.g('scrollbar').attr({ + zIndex: options.zIndex, + translateY: -99999 + }).add(); + // Draw the scrollbar track: + scroller.track = renderer.rect() + .addClass('highcharts-scrollbar-track') + .attr({ + x: 0, + r: options.trackBorderRadius || 0, + height: size, + width: size + }).add(group); + if (!styledMode) { + scroller.track.attr({ + fill: options.trackBackgroundColor, + stroke: options.trackBorderColor, + 'stroke-width': options.trackBorderWidth + }); + } + this.trackBorderWidth = scroller.track.strokeWidth(); + scroller.track.attr({ + y: -this.trackBorderWidth % 2 / 2 + }); + // Draw the scrollbar itself + scroller.scrollbarGroup = renderer.g().add(group); + scroller.scrollbar = renderer.rect() + .addClass('highcharts-scrollbar-thumb') + .attr({ + height: size, + width: size, + r: options.barBorderRadius || 0 + }).add(scroller.scrollbarGroup); + scroller.scrollbarRifles = renderer + .path(swapXY([ + ['M', -3, size / 4], + ['L', -3, 2 * size / 3], + ['M', 0, size / 4], + ['L', 0, 2 * size / 3], + ['M', 3, size / 4], + ['L', 3, 2 * size / 3] + ], options.vertical)) + .addClass('highcharts-scrollbar-rifles') + .add(scroller.scrollbarGroup); + if (!styledMode) { + scroller.scrollbar.attr({ + fill: options.barBackgroundColor, + stroke: options.barBorderColor, + 'stroke-width': options.barBorderWidth + }); + scroller.scrollbarRifles.attr({ + stroke: options.rifleColor, + 'stroke-width': 1 + }); + } + scroller.scrollbarStrokeWidth = scroller.scrollbar.strokeWidth(); + scroller.scrollbarGroup.translate(-scroller.scrollbarStrokeWidth % 2 / 2, -scroller.scrollbarStrokeWidth % 2 / 2); + // Draw the buttons: + scroller.drawScrollbarButton(0); + scroller.drawScrollbarButton(1); + }; + /** + * Set scrollbar size, with a given scale. + * + * @private + * @function Highcharts.Scrollbar#setRange + * @param {number} from + * scale (0-1) where bar should start + * @param {number} to + * scale (0-1) where bar should end + * @return {void} + */ + Scrollbar.prototype.setRange = function (from, to) { + var scroller = this, + options = scroller.options, + vertical = options.vertical, + minWidth = options.minWidth, + fullWidth = scroller.barWidth, + fromPX, + toPX, + newPos, + newSize, + newRiflesPos, + method = (this.rendered && + !this.hasDragged && + !(this.chart.navigator && this.chart.navigator.hasDragged)) ? 'animate' : 'attr'; + if (!defined(fullWidth)) { + return; + } + from = Math.max(from, 0); + fromPX = Math.ceil(fullWidth * from); + toPX = fullWidth * Math.min(to, 1); + scroller.calculatedWidth = newSize = correctFloat(toPX - fromPX); + // We need to recalculate position, if minWidth is used + if (newSize < minWidth) { + fromPX = (fullWidth - minWidth + newSize) * from; + newSize = minWidth; + } + newPos = Math.floor(fromPX + scroller.xOffset + scroller.yOffset); + newRiflesPos = newSize / 2 - 0.5; // -0.5 -> rifle line width / 2 + // Store current position: + scroller.from = from; + scroller.to = to; + if (!vertical) { + scroller.scrollbarGroup[method]({ + translateX: newPos + }); + scroller.scrollbar[method]({ + width: newSize + }); + scroller.scrollbarRifles[method]({ + translateX: newRiflesPos + }); + scroller.scrollbarLeft = newPos; + scroller.scrollbarTop = 0; + } + else { + scroller.scrollbarGroup[method]({ + translateY: newPos + }); + scroller.scrollbar[method]({ + height: newSize + }); + scroller.scrollbarRifles[method]({ + translateY: newRiflesPos + }); + scroller.scrollbarTop = newPos; + scroller.scrollbarLeft = 0; + } + if (newSize <= 12) { + scroller.scrollbarRifles.hide(); + } + else { + scroller.scrollbarRifles.show(true); + } + // Show or hide the scrollbar based on the showFull setting + if (options.showFull === false) { + if (from <= 0 && to >= 1) { + scroller.group.hide(); + } + else { + scroller.group.show(); + } + } + scroller.rendered = true; + }; + Scrollbar.prototype.trackClick = function (e) { + var scroller = this; + var normalizedEvent = scroller.chart.pointer.normalize(e), + range = scroller.to - scroller.from, + top = scroller.y + scroller.scrollbarTop, + left = scroller.x + scroller.scrollbarLeft; + if ((scroller.options.vertical && normalizedEvent.chartY > top) || + (!scroller.options.vertical && normalizedEvent.chartX > left)) { + // On the top or on the left side of the track: + scroller.updatePosition(scroller.from + range, scroller.to + range); + } + else { + // On the bottom or the right side of the track: + scroller.updatePosition(scroller.from - range, scroller.to - range); + } + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMEvent: e + }); + }; + /** + * Update the scrollbar with new options + * + * @private + * @function Highcharts.Scrollbar#update + * @param {Highcharts.ScrollbarOptions} options + * @return {void} + */ + Scrollbar.prototype.update = function (options) { + this.destroy(); + this.init(this.chart.renderer, merge(true, this.options, options), this.chart); + }; + /** + * Update position option in the Scrollbar, with normalized 0-1 scale + * + * @private + * @function Highcharts.Scrollbar#updatePosition + * @param {number} from + * @param {number} to + * @return {void} + */ + Scrollbar.prototype.updatePosition = function (from, to) { + if (to > 1) { + from = correctFloat(1 - correctFloat(to - from)); + to = 1; + } + if (from < 0) { + to = correctFloat(to - from); + from = 0; + } + this.from = from; + this.to = to; + }; + /* * + * + * Static Properties + * + * */ + /** + * + * The scrollbar is a means of panning over the X axis of a stock chart. + * Scrollbars can also be applied to other types of axes. + * + * Another approach to scrollable charts is the [chart.scrollablePlotArea]( + * https://api.highcharts.com/highcharts/chart.scrollablePlotArea) option that + * is especially suitable for simpler cartesian charts on mobile. + * + * In styled mode, all the presentational options for the + * scrollbar are replaced by the classes `.highcharts-scrollbar-thumb`, + * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`, + * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`. + * + * @sample stock/yaxis/inverted-bar-scrollbar/ + * A scrollbar on a simple bar chart + * + * @product highstock gantt + * @optionparent scrollbar + * + * @private + */ + Scrollbar.defaultOptions = { + /** + * The height of the scrollbar. The height also applies to the width + * of the scroll arrows so that they are always squares. Defaults to + * 20 for touch devices and 14 for mouse devices. + * + * @sample stock/scrollbar/height/ + * A 30px scrollbar + * + * @type {number} + * @default 20/14 + */ + height: isTouchDevice ? 20 : 14, + /** + * The border rounding radius of the bar. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + barBorderRadius: 0, + /** + * The corner radius of the scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + buttonBorderRadius: 0, + /** + * Enable or disable the scrollbar. + * + * @sample stock/scrollbar/enabled/ + * Disable the scrollbar, only use navigator + * + * @type {boolean} + * @default true + * @apioption scrollbar.enabled + */ + /** + * Whether to redraw the main chart as the scrollbar or the navigator + * zoomed window is moved. Defaults to `true` for modern browsers and + * `false` for legacy IE browsers as well as mobile devices. + * + * @sample stock/scrollbar/liveredraw + * Setting live redraw to false + * + * @type {boolean} + * @since 1.3 + */ + liveRedraw: void 0, + /** + * The margin between the scrollbar and its axis when the scrollbar is + * applied directly to an axis. + */ + margin: 10, + /** + * The minimum width of the scrollbar. + * + * @since 1.2.5 + */ + minWidth: 6, + /** + * Whether to show or hide the scrollbar when the scrolled content is + * zoomed out to it full extent. + * + * @type {boolean} + * @default true + * @apioption scrollbar.showFull + */ + step: 0.2, + /** + * The z index of the scrollbar group. + */ + zIndex: 3, + /** + * The background color of the scrollbar itself. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + barBackgroundColor: '#cccccc', + /** + * The width of the bar's border. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + barBorderWidth: 1, + /** + * The color of the scrollbar's border. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + barBorderColor: '#cccccc', + /** + * The color of the small arrow inside the scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + buttonArrowColor: '#333333', + /** + * The color of scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + buttonBackgroundColor: '#e6e6e6', + /** + * The color of the border of the scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + buttonBorderColor: '#cccccc', + /** + * The border width of the scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + buttonBorderWidth: 1, + /** + * The color of the small rifles in the middle of the scrollbar. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + rifleColor: '#333333', + /** + * The color of the track background. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + trackBackgroundColor: '#f2f2f2', + /** + * The color of the border of the scrollbar track. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + trackBorderColor: '#f2f2f2', + /** + * The corner radius of the border of the scrollbar track. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {number} + * @default 0 + * @apioption scrollbar.trackBorderRadius + */ + /** + * The width of the border of the scrollbar track. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + trackBorderWidth: 1 + }; + return Scrollbar; + }()); + if (!H.Scrollbar) { + defaultOptions.scrollbar = merge(true, Scrollbar.defaultOptions, defaultOptions.scrollbar); + H.Scrollbar = Scrollbar; + ScrollbarAxis.compose(Axis, Scrollbar); + } + + return H.Scrollbar; + }); + _registerModule(_modules, 'Extensions/RangeSelector.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Chart/Chart.js'], _modules['Core/Globals.js'], _modules['Core/Options.js'], _modules['Core/Renderer/SVG/SVGElement.js'], _modules['Core/Utilities.js']], function (Axis, Chart, H, O, SVGElement, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var defaultOptions = O.defaultOptions; + var addEvent = U.addEvent, + createElement = U.createElement, + css = U.css, + defined = U.defined, + destroyObjectProperties = U.destroyObjectProperties, + discardElement = U.discardElement, + extend = U.extend, + fireEvent = U.fireEvent, + isNumber = U.isNumber, + merge = U.merge, + objectEach = U.objectEach, + pick = U.pick, + pInt = U.pInt, + splat = U.splat; + /** + * Define the time span for the button + * + * @typedef {"all"|"day"|"hour"|"millisecond"|"minute"|"month"|"second"|"week"|"year"|"ytd"} Highcharts.RangeSelectorButtonTypeValue + */ + /** + * Callback function to react on button clicks. + * + * @callback Highcharts.RangeSelectorClickCallbackFunction + * + * @param {global.Event} e + * Event arguments. + * + * @param {boolean|undefined} + * Return false to cancel the default button event. + */ + /** + * Callback function to parse values entered in the input boxes and return a + * valid JavaScript time as milliseconds since 1970. + * + * @callback Highcharts.RangeSelectorParseCallbackFunction + * + * @param {string} value + * Input value to parse. + * + * @return {number} + * Parsed JavaScript time value. + */ + /* ************************************************************************** * + * Start Range Selector code * + * ************************************************************************** */ + extend(defaultOptions, { + /** + * The range selector is a tool for selecting ranges to display within + * the chart. It provides buttons to select preconfigured ranges in + * the chart, like 1 day, 1 week, 1 month etc. It also provides input + * boxes where min and max dates can be manually input. + * + * @product highstock gantt + * @optionparent rangeSelector + */ + rangeSelector: { + /** + * Whether to enable all buttons from the start. By default buttons are + * only enabled if the corresponding time range exists on the X axis, + * but enabling all buttons allows for dynamically loading different + * time ranges. + * + * @sample {highstock} stock/rangeselector/allbuttonsenabled-true/ + * All buttons enabled + * + * @type {boolean} + * @default false + * @since 2.0.3 + * @apioption rangeSelector.allButtonsEnabled + */ + /** + * An array of configuration objects for the buttons. + * + * Defaults to: + * ```js + * buttons: [{ + * type: 'month', + * count: 1, + * text: '1m' + * }, { + * type: 'month', + * count: 3, + * text: '3m' + * }, { + * type: 'month', + * count: 6, + * text: '6m' + * }, { + * type: 'ytd', + * text: 'YTD' + * }, { + * type: 'year', + * count: 1, + * text: '1y' + * }, { + * type: 'all', + * text: 'All' + * }] + * ``` + * + * @sample {highstock} stock/rangeselector/datagrouping/ + * Data grouping by buttons + * + * @type {Array<*>} + * @apioption rangeSelector.buttons + */ + /** + * How many units of the defined type the button should span. If `type` + * is "month" and `count` is 3, the button spans three months. + * + * @type {number} + * @default 1 + * @apioption rangeSelector.buttons.count + */ + /** + * Fires when clicking on the rangeSelector button. One parameter, + * event, is passed to the function, containing common event + * information. + * + * ```js + * click: function(e) { + * console.log(this); + * } + * ``` + * + * Return false to stop default button's click action. + * + * @sample {highstock} stock/rangeselector/button-click/ + * Click event on the button + * + * @type {Highcharts.RangeSelectorClickCallbackFunction} + * @apioption rangeSelector.buttons.events.click + */ + /** + * Additional range (in milliseconds) added to the end of the calculated + * time span. + * + * @sample {highstock} stock/rangeselector/min-max-offsets/ + * Button offsets + * + * @type {number} + * @default 0 + * @since 6.0.0 + * @apioption rangeSelector.buttons.offsetMax + */ + /** + * Additional range (in milliseconds) added to the start of the + * calculated time span. + * + * @sample {highstock} stock/rangeselector/min-max-offsets/ + * Button offsets + * + * @type {number} + * @default 0 + * @since 6.0.0 + * @apioption rangeSelector.buttons.offsetMin + */ + /** + * When buttons apply dataGrouping on a series, by default zooming + * in/out will deselect buttons and unset dataGrouping. Enable this + * option to keep buttons selected when extremes change. + * + * @sample {highstock} stock/rangeselector/preserve-datagrouping/ + * Different preserveDataGrouping settings + * + * @type {boolean} + * @default false + * @since 6.1.2 + * @apioption rangeSelector.buttons.preserveDataGrouping + */ + /** + * A custom data grouping object for each button. + * + * @see [series.dataGrouping](#plotOptions.series.dataGrouping) + * + * @sample {highstock} stock/rangeselector/datagrouping/ + * Data grouping by range selector buttons + * + * @type {*} + * @extends plotOptions.series.dataGrouping + * @apioption rangeSelector.buttons.dataGrouping + */ + /** + * The text for the button itself. + * + * @type {string} + * @apioption rangeSelector.buttons.text + */ + /** + * Defined the time span for the button. Can be one of `millisecond`, + * `second`, `minute`, `hour`, `day`, `week`, `month`, `year`, `ytd`, + * and `all`. + * + * @type {Highcharts.RangeSelectorButtonTypeValue} + * @apioption rangeSelector.buttons.type + */ + /** + * The space in pixels between the buttons in the range selector. + * + * @type {number} + * @default 0 + * @apioption rangeSelector.buttonSpacing + */ + /** + * Enable or disable the range selector. + * + * @sample {highstock} stock/rangeselector/enabled/ + * Disable the range selector + * + * @type {boolean} + * @default true + * @apioption rangeSelector.enabled + */ + /** + * The vertical alignment of the rangeselector box. Allowed properties + * are `top`, `middle`, `bottom`. + * + * @sample {highstock} stock/rangeselector/vertical-align-middle/ + * Middle + * @sample {highstock} stock/rangeselector/vertical-align-bottom/ + * Bottom + * + * @type {Highcharts.VerticalAlignValue} + * @since 6.0.0 + */ + verticalAlign: 'top', + /** + * A collection of attributes for the buttons. The object takes SVG + * attributes like `fill`, `stroke`, `stroke-width`, as well as `style`, + * a collection of CSS properties for the text. + * + * The object can also be extended with states, so you can set + * presentational options for `hover`, `select` or `disabled` button + * states. + * + * CSS styles for the text label. + * + * In styled mode, the buttons are styled by the + * `.highcharts-range-selector-buttons .highcharts-button` rule with its + * different states. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {Highcharts.SVGAttributes} + */ + buttonTheme: { + /** @ignore */ + width: 28, + /** @ignore */ + height: 18, + /** @ignore */ + padding: 2, + /** @ignore */ + zIndex: 7 // #484, #852 + }, + /** + * When the rangeselector is floating, the plot area does not reserve + * space for it. This opens for positioning anywhere on the chart. + * + * @sample {highstock} stock/rangeselector/floating/ + * Placing the range selector between the plot area and the + * navigator + * + * @since 6.0.0 + */ + floating: false, + /** + * The x offset of the range selector relative to its horizontal + * alignment within `chart.spacingLeft` and `chart.spacingRight`. + * + * @since 6.0.0 + */ + x: 0, + /** + * The y offset of the range selector relative to its horizontal + * alignment within `chart.spacingLeft` and `chart.spacingRight`. + * + * @since 6.0.0 + */ + y: 0, + /** + * Deprecated. The height of the range selector. Currently it is + * calculated dynamically. + * + * @deprecated + * @type {number|undefined} + * @since 2.1.9 + */ + height: void 0, + /** + * The border color of the date input boxes. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {Highcharts.ColorString} + * @default #cccccc + * @since 1.3.7 + * @apioption rangeSelector.inputBoxBorderColor + */ + /** + * The pixel height of the date input boxes. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {number} + * @default 17 + * @since 1.3.7 + * @apioption rangeSelector.inputBoxHeight + */ + /** + * CSS for the container DIV holding the input boxes. Deprecated as + * of 1.2.5\. Use [inputPosition](#rangeSelector.inputPosition) instead. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @deprecated + * @type {Highcharts.CSSObject} + * @apioption rangeSelector.inputBoxStyle + */ + /** + * The pixel width of the date input boxes. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {number} + * @default 90 + * @since 1.3.7 + * @apioption rangeSelector.inputBoxWidth + */ + /** + * The date format in the input boxes when not selected for editing. + * Defaults to `%b %e, %Y`. + * + * @sample {highstock} stock/rangeselector/input-format/ + * Milliseconds in the range selector + * + * @type {string} + * @default %b %e, %Y + * @apioption rangeSelector.inputDateFormat + */ + /** + * A custom callback function to parse values entered in the input boxes + * and return a valid JavaScript time as milliseconds since 1970. + * The first argument passed is a value to parse, + * second is a boolean indicating use of the UTC time. + * + * @sample {highstock} stock/rangeselector/input-format/ + * Milliseconds in the range selector + * + * @type {Highcharts.RangeSelectorParseCallbackFunction} + * @since 1.3.3 + * @apioption rangeSelector.inputDateParser + */ + /** + * The date format in the input boxes when they are selected for + * editing. This must be a format that is recognized by JavaScript + * Date.parse. + * + * @sample {highstock} stock/rangeselector/input-format/ + * Milliseconds in the range selector + * + * @type {string} + * @default %Y-%m-%d + * @apioption rangeSelector.inputEditDateFormat + */ + /** + * Enable or disable the date input boxes. Defaults to enabled when + * there is enough space, disabled if not (typically mobile). + * + * @sample {highstock} stock/rangeselector/input-datepicker/ + * Extending the input with a jQuery UI datepicker + * + * @type {boolean} + * @default true + * @apioption rangeSelector.inputEnabled + */ + /** + * Positioning for the input boxes. Allowed properties are `align`, + * `x` and `y`. + * + * @since 1.2.4 + */ + inputPosition: { + /** + * The alignment of the input box. Allowed properties are `left`, + * `center`, `right`. + * + * @sample {highstock} stock/rangeselector/input-button-position/ + * Alignment + * + * @type {Highcharts.AlignValue} + * @since 6.0.0 + */ + align: 'right', + /** + * X offset of the input row. + */ + x: 0, + /** + * Y offset of the input row. + */ + y: 0 + }, + /** + * The index of the button to appear pre-selected. + * + * @type {number} + * @apioption rangeSelector.selected + */ + /** + * Positioning for the button row. + * + * @since 1.2.4 + */ + buttonPosition: { + /** + * The alignment of the input box. Allowed properties are `left`, + * `center`, `right`. + * + * @sample {highstock} stock/rangeselector/input-button-position/ + * Alignment + * + * @type {Highcharts.AlignValue} + * @since 6.0.0 + */ + align: 'left', + /** + * X offset of the button row. + */ + x: 0, + /** + * Y offset of the button row. + */ + y: 0 + }, + /** + * CSS for the HTML inputs in the range selector. + * + * In styled mode, the inputs are styled by the + * `.highcharts-range-input text` rule in SVG mode, and + * `input.highcharts-range-selector` when active. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {Highcharts.CSSObject} + * @apioption rangeSelector.inputStyle + */ + /** + * CSS styles for the labels - the Zoom, From and To texts. + * + * In styled mode, the labels are styled by the + * `.highcharts-range-label` class. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {Highcharts.CSSObject} + */ + labelStyle: { + /** @ignore */ + color: '#666666' + } + } + }); + defaultOptions.lang = merge(defaultOptions.lang, + /** + * Language object. The language object is global and it can't be set + * on each chart initialization. Instead, use `Highcharts.setOptions` to + * set it before any chart is initialized. + * + * ```js + * Highcharts.setOptions({ + * lang: { + * months: [ + * 'Janvier', 'Février', 'Mars', 'Avril', + * 'Mai', 'Juin', 'Juillet', 'Août', + * 'Septembre', 'Octobre', 'Novembre', 'Décembre' + * ], + * weekdays: [ + * 'Dimanche', 'Lundi', 'Mardi', 'Mercredi', + * 'Jeudi', 'Vendredi', 'Samedi' + * ] + * } + * }); + * ``` + * + * @optionparent lang + */ + { + /** + * The text for the label for the range selector buttons. + * + * @product highstock gantt + */ + rangeSelectorZoom: 'Zoom', + /** + * The text for the label for the "from" input box in the range + * selector. + * + * @product highstock gantt + */ + rangeSelectorFrom: 'From', + /** + * The text for the label for the "to" input box in the range selector. + * + * @product highstock gantt + */ + rangeSelectorTo: 'To' + }); + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The range selector. + * + * @private + * @class + * @name Highcharts.RangeSelector + * @param {Highcharts.Chart} chart + */ + var RangeSelector = /** @class */ (function () { + function RangeSelector(chart) { + /* * + * + * Properties + * + * */ + this.buttons = void 0; + this.buttonOptions = RangeSelector.prototype.defaultButtons; + this.options = void 0; + this.chart = chart; + // Run RangeSelector + this.init(chart); + } + /** + * The method to run when one of the buttons in the range selectors is + * clicked + * + * @private + * @function Highcharts.RangeSelector#clickButton + * @param {number} i + * The index of the button + * @param {boolean} [redraw] + * @return {void} + */ + RangeSelector.prototype.clickButton = function (i, redraw) { + var rangeSelector = this, + chart = rangeSelector.chart, + rangeOptions = rangeSelector.buttonOptions[i], + baseAxis = chart.xAxis[0], + unionExtremes = (chart.scroller && chart.scroller.getUnionExtremes()) || baseAxis || {}, + dataMin = unionExtremes.dataMin, + dataMax = unionExtremes.dataMax, + newMin, + newMax = baseAxis && Math.round(Math.min(baseAxis.max, + pick(dataMax, + baseAxis.max))), // #1568 + type = rangeOptions.type, + baseXAxisOptions, + range = rangeOptions._range, + rangeMin, + minSetting, + rangeSetting, + ctx, + ytdExtremes, + dataGrouping = rangeOptions.dataGrouping; + // chart has no data, base series is removed + if (dataMin === null || dataMax === null) { + return; + } + // Set the fixed range before range is altered + chart.fixedRange = range; + // Apply dataGrouping associated to button + if (dataGrouping) { + this.forcedDataGrouping = true; + Axis.prototype.setDataGrouping.call(baseAxis || { chart: this.chart }, dataGrouping, false); + this.frozenStates = rangeOptions.preserveDataGrouping; + } + // Apply range + if (type === 'month' || type === 'year') { + if (!baseAxis) { + // This is set to the user options and picked up later when the + // axis is instantiated so that we know the min and max. + range = rangeOptions; + } + else { + ctx = { + range: rangeOptions, + max: newMax, + chart: chart, + dataMin: dataMin, + dataMax: dataMax + }; + newMin = baseAxis.minFromRange.call(ctx); + if (isNumber(ctx.newMax)) { + newMax = ctx.newMax; + } + } + // Fixed times like minutes, hours, days + } + else if (range) { + newMin = Math.max(newMax - range, dataMin); + newMax = Math.min(newMin + range, dataMax); + } + else if (type === 'ytd') { + // On user clicks on the buttons, or a delayed action running from + // the beforeRender event (below), the baseAxis is defined. + if (baseAxis) { + // When "ytd" is the pre-selected button for the initial view, + // its calculation is delayed and rerun in the beforeRender + // event (below). When the series are initialized, but before + // the chart is rendered, we have access to the xData array + // (#942). + if (typeof dataMax === 'undefined') { + dataMin = Number.MAX_VALUE; + dataMax = Number.MIN_VALUE; + chart.series.forEach(function (series) { + // reassign it to the last item + var xData = series.xData; + dataMin = Math.min(xData[0], dataMin); + dataMax = Math.max(xData[xData.length - 1], dataMax); + }); + redraw = false; + } + ytdExtremes = rangeSelector.getYTDExtremes(dataMax, dataMin, chart.time.useUTC); + newMin = rangeMin = ytdExtremes.min; + newMax = ytdExtremes.max; + // "ytd" is pre-selected. We don't yet have access to processed + // point and extremes data (things like pointStart and pointInterval + // are missing), so we delay the process (#942) + } + else { + rangeSelector.deferredYTDClick = i; + return; + } + } + else if (type === 'all' && baseAxis) { + newMin = dataMin; + newMax = dataMax; + } + if (defined(newMin)) { + newMin += rangeOptions._offsetMin; + } + if (defined(newMax)) { + newMax += rangeOptions._offsetMax; + } + rangeSelector.setSelected(i); + // Update the chart + if (!baseAxis) { + // Axis not yet instanciated. Temporarily set min and range + // options and remove them on chart load (#4317). + baseXAxisOptions = splat(chart.options.xAxis)[0]; + rangeSetting = baseXAxisOptions.range; + baseXAxisOptions.range = range; + minSetting = baseXAxisOptions.min; + baseXAxisOptions.min = rangeMin; + addEvent(chart, 'load', function resetMinAndRange() { + baseXAxisOptions.range = rangeSetting; + baseXAxisOptions.min = minSetting; + }); + } + else { + // Existing axis object. Set extremes after render time. + baseAxis.setExtremes(newMin, newMax, pick(redraw, 1), null, // auto animation + { + trigger: 'rangeSelectorButton', + rangeSelectorButton: rangeOptions + }); + } + }; + /** + * Set the selected option. This method only sets the internal flag, it + * doesn't update the buttons or the actual zoomed range. + * + * @private + * @function Highcharts.RangeSelector#setSelected + * @param {number} [selected] + * @return {void} + */ + RangeSelector.prototype.setSelected = function (selected) { + this.selected = this.options.selected = selected; + }; + /** + * Initialize the range selector + * + * @private + * @function Highcharts.RangeSelector#init + * @param {Highcharts.Chart} chart + * @return {void} + */ + RangeSelector.prototype.init = function (chart) { + var rangeSelector = this, + options = chart.options.rangeSelector, + buttonOptions = options.buttons || rangeSelector.defaultButtons.slice(), + selectedOption = options.selected, + blurInputs = function () { + var minInput = rangeSelector.minInput, + maxInput = rangeSelector.maxInput; + // #3274 in some case blur is not defined + if (minInput && minInput.blur) { + fireEvent(minInput, 'blur'); + } + if (maxInput && maxInput.blur) { + fireEvent(maxInput, 'blur'); + } + }; + rangeSelector.chart = chart; + rangeSelector.options = options; + rangeSelector.buttons = []; + rangeSelector.buttonOptions = buttonOptions; + this.unMouseDown = addEvent(chart.container, 'mousedown', blurInputs); + this.unResize = addEvent(chart, 'resize', blurInputs); + // Extend the buttonOptions with actual range + buttonOptions.forEach(rangeSelector.computeButtonRange); + // zoomed range based on a pre-selected button index + if (typeof selectedOption !== 'undefined' && + buttonOptions[selectedOption]) { + this.clickButton(selectedOption, false); + } + addEvent(chart, 'load', function () { + // If a data grouping is applied to the current button, release it + // when extremes change + if (chart.xAxis && chart.xAxis[0]) { + addEvent(chart.xAxis[0], 'setExtremes', function (e) { + if (this.max - this.min !== + chart.fixedRange && + e.trigger !== 'rangeSelectorButton' && + e.trigger !== 'updatedData' && + rangeSelector.forcedDataGrouping && + !rangeSelector.frozenStates) { + this.setDataGrouping(false, false); + } + }); + } + }); + }; + /** + * Dynamically update the range selector buttons after a new range has been + * set + * + * @private + * @function Highcharts.RangeSelector#updateButtonStates + * @return {void} + */ + RangeSelector.prototype.updateButtonStates = function () { + var rangeSelector = this, + chart = this.chart, + baseAxis = chart.xAxis[0], + actualRange = Math.round(baseAxis.max - baseAxis.min), + hasNoData = !baseAxis.hasVisibleSeries, + day = 24 * 36e5, // A single day in milliseconds + unionExtremes = (chart.scroller && + chart.scroller.getUnionExtremes()) || baseAxis, + dataMin = unionExtremes.dataMin, + dataMax = unionExtremes.dataMax, + ytdExtremes = rangeSelector.getYTDExtremes(dataMax, + dataMin, + chart.time.useUTC), + ytdMin = ytdExtremes.min, + ytdMax = ytdExtremes.max, + selected = rangeSelector.selected, + selectedExists = isNumber(selected), + allButtonsEnabled = rangeSelector.options.allButtonsEnabled, + buttons = rangeSelector.buttons; + rangeSelector.buttonOptions.forEach(function (rangeOptions, i) { + var range = rangeOptions._range, + type = rangeOptions.type, + count = rangeOptions.count || 1, + button = buttons[i], + state = 0, + disable, + select, + offsetRange = rangeOptions._offsetMax - + rangeOptions._offsetMin, + isSelected = i === selected, + // Disable buttons where the range exceeds what is allowed in + // the current view + isTooGreatRange = range > + dataMax - dataMin, + // Disable buttons where the range is smaller than the minimum + // range + isTooSmallRange = range < baseAxis.minRange, + // Do not select the YTD button if not explicitly told so + isYTDButNotSelected = false, + // Disable the All button if we're already showing all + isAllButAlreadyShowingAll = false, + isSameRange = range === actualRange; + // Months and years have a variable range so we check the extremes + if ((type === 'month' || type === 'year') && + (actualRange + 36e5 >= + { month: 28, year: 365 }[type] * day * count - offsetRange) && + (actualRange - 36e5 <= + { month: 31, year: 366 }[type] * day * count + offsetRange)) { + isSameRange = true; + } + else if (type === 'ytd') { + isSameRange = (ytdMax - ytdMin + offsetRange) === actualRange; + isYTDButNotSelected = !isSelected; + } + else if (type === 'all') { + isSameRange = (baseAxis.max - baseAxis.min >= + dataMax - dataMin); + isAllButAlreadyShowingAll = (!isSelected && + selectedExists && + isSameRange); + } + // The new zoom area happens to match the range for a button - mark + // it selected. This happens when scrolling across an ordinal gap. + // It can be seen in the intraday demos when selecting 1h and scroll + // across the night gap. + disable = (!allButtonsEnabled && + (isTooGreatRange || + isTooSmallRange || + isAllButAlreadyShowingAll || + hasNoData)); + select = ((isSelected && isSameRange) || + (isSameRange && !selectedExists && !isYTDButNotSelected) || + (isSelected && rangeSelector.frozenStates)); + if (disable) { + state = 3; + } + else if (select) { + selectedExists = true; // Only one button can be selected + state = 2; + } + // If state has changed, update the button + if (button.state !== state) { + button.setState(state); + // Reset (#9209) + if (state === 0 && selected === i) { + rangeSelector.setSelected(null); + } + } + }); + }; + /** + * Compute and cache the range for an individual button + * + * @private + * @function Highcharts.RangeSelector#computeButtonRange + * @param {Highcharts.RangeSelectorButtonsOptions} rangeOptions + * @return {void} + */ + RangeSelector.prototype.computeButtonRange = function (rangeOptions) { + var type = rangeOptions.type, + count = rangeOptions.count || 1, + // these time intervals have a fixed number of milliseconds, as + // opposed to month, ytd and year + fixedTimes = { + millisecond: 1, + second: 1000, + minute: 60 * 1000, + hour: 3600 * 1000, + day: 24 * 3600 * 1000, + week: 7 * 24 * 3600 * 1000 + }; + // Store the range on the button object + if (fixedTimes[type]) { + rangeOptions._range = fixedTimes[type] * count; + } + else if (type === 'month' || type === 'year') { + rangeOptions._range = { + month: 30, + year: 365 + }[type] * 24 * 36e5 * count; + } + rangeOptions._offsetMin = pick(rangeOptions.offsetMin, 0); + rangeOptions._offsetMax = pick(rangeOptions.offsetMax, 0); + rangeOptions._range += + rangeOptions._offsetMax - rangeOptions._offsetMin; + }; + /** + * Set the internal and displayed value of a HTML input for the dates + * + * @private + * @function Highcharts.RangeSelector#setInputValue + * @param {string} name + * @param {number} [inputTime] + * @return {void} + */ + RangeSelector.prototype.setInputValue = function (name, inputTime) { + var options = this.chart.options.rangeSelector, + time = this.chart.time, + input = this[name + 'Input']; + if (defined(inputTime)) { + input.previousValue = input.HCTime; + input.HCTime = inputTime; + } + input.value = time.dateFormat(options.inputEditDateFormat || '%Y-%m-%d', input.HCTime); + this[name + 'DateBox'].attr({ + text: time.dateFormat(options.inputDateFormat || '%b %e, %Y', input.HCTime) + }); + }; + /** + * @private + * @function Highcharts.RangeSelector#showInput + * @param {string} name + * @return {void} + */ + RangeSelector.prototype.showInput = function (name) { + var inputGroup = this.inputGroup, + dateBox = this[name + 'DateBox']; + css(this[name + 'Input'], { + left: (inputGroup.translateX + dateBox.x) + 'px', + top: inputGroup.translateY + 'px', + width: (dateBox.width - 2) + 'px', + height: (dateBox.height - 2) + 'px', + border: '2px solid silver' + }); + }; + /** + * @private + * @function Highcharts.RangeSelector#hideInput + * @param {string} name + * @return {void} + */ + RangeSelector.prototype.hideInput = function (name) { + css(this[name + 'Input'], { + border: 0, + width: '1px', + height: '1px' + }); + this.setInputValue(name); + }; + /** + * @private + * @function Highcharts.RangeSelector#defaultInputDateParser + */ + RangeSelector.prototype.defaultInputDateParser = function (inputDate, useUTC) { + var date = new Date(); + if (H.isSafari) { + return Date.parse(inputDate.split(' ').join('T')); + } + if (useUTC) { + return Date.parse(inputDate + 'Z'); + } + return Date.parse(inputDate) - date.getTimezoneOffset() * 60 * 1000; + }; + /** + * Draw either the 'from' or the 'to' HTML input box of the range selector + * + * @private + * @function Highcharts.RangeSelector#drawInput + * @param {string} name + * @return {void} + */ + RangeSelector.prototype.drawInput = function (name) { + var rangeSelector = this, + chart = rangeSelector.chart, + chartStyle = chart.renderer.style || {}, + renderer = chart.renderer, + options = chart.options.rangeSelector, + lang = defaultOptions.lang, + div = rangeSelector.div, + isMin = name === 'min', + input, + label, + dateBox, + inputGroup = this.inputGroup, + defaultInputDateParser = this.defaultInputDateParser; + /** + * @private + */ + function updateExtremes() { + var inputValue = input.value, + value, + chartAxis = chart.xAxis[0], + dataAxis = chart.scroller && chart.scroller.xAxis ? + chart.scroller.xAxis : + chartAxis, + dataMin = dataAxis.dataMin, + dataMax = dataAxis.dataMax; + value = (options.inputDateParser || defaultInputDateParser)(inputValue, chart.time.useUTC); + if (value !== input.previousValue) { + input.previousValue = value; + // If the value isn't parsed directly to a value by the + // browser's Date.parse method, like YYYY-MM-DD in IE, try + // parsing it a different way + if (!isNumber(value)) { + value = inputValue.split('-'); + value = Date.UTC(pInt(value[0]), pInt(value[1]) - 1, pInt(value[2])); + } + if (isNumber(value)) { + // Correct for timezone offset (#433) + if (!chart.time.useUTC) { + value = + value + new Date().getTimezoneOffset() * 60 * 1000; + } + // Validate the extremes. If it goes beyound the data min or + // max, use the actual data extreme (#2438). + if (isMin) { + if (value > rangeSelector.maxInput.HCTime) { + value = void 0; + } + else if (value < dataMin) { + value = dataMin; + } + } + else { + if (value < rangeSelector.minInput.HCTime) { + value = void 0; + } + else if (value > dataMax) { + value = dataMax; + } + } + // Set the extremes + if (typeof value !== 'undefined') { // @todo typof undefined + chartAxis.setExtremes(isMin ? value : chartAxis.min, isMin ? chartAxis.max : value, void 0, void 0, { trigger: 'rangeSelectorInput' }); + } + } + } + } + // Create the text label + this[name + 'Label'] = label = renderer + .label(lang[isMin ? 'rangeSelectorFrom' : 'rangeSelectorTo'], this.inputGroup.offset) + .addClass('highcharts-range-label') + .attr({ + padding: 2 + }) + .add(inputGroup); + inputGroup.offset += label.width + 5; + // Create an SVG label that shows updated date ranges and and records + // click events that bring in the HTML input. + this[name + 'DateBox'] = dateBox = renderer + .label('', inputGroup.offset) + .addClass('highcharts-range-input') + .attr({ + padding: 2, + width: options.inputBoxWidth || 90, + height: options.inputBoxHeight || 17, + 'text-align': 'center' + }) + .on('click', function () { + // If it is already focused, the onfocus event doesn't fire + // (#3713) + rangeSelector.showInput(name); + rangeSelector[name + 'Input'].focus(); + }); + if (!chart.styledMode) { + dateBox.attr({ + stroke: options.inputBoxBorderColor || '#cccccc', + 'stroke-width': 1 + }); + } + dateBox.add(inputGroup); + inputGroup.offset += dateBox.width + (isMin ? 10 : 0); + // Create the HTML input element. This is rendered as 1x1 pixel then set + // to the right size when focused. + this[name + 'Input'] = input = createElement('input', { + name: name, + className: 'highcharts-range-selector', + type: 'text' + }, { + top: chart.plotTop + 'px' // prevent jump on focus in Firefox + }, div); + if (!chart.styledMode) { + // Styles + label.css(merge(chartStyle, options.labelStyle)); + dateBox.css(merge({ + color: '#333333' + }, chartStyle, options.inputStyle)); + css(input, extend({ + position: 'absolute', + border: 0, + width: '1px', + height: '1px', + padding: 0, + textAlign: 'center', + fontSize: chartStyle.fontSize, + fontFamily: chartStyle.fontFamily, + top: '-9999em' // #4798 + }, options.inputStyle)); + } + // Blow up the input box + input.onfocus = function () { + rangeSelector.showInput(name); + }; + // Hide away the input box + input.onblur = function () { + // update extermes only when inputs are active + if (input === H.doc.activeElement) { // Only when focused + // Update also when no `change` event is triggered, like when + // clicking inside the SVG (#4710) + updateExtremes(); + } + // #10404 - move hide and blur outside focus + rangeSelector.hideInput(name); + input.blur(); // #4606 + }; + // handle changes in the input boxes + input.onchange = updateExtremes; + input.onkeypress = function (event) { + // IE does not fire onchange on enter + if (event.keyCode === 13) { + updateExtremes(); + } + }; + }; + /** + * Get the position of the range selector buttons and inputs. This can be + * overridden from outside for custom positioning. + * + * @private + * @function Highcharts.RangeSelector#getPosition + * + * @return {Highcharts.Dictionary} + */ + RangeSelector.prototype.getPosition = function () { + var chart = this.chart, + options = chart.options.rangeSelector, + top = options.verticalAlign === 'top' ? + chart.plotTop - chart.axisOffset[0] : + 0; // set offset only for varticalAlign top + return { + buttonTop: top + options.buttonPosition.y, + inputTop: top + options.inputPosition.y - 10 + }; + }; + /** + * Get the extremes of YTD. Will choose dataMax if its value is lower than + * the current timestamp. Will choose dataMin if its value is higher than + * the timestamp for the start of current year. + * + * @private + * @function Highcharts.RangeSelector#getYTDExtremes + * + * @param {number} dataMax + * + * @param {number} dataMin + * + * @return {*} + * Returns min and max for the YTD + */ + RangeSelector.prototype.getYTDExtremes = function (dataMax, dataMin, useUTC) { + var time = this.chart.time, + min, + now = new time.Date(dataMax), + year = time.get('FullYear', + now), + startOfYear = useUTC ? + time.Date.UTC(year, 0, 1) : // eslint-disable-line new-cap + +new time.Date(year, 0, 1); + min = Math.max(dataMin || 0, startOfYear); + now = now.getTime(); + return { + max: Math.min(dataMax || now, now), + min: min + }; + }; + /** + * Render the range selector including the buttons and the inputs. The first + * time render is called, the elements are created and positioned. On + * subsequent calls, they are moved and updated. + * + * @private + * @function Highcharts.RangeSelector#render + * @param {number} [min] + * X axis minimum + * @param {number} [max] + * X axis maximum + * @return {void} + */ + RangeSelector.prototype.render = function (min, max) { + var rangeSelector = this, + chart = rangeSelector.chart, + renderer = chart.renderer, + container = chart.container, + chartOptions = chart.options, + navButtonOptions = (chartOptions.exporting && + chartOptions.exporting.enabled !== false && + chartOptions.navigation && + chartOptions.navigation.buttonOptions), + lang = defaultOptions.lang, + div = rangeSelector.div, + options = chartOptions.rangeSelector, + // Place inputs above the container + inputsZIndex = pick(chartOptions.chart.style && + chartOptions.chart.style.zIndex, 0) + 1, + floating = options.floating, + buttons = rangeSelector.buttons, + inputGroup = rangeSelector.inputGroup, + buttonTheme = options.buttonTheme, + buttonPosition = options.buttonPosition, + inputPosition = options.inputPosition, + inputEnabled = options.inputEnabled, + states = buttonTheme && buttonTheme.states, + plotLeft = chart.plotLeft, + buttonLeft, + buttonGroup = rangeSelector.buttonGroup, + group, + groupHeight, + rendered = rangeSelector.rendered, + verticalAlign = rangeSelector.options.verticalAlign, + legend = chart.legend, + legendOptions = legend && legend.options, + buttonPositionY = buttonPosition.y, + inputPositionY = inputPosition.y, + animate = chart.hasLoaded, + verb = animate ? 'animate' : 'attr', + exportingX = 0, + alignTranslateY, + legendHeight, + minPosition, + translateY = 0, + translateX; + if (options.enabled === false) { + return; + } + // create the elements + if (!rendered) { + rangeSelector.group = group = renderer.g('range-selector-group') + .attr({ + zIndex: 7 + }) + .add(); + rangeSelector.buttonGroup = buttonGroup = + renderer.g('range-selector-buttons').add(group); + rangeSelector.zoomText = renderer + .text(lang.rangeSelectorZoom, 0, 15) + .add(buttonGroup); + if (!chart.styledMode) { + rangeSelector.zoomText.css(options.labelStyle); + buttonTheme['stroke-width'] = + pick(buttonTheme['stroke-width'], 0); + } + rangeSelector.buttonOptions.forEach(function (rangeOptions, i) { + buttons[i] = renderer + .button(rangeOptions.text, 0, 0, function (e) { + // extract events from button object and call + var buttonEvents = (rangeOptions.events && + rangeOptions.events.click), + callDefaultEvent; + if (buttonEvents) { + callDefaultEvent = + buttonEvents.call(rangeOptions, e); + } + if (callDefaultEvent !== false) { + rangeSelector.clickButton(i); + } + rangeSelector.isActive = true; + }, buttonTheme, states && states.hover, states && states.select, states && states.disabled) + .attr({ + 'text-align': 'center' + }) + .add(buttonGroup); + }); + // first create a wrapper outside the container in order to make + // the inputs work and make export correct + if (inputEnabled !== false) { + rangeSelector.div = div = createElement('div', null, { + position: 'relative', + height: 0, + zIndex: inputsZIndex + }); + container.parentNode.insertBefore(div, container); + // Create the group to keep the inputs + rangeSelector.inputGroup = inputGroup = + renderer.g('input-group').add(group); + inputGroup.offset = 0; + rangeSelector.drawInput('min'); + rangeSelector.drawInput('max'); + } + } + // #8769, allow dynamically updating margins + rangeSelector.zoomText[verb]({ + x: pick(plotLeft + buttonPosition.x, plotLeft) + }); + // button start position + buttonLeft = pick(plotLeft + buttonPosition.x, plotLeft) + + rangeSelector.zoomText.getBBox().width + 5; + rangeSelector.buttonOptions.forEach(function (rangeOptions, i) { + buttons[i][verb]({ x: buttonLeft }); + // increase button position for the next button + buttonLeft += buttons[i].width + pick(options.buttonSpacing, 5); + }); + plotLeft = chart.plotLeft - chart.spacing[3]; + rangeSelector.updateButtonStates(); + // detect collisiton with exporting + if (navButtonOptions && + this.titleCollision(chart) && + verticalAlign === 'top' && + buttonPosition.align === 'right' && ((buttonPosition.y + + buttonGroup.getBBox().height - 12) < + ((navButtonOptions.y || 0) + + navButtonOptions.height))) { + exportingX = -40; + } + translateX = buttonPosition.x - chart.spacing[3]; + if (buttonPosition.align === 'right') { + translateX += exportingX - plotLeft; // (#13014) + } + else if (buttonPosition.align === 'center') { + translateX -= plotLeft / 2; + } + // align button group + buttonGroup.align({ + y: buttonPosition.y, + width: buttonGroup.getBBox().width, + align: buttonPosition.align, + x: translateX + }, true, chart.spacingBox); + // skip animation + rangeSelector.group.placed = animate; + rangeSelector.buttonGroup.placed = animate; + if (inputEnabled !== false) { + var inputGroupX, + inputGroupWidth, + buttonGroupX, + buttonGroupWidth; + // detect collision with exporting + if (navButtonOptions && + this.titleCollision(chart) && + verticalAlign === 'top' && + inputPosition.align === 'right' && ((inputPosition.y - + inputGroup.getBBox().height - 12) < + ((navButtonOptions.y || 0) + + navButtonOptions.height + + chart.spacing[0]))) { + exportingX = -40; + } + else { + exportingX = 0; + } + if (inputPosition.align === 'left') { + translateX = plotLeft; + } + else if (inputPosition.align === 'right') { + translateX = -Math.max(chart.axisOffset[1], -exportingX); + } + // Update the alignment to the updated spacing box + inputGroup.align({ + y: inputPosition.y, + width: inputGroup.getBBox().width, + align: inputPosition.align, + // fix wrong getBBox() value on right align + x: inputPosition.x + translateX - 2 + }, true, chart.spacingBox); + // detect collision + inputGroupX = (inputGroup.alignAttr.translateX + + inputGroup.alignOptions.x - + exportingX + + // getBBox for detecing left margin + inputGroup.getBBox().x + + // 2px padding to not overlap input and label + 2); + inputGroupWidth = inputGroup.alignOptions.width; + buttonGroupX = buttonGroup.alignAttr.translateX + + buttonGroup.getBBox().x; + // 20 is minimal spacing between elements + buttonGroupWidth = buttonGroup.getBBox().width + 20; + if ((inputPosition.align === + buttonPosition.align) || ((buttonGroupX + buttonGroupWidth > inputGroupX) && + (inputGroupX + inputGroupWidth > buttonGroupX) && + (buttonPositionY < + (inputPositionY + + inputGroup.getBBox().height)))) { + inputGroup.attr({ + translateX: inputGroup.alignAttr.translateX + + (chart.axisOffset[1] >= -exportingX ? 0 : -exportingX), + translateY: inputGroup.alignAttr.translateY + + buttonGroup.getBBox().height + 10 + }); + } + // Set or reset the input values + rangeSelector.setInputValue('min', min); + rangeSelector.setInputValue('max', max); + // skip animation + rangeSelector.inputGroup.placed = animate; + } + // vertical align + rangeSelector.group.align({ + verticalAlign: verticalAlign + }, true, chart.spacingBox); + // set position + groupHeight = + rangeSelector.group.getBBox().height + 20; // # 20 padding + alignTranslateY = + rangeSelector.group.alignAttr.translateY; + // calculate bottom position + if (verticalAlign === 'bottom') { + legendHeight = (legendOptions && + legendOptions.verticalAlign === 'bottom' && + legendOptions.enabled && + !legendOptions.floating ? + legend.legendHeight + pick(legendOptions.margin, 10) : + 0); + groupHeight = groupHeight + legendHeight - 20; + translateY = (alignTranslateY - + groupHeight - + (floating ? 0 : options.y) - + (chart.titleOffset ? chart.titleOffset[2] : 0) - + 10 // 10 spacing + ); + } + if (verticalAlign === 'top') { + if (floating) { + translateY = 0; + } + if (chart.titleOffset && chart.titleOffset[0]) { + translateY = chart.titleOffset[0]; + } + translateY += ((chart.margin[0] - chart.spacing[0]) || 0); + } + else if (verticalAlign === 'middle') { + if (inputPositionY === buttonPositionY) { + if (inputPositionY < 0) { + translateY = alignTranslateY + minPosition; + } + else { + translateY = alignTranslateY; + } + } + else if (inputPositionY || buttonPositionY) { + if (inputPositionY < 0 || + buttonPositionY < 0) { + translateY -= Math.min(inputPositionY, buttonPositionY); + } + else { + translateY = + alignTranslateY - groupHeight + minPosition; + } + } + } + rangeSelector.group.translate(options.x, options.y + Math.floor(translateY)); + // translate HTML inputs + if (inputEnabled !== false) { + rangeSelector.minInput.style.marginTop = + rangeSelector.group.translateY + 'px'; + rangeSelector.maxInput.style.marginTop = + rangeSelector.group.translateY + 'px'; + } + rangeSelector.rendered = true; + }; + /** + * Extracts height of range selector + * + * @private + * @function Highcharts.RangeSelector#getHeight + * @return {number} + * Returns rangeSelector height + */ + RangeSelector.prototype.getHeight = function () { + var rangeSelector = this, + options = rangeSelector.options, + rangeSelectorGroup = rangeSelector.group, + inputPosition = options.inputPosition, + buttonPosition = options.buttonPosition, + yPosition = options.y, + buttonPositionY = buttonPosition.y, + inputPositionY = inputPosition.y, + rangeSelectorHeight = 0, + minPosition; + if (options.height) { + return options.height; + } + rangeSelectorHeight = rangeSelectorGroup ? + // 13px to keep back compatibility + (rangeSelectorGroup.getBBox(true).height) + 13 + + yPosition : + 0; + minPosition = Math.min(inputPositionY, buttonPositionY); + if ((inputPositionY < 0 && buttonPositionY < 0) || + (inputPositionY > 0 && buttonPositionY > 0)) { + rangeSelectorHeight += Math.abs(minPosition); + } + return rangeSelectorHeight; + }; + /** + * Detect collision with title or subtitle + * + * @private + * @function Highcharts.RangeSelector#titleCollision + * + * @param {Highcharts.Chart} chart + * + * @return {boolean} + * Returns collision status + */ + RangeSelector.prototype.titleCollision = function (chart) { + return !(chart.options.title.text || + chart.options.subtitle.text); + }; + /** + * Update the range selector with new options + * + * @private + * @function Highcharts.RangeSelector#update + * @param {Highcharts.RangeSelectorOptions} options + * @return {void} + */ + RangeSelector.prototype.update = function (options) { + var chart = this.chart; + merge(true, chart.options.rangeSelector, options); + this.destroy(); + this.init(chart); + chart.rangeSelector.render(); + }; + /** + * Destroys allocated elements. + * + * @private + * @function Highcharts.RangeSelector#destroy + */ + RangeSelector.prototype.destroy = function () { + var rSelector = this, + minInput = rSelector.minInput, + maxInput = rSelector.maxInput; + rSelector.unMouseDown(); + rSelector.unResize(); + // Destroy elements in collections + destroyObjectProperties(rSelector.buttons); + // Clear input element events + if (minInput) { + minInput.onfocus = minInput.onblur = minInput.onchange = null; + } + if (maxInput) { + maxInput.onfocus = maxInput.onblur = maxInput.onchange = null; + } + // Destroy HTML and SVG elements + objectEach(rSelector, function (val, key) { + if (val && key !== 'chart') { + if (val instanceof SVGElement) { + // SVGElement + val.destroy(); + } + else if (val instanceof window.HTMLElement) { + // HTML element + discardElement(val); + } + } + if (val !== RangeSelector.prototype[key]) { + rSelector[key] = null; + } + }, this); + }; + return RangeSelector; + }()); + /** + * The default buttons for pre-selecting time frames + */ + RangeSelector.prototype.defaultButtons = [{ + type: 'month', + count: 1, + text: '1m' + }, { + type: 'month', + count: 3, + text: '3m' + }, { + type: 'month', + count: 6, + text: '6m' + }, { + type: 'ytd', + text: 'YTD' + }, { + type: 'year', + count: 1, + text: '1y' + }, { + type: 'all', + text: 'All' + }]; + /** + * Get the axis min value based on the range option and the current max. For + * stock charts this is extended via the {@link RangeSelector} so that if the + * selected range is a multiple of months or years, it is compensated for + * various month lengths. + * + * @private + * @function Highcharts.Axis#minFromRange + * @return {number|undefined} + * The new minimum value. + */ + Axis.prototype.minFromRange = function () { + var rangeOptions = this.range, + type = rangeOptions.type, + min, + max = this.max, + dataMin, + range, + time = this.chart.time, + // Get the true range from a start date + getTrueRange = function (base, + count) { + var timeName = type === 'year' ? 'FullYear' : 'Month'; + var date = new time.Date(base); + var basePeriod = time.get(timeName, + date); + time.set(timeName, date, basePeriod + count); + if (basePeriod === time.get(timeName, date)) { + time.set('Date', date, 0); // #6537 + } + return date.getTime() - base; + }; + if (isNumber(rangeOptions)) { + min = max - rangeOptions; + range = rangeOptions; + } + else { + min = max + getTrueRange(max, -rangeOptions.count); + // Let the fixedRange reflect initial settings (#5930) + if (this.chart) { + this.chart.fixedRange = max - min; + } + } + dataMin = pick(this.dataMin, Number.MIN_VALUE); + if (!isNumber(min)) { + min = dataMin; + } + if (min <= dataMin) { + min = dataMin; + if (typeof range === 'undefined') { // #4501 + range = getTrueRange(min, rangeOptions.count); + } + this.newMax = Math.min(min + range, this.dataMax); + } + if (!isNumber(max)) { + min = void 0; + } + return min; + }; + if (!H.RangeSelector) { + // Initialize rangeselector for stock charts + addEvent(Chart, 'afterGetContainer', function () { + if (this.options.rangeSelector.enabled) { + this.rangeSelector = new RangeSelector(this); + } + }); + addEvent(Chart, 'beforeRender', function () { + var chart = this, + axes = chart.axes, + rangeSelector = chart.rangeSelector, + verticalAlign; + if (rangeSelector) { + if (isNumber(rangeSelector.deferredYTDClick)) { + rangeSelector.clickButton(rangeSelector.deferredYTDClick); + delete rangeSelector.deferredYTDClick; + } + axes.forEach(function (axis) { + axis.updateNames(); + axis.setScale(); + }); + chart.getAxisMargins(); + rangeSelector.render(); + verticalAlign = rangeSelector.options.verticalAlign; + if (!rangeSelector.options.floating) { + if (verticalAlign === 'bottom') { + this.extraBottomMargin = true; + } + else if (verticalAlign !== 'middle') { + this.extraTopMargin = true; + } + } + } + }); + addEvent(Chart, 'update', function (e) { + var chart = this, + options = e.options, + optionsRangeSelector = options.rangeSelector, + rangeSelector = chart.rangeSelector, + verticalAlign, + extraBottomMarginWas = this.extraBottomMargin, + extraTopMarginWas = this.extraTopMargin; + if (optionsRangeSelector && + optionsRangeSelector.enabled && + !defined(rangeSelector)) { + this.options.rangeSelector.enabled = true; + this.rangeSelector = new RangeSelector(this); + } + this.extraBottomMargin = false; + this.extraTopMargin = false; + if (rangeSelector) { + rangeSelector.render(); + verticalAlign = (optionsRangeSelector && + optionsRangeSelector.verticalAlign) || (rangeSelector.options && rangeSelector.options.verticalAlign); + if (!rangeSelector.options.floating) { + if (verticalAlign === 'bottom') { + this.extraBottomMargin = true; + } + else if (verticalAlign !== 'middle') { + this.extraTopMargin = true; + } + } + if (this.extraBottomMargin !== extraBottomMarginWas || + this.extraTopMargin !== extraTopMarginWas) { + this.isDirtyBox = true; + } + } + }); + addEvent(Chart, 'render', function () { + var chart = this, + rangeSelector = chart.rangeSelector, + verticalAlign; + if (rangeSelector && !rangeSelector.options.floating) { + rangeSelector.render(); + verticalAlign = rangeSelector.options.verticalAlign; + if (verticalAlign === 'bottom') { + this.extraBottomMargin = true; + } + else if (verticalAlign !== 'middle') { + this.extraTopMargin = true; + } + } + }); + addEvent(Chart, 'getMargins', function () { + var rangeSelector = this.rangeSelector, + rangeSelectorHeight; + if (rangeSelector) { + rangeSelectorHeight = rangeSelector.getHeight(); + if (this.extraTopMargin) { + this.plotTop += rangeSelectorHeight; + } + if (this.extraBottomMargin) { + this.marginBottom += rangeSelectorHeight; + } + } + }); + Chart.prototype.callbacks.push(function (chart) { + var extremes, + rangeSelector = chart.rangeSelector, + unbindRender, + unbindSetExtremes, + legend, + alignTo, + verticalAlign; + /** + * @private + */ + function renderRangeSelector() { + extremes = chart.xAxis[0].getExtremes(); + legend = chart.legend; + verticalAlign = rangeSelector === null || rangeSelector === void 0 ? void 0 : rangeSelector.options.verticalAlign; + if (isNumber(extremes.min)) { + rangeSelector.render(extremes.min, extremes.max); + } + // Re-align the legend so that it's below the rangeselector + if (rangeSelector && legend.display && + verticalAlign === 'top' && + verticalAlign === legend.options.verticalAlign) { + // Create a new alignment box for the legend. + alignTo = merge(chart.spacingBox); + if (legend.options.layout === 'vertical') { + alignTo.y = chart.plotTop; + } + else { + alignTo.y += rangeSelector.getHeight(); + } + legend.group.placed = false; // Don't animate the alignment. + legend.align(alignTo); + } + } + if (rangeSelector) { + // redraw the scroller on setExtremes + unbindSetExtremes = addEvent(chart.xAxis[0], 'afterSetExtremes', function (e) { + rangeSelector.render(e.min, e.max); + }); + // redraw the scroller chart resize + unbindRender = addEvent(chart, 'redraw', renderRangeSelector); + // do it now + renderRangeSelector(); + } + // Remove resize/afterSetExtremes at chart destroy + addEvent(chart, 'destroy', function destroyEvents() { + if (rangeSelector) { + unbindRender(); + unbindSetExtremes(); + } + }); + }); + H.RangeSelector = RangeSelector; + } + + return H.RangeSelector; + }); + _registerModule(_modules, 'Core/Axis/NavigatorAxis.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var isTouchDevice = H.isTouchDevice; + var addEvent = U.addEvent, + correctFloat = U.correctFloat, + defined = U.defined, + isNumber = U.isNumber, + pick = U.pick; + /* eslint-disable valid-jsdoc */ + /** + * @private + * @class + */ + var NavigatorAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function NavigatorAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * @private + */ + NavigatorAxisAdditions.prototype.destroy = function () { + this.axis = void 0; + }; + /** + * Add logic to normalize the zoomed range in order to preserve the pressed + * state of range selector buttons + * + * @private + * @function Highcharts.Axis#toFixedRange + * @param {number} [pxMin] + * @param {number} [pxMax] + * @param {number} [fixedMin] + * @param {number} [fixedMax] + * @return {*} + */ + NavigatorAxisAdditions.prototype.toFixedRange = function (pxMin, pxMax, fixedMin, fixedMax) { + var navigator = this; + var axis = navigator.axis; + var chart = axis.chart; + var fixedRange = chart && chart.fixedRange, + halfPointRange = (axis.pointRange || 0) / 2, + newMin = pick(fixedMin, + axis.translate(pxMin, + true, !axis.horiz)), + newMax = pick(fixedMax, + axis.translate(pxMax, + true, !axis.horiz)), + changeRatio = fixedRange && (newMax - newMin) / fixedRange; + // Add/remove half point range to/from the extremes (#1172) + if (!defined(fixedMin)) { + newMin = correctFloat(newMin + halfPointRange); + } + if (!defined(fixedMax)) { + newMax = correctFloat(newMax - halfPointRange); + } + // If the difference between the fixed range and the actual requested + // range is too great, the user is dragging across an ordinal gap, and + // we need to release the range selector button. + if (changeRatio > 0.7 && changeRatio < 1.3) { + if (fixedMax) { + newMin = newMax - fixedRange; + } + else { + newMax = newMin + fixedRange; + } + } + if (!isNumber(newMin) || !isNumber(newMax)) { // #1195, #7411 + newMin = newMax = void 0; + } + return { + min: newMin, + max: newMax + }; + }; + return NavigatorAxisAdditions; + }()); + /** + * @private + * @class + */ + var NavigatorAxis = /** @class */ (function () { + function NavigatorAxis() { + } + /* * + * + * Static Functions + * + * */ + /** + * @private + */ + NavigatorAxis.compose = function (AxisClass) { + AxisClass.keepProps.push('navigatorAxis'); + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'init', function () { + var axis = this; + if (!axis.navigatorAxis) { + axis.navigatorAxis = new NavigatorAxisAdditions(axis); + } + }); + // For Stock charts, override selection zooming with some special + // features because X axis zooming is already allowed by the Navigator + // and Range selector. + addEvent(AxisClass, 'zoom', function (e) { + var axis = this; + var chart = axis.chart; + var chartOptions = chart.options; + var navigator = chartOptions.navigator; + var navigatorAxis = axis.navigatorAxis; + var pinchType = chartOptions.chart.pinchType; + var rangeSelector = chartOptions.rangeSelector; + var zoomType = chartOptions.chart.zoomType; + var previousZoom; + if (axis.isXAxis && ((navigator && navigator.enabled) || + (rangeSelector && rangeSelector.enabled))) { + // For y only zooming, ignore the X axis completely + if (zoomType === 'y') { + e.zoomed = false; + // For xy zooming, record the state of the zoom before zoom + // selection, then when the reset button is pressed, revert to + // this state. This should apply only if the chart is + // initialized with a range (#6612), otherwise zoom all the way + // out. + } + else if (((!isTouchDevice && zoomType === 'xy') || + (isTouchDevice && pinchType === 'xy')) && + axis.options.range) { + previousZoom = navigatorAxis.previousZoom; + if (defined(e.newMin)) { + navigatorAxis.previousZoom = [axis.min, axis.max]; + } + else if (previousZoom) { + e.newMin = previousZoom[0]; + e.newMax = previousZoom[1]; + navigatorAxis.previousZoom = void 0; + } + } + } + if (typeof e.zoomed !== 'undefined') { + e.preventDefault(); + } + }); + /* eslint-enable no-invalid-this */ + }; + /* * + * + * Static Properties + * + * */ + /** + * @private + */ + NavigatorAxis.AdditionsClass = NavigatorAxisAdditions; + return NavigatorAxis; + }()); + + return NavigatorAxis; + }); + _registerModule(_modules, 'Core/Navigator.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Chart/Chart.js'], _modules['Core/Color.js'], _modules['Core/Globals.js'], _modules['Core/Axis/NavigatorAxis.js'], _modules['Core/Options.js'], _modules['Core/Scrollbar.js'], _modules['Core/Utilities.js']], function (Axis, Chart, Color, H, NavigatorAxis, O, Scrollbar, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var color = Color.parse; + var defaultOptions = O.defaultOptions; + var addEvent = U.addEvent, + clamp = U.clamp, + correctFloat = U.correctFloat, + defined = U.defined, + destroyObjectProperties = U.destroyObjectProperties, + erase = U.erase, + extend = U.extend, + find = U.find, + isArray = U.isArray, + isNumber = U.isNumber, + merge = U.merge, + pick = U.pick, + removeEvent = U.removeEvent, + splat = U.splat; + var hasTouch = H.hasTouch, + isTouchDevice = H.isTouchDevice, + Series = H.Series, + seriesTypes = H.seriesTypes, + defaultSeriesType, + // Finding the min or max of a set of variables where we don't know if they + // are defined, is a pattern that is repeated several places in Highcharts. + // Consider making this a global utility method. + numExt = function (extreme) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + var numbers = [].filter.call(args, + isNumber); + if (numbers.length) { + return Math[extreme].apply(0, numbers); + } + }; + defaultSeriesType = typeof seriesTypes.areaspline === 'undefined' ? + 'line' : + 'areaspline'; + extend(defaultOptions, { + /** + * Maximum range which can be set using the navigator's handles. + * Opposite of [xAxis.minRange](#xAxis.minRange). + * + * @sample {highstock} stock/navigator/maxrange/ + * Defined max and min range + * + * @type {number} + * @since 6.0.0 + * @product highstock gantt + * @apioption xAxis.maxRange + */ + /** + * The navigator is a small series below the main series, displaying + * a view of the entire data set. It provides tools to zoom in and + * out on parts of the data as well as panning across the dataset. + * + * @product highstock gantt + * @optionparent navigator + */ + navigator: { + /** + * Whether the navigator and scrollbar should adapt to updated data + * in the base X axis. When loading data async, as in the demo below, + * this should be `false`. Otherwise new data will trigger navigator + * redraw, which will cause unwanted looping. In the demo below, the + * data in the navigator is set only once. On navigating, only the main + * chart content is updated. + * + * @sample {highstock} stock/demo/lazy-loading/ + * Set to false with async data loading + * + * @type {boolean} + * @default true + * @apioption navigator.adaptToUpdatedData + */ + /** + * An integer identifying the index to use for the base series, or a + * string representing the id of the series. + * + * **Note**: As of Highcharts 5.0, this is now a deprecated option. + * Prefer [series.showInNavigator](#plotOptions.series.showInNavigator). + * + * @see [series.showInNavigator](#plotOptions.series.showInNavigator) + * + * @deprecated + * @type {number|string} + * @default 0 + * @apioption navigator.baseSeries + */ + /** + * Enable or disable the navigator. + * + * @sample {highstock} stock/navigator/enabled/ + * Disable the navigator + * + * @type {boolean} + * @default true + * @apioption navigator.enabled + */ + /** + * When the chart is inverted, whether to draw the navigator on the + * opposite side. + * + * @type {boolean} + * @default false + * @since 5.0.8 + * @apioption navigator.opposite + */ + /** + * The height of the navigator. + * + * @sample {highstock} stock/navigator/height/ + * A higher navigator + */ + height: 40, + /** + * The distance from the nearest element, the X axis or X axis labels. + * + * @sample {highstock} stock/navigator/margin/ + * A margin of 2 draws the navigator closer to the X axis labels + */ + margin: 25, + /** + * Whether the mask should be inside the range marking the zoomed + * range, or outside. In Highstock 1.x it was always `false`. + * + * @sample {highstock} stock/navigator/maskinside-false/ + * False, mask outside + * + * @since 2.0 + */ + maskInside: true, + /** + * Options for the handles for dragging the zoomed area. + * + * @sample {highstock} stock/navigator/handles/ + * Colored handles + */ + handles: { + /** + * Width for handles. + * + * @sample {highstock} stock/navigator/styled-handles/ + * Styled handles + * + * @since 6.0.0 + */ + width: 7, + /** + * Height for handles. + * + * @sample {highstock} stock/navigator/styled-handles/ + * Styled handles + * + * @since 6.0.0 + */ + height: 15, + /** + * Array to define shapes of handles. 0-index for left, 1-index for + * right. + * + * Additionally, the URL to a graphic can be given on this form: + * `url(graphic.png)`. Note that for the image to be applied to + * exported charts, its URL needs to be accessible by the export + * server. + * + * Custom callbacks for symbol path generation can also be added to + * `Highcharts.SVGRenderer.prototype.symbols`. The callback is then + * used by its method name, as shown in the demo. + * + * @sample {highstock} stock/navigator/styled-handles/ + * Styled handles + * + * @type {Array} + * @default ["navigator-handle", "navigator-handle"] + * @since 6.0.0 + */ + symbols: ['navigator-handle', 'navigator-handle'], + /** + * Allows to enable/disable handles. + * + * @since 6.0.0 + */ + enabled: true, + /** + * The width for the handle border and the stripes inside. + * + * @sample {highstock} stock/navigator/styled-handles/ + * Styled handles + * + * @since 6.0.0 + * @apioption navigator.handles.lineWidth + */ + lineWidth: 1, + /** + * The fill for the handle. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + backgroundColor: '#f2f2f2', + /** + * The stroke for the handle border and the stripes inside. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + borderColor: '#999999' + }, + /** + * The color of the mask covering the areas of the navigator series + * that are currently not visible in the main series. The default + * color is bluish with an opacity of 0.3 to see the series below. + * + * @see In styled mode, the mask is styled with the + * `.highcharts-navigator-mask` and + * `.highcharts-navigator-mask-inside` classes. + * + * @sample {highstock} stock/navigator/maskfill/ + * Blue, semi transparent mask + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default rgba(102,133,194,0.3) + */ + maskFill: color('#6685c2').setOpacity(0.3).get(), + /** + * The color of the line marking the currently zoomed area in the + * navigator. + * + * @sample {highstock} stock/navigator/outline/ + * 2px blue outline + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #cccccc + */ + outlineColor: '#cccccc', + /** + * The width of the line marking the currently zoomed area in the + * navigator. + * + * @see In styled mode, the outline stroke width is set with the + * `.highcharts-navigator-outline` class. + * + * @sample {highstock} stock/navigator/outline/ + * 2px blue outline + * + * @type {number} + */ + outlineWidth: 1, + /** + * Options for the navigator series. Available options are the same + * as any series, documented at [plotOptions](#plotOptions.series) + * and [series](#series). + * + * Unless data is explicitly defined on navigator.series, the data + * is borrowed from the first series in the chart. + * + * Default series options for the navigator series are: + * ```js + * series: { + * type: 'areaspline', + * fillOpacity: 0.05, + * dataGrouping: { + * smoothed: true + * }, + * lineWidth: 1, + * marker: { + * enabled: false + * } + * } + * ``` + * + * @see In styled mode, the navigator series is styled with the + * `.highcharts-navigator-series` class. + * + * @sample {highstock} stock/navigator/series-data/ + * Using a separate data set for the navigator + * @sample {highstock} stock/navigator/series/ + * A green navigator series + * + * @type {*|Array<*>|Highcharts.SeriesOptionsType|Array} + */ + series: { + /** + * The type of the navigator series. + * + * Heads up: + * In column-type navigator, zooming is limited to at least one + * point with its `pointRange`. + * + * @sample {highstock} stock/navigator/column/ + * Column type navigator + * + * @type {string} + * @default {highstock} `areaspline` if defined, otherwise `line` + * @default {gantt} gantt + */ + type: defaultSeriesType, + /** + * The fill opacity of the navigator series. + */ + fillOpacity: 0.05, + /** + * The pixel line width of the navigator series. + */ + lineWidth: 1, + /** + * @ignore-option + */ + compare: null, + /** + * Unless data is explicitly defined, the data is borrowed from the + * first series in the chart. + * + * @type {Array|object|null>} + * @product highstock + * @apioption navigator.series.data + */ + /** + * Data grouping options for the navigator series. + * + * @extends plotOptions.series.dataGrouping + */ + dataGrouping: { + approximation: 'average', + enabled: true, + groupPixelWidth: 2, + smoothed: true, + // Day and week differs from plotOptions.series.dataGrouping + units: [ + ['millisecond', [1, 2, 5, 10, 20, 25, 50, 100, 200, 500]], + ['second', [1, 2, 5, 10, 15, 30]], + ['minute', [1, 2, 5, 10, 15, 30]], + ['hour', [1, 2, 3, 4, 6, 8, 12]], + ['day', [1, 2, 3, 4]], + ['week', [1, 2, 3]], + ['month', [1, 3, 6]], + ['year', null] + ] + }, + /** + * Data label options for the navigator series. Data labels are + * disabled by default on the navigator series. + * + * @extends plotOptions.series.dataLabels + */ + dataLabels: { + enabled: false, + zIndex: 2 // #1839 + }, + id: 'highcharts-navigator-series', + className: 'highcharts-navigator-series', + /** + * Sets the fill color of the navigator series. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption navigator.series.color + */ + /** + * Line color for the navigator series. Allows setting the color + * while disallowing the default candlestick setting. + * + * @type {Highcharts.ColorString|null} + */ + lineColor: null, + marker: { + enabled: false + }, + /** + * Since Highstock v8, default value is the same as default + * `pointRange` defined for a specific type (e.g. `null` for + * column type). + * + * In Highstock version < 8, defaults to 0. + * + * @extends plotOptions.series.pointRange + * @type {number|null} + * @apioption navigator.series.pointRange + */ + /** + * The threshold option. Setting it to 0 will make the default + * navigator area series draw its area from the 0 value and up. + * + * @type {number|null} + */ + threshold: null + }, + /** + * Options for the navigator X axis. Default series options for the + * navigator xAxis are: + * ```js + * xAxis: { + * tickWidth: 0, + * lineWidth: 0, + * gridLineWidth: 1, + * tickPixelInterval: 200, + * labels: { + * align: 'left', + * style: { + * color: '#888' + * }, + * x: 3, + * y: -4 + * } + * } + * ``` + * + * @extends xAxis + * @excluding linkedTo, maxZoom, minRange, opposite, range, scrollbar, + * showEmpty, maxRange + */ + xAxis: { + /** + * Additional range on the right side of the xAxis. Works similar to + * xAxis.maxPadding, but value is set in milliseconds. + * Can be set for both, main xAxis and navigator's xAxis. + * + * @since 6.0.0 + */ + overscroll: 0, + className: 'highcharts-navigator-xaxis', + tickLength: 0, + lineWidth: 0, + gridLineColor: '#e6e6e6', + gridLineWidth: 1, + tickPixelInterval: 200, + labels: { + align: 'left', + /** + * @type {Highcharts.CSSObject} + */ + style: { + /** @ignore */ + color: '#999999' + }, + x: 3, + y: -4 + }, + crosshair: false + }, + /** + * Options for the navigator Y axis. Default series options for the + * navigator yAxis are: + * ```js + * yAxis: { + * gridLineWidth: 0, + * startOnTick: false, + * endOnTick: false, + * minPadding: 0.1, + * maxPadding: 0.1, + * labels: { + * enabled: false + * }, + * title: { + * text: null + * }, + * tickWidth: 0 + * } + * ``` + * + * @extends yAxis + * @excluding height, linkedTo, maxZoom, minRange, ordinal, range, + * showEmpty, scrollbar, top, units, maxRange, minLength, + * maxLength, resize + */ + yAxis: { + className: 'highcharts-navigator-yaxis', + gridLineWidth: 0, + startOnTick: false, + endOnTick: false, + minPadding: 0.1, + maxPadding: 0.1, + labels: { + enabled: false + }, + crosshair: false, + title: { + text: null + }, + tickLength: 0, + tickWidth: 0 + } + } + }); + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Draw one of the handles on the side of the zoomed range in the navigator + * + * @private + * @function Highcharts.Renderer#symbols.navigator-handle + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @param {Highcharts.NavigatorHandlesOptions} options + * @return {Highcharts.SVGPathArray} + * Path to be used in a handle + */ + H.Renderer.prototype.symbols['navigator-handle'] = function (x, y, w, h, options) { + var halfWidth = (options && options.width || 0) / 2, + markerPosition = Math.round(halfWidth / 3) + 0.5, + height = options && options.height || 0; + return [ + ['M', -halfWidth - 1, 0.5], + ['L', halfWidth, 0.5], + ['L', halfWidth, height + 0.5], + ['L', -halfWidth - 1, height + 0.5], + ['L', -halfWidth - 1, 0.5], + ['M', -markerPosition, 4], + ['L', -markerPosition, height - 3], + ['M', markerPosition - 1, 4], + ['L', markerPosition - 1, height - 3] + ]; + }; + /** + * The Navigator class + * + * @private + * @class + * @name Highcharts.Navigator + * + * @param {Highcharts.Chart} chart + * Chart object + */ + var Navigator = /** @class */ (function () { + function Navigator(chart) { + this.baseSeries = void 0; + this.chart = void 0; + this.handles = void 0; + this.height = void 0; + this.left = void 0; + this.navigatorEnabled = void 0; + this.navigatorGroup = void 0; + this.navigatorOptions = void 0; + this.navigatorSeries = void 0; + this.navigatorSize = void 0; + this.opposite = void 0; + this.outline = void 0; + this.outlineHeight = void 0; + this.range = void 0; + this.rendered = void 0; + this.shades = void 0; + this.size = void 0; + this.top = void 0; + this.xAxis = void 0; + this.yAxis = void 0; + this.zoomedMax = void 0; + this.zoomedMin = void 0; + this.init(chart); + } + /** + * Draw one of the handles on the side of the zoomed range in the navigator + * + * @private + * @function Highcharts.Navigator#drawHandle + * + * @param {number} x + * The x center for the handle + * + * @param {number} index + * 0 for left and 1 for right + * + * @param {boolean|undefined} inverted + * flag for chart.inverted + * + * @param {string} verb + * use 'animate' or 'attr' + */ + Navigator.prototype.drawHandle = function (x, index, inverted, verb) { + var navigator = this, + height = navigator.navigatorOptions.handles.height; + // Place it + navigator.handles[index][verb](inverted ? { + translateX: Math.round(navigator.left + navigator.height / 2), + translateY: Math.round(navigator.top + parseInt(x, 10) + 0.5 - height) + } : { + translateX: Math.round(navigator.left + parseInt(x, 10)), + translateY: Math.round(navigator.top + navigator.height / 2 - height / 2 - 1) + }); + }; + /** + * Render outline around the zoomed range + * + * @private + * @function Highcharts.Navigator#drawOutline + * + * @param {number} zoomedMin + * in pixels position where zoomed range starts + * + * @param {number} zoomedMax + * in pixels position where zoomed range ends + * + * @param {boolean|undefined} inverted + * flag if chart is inverted + * + * @param {string} verb + * use 'animate' or 'attr' + */ + Navigator.prototype.drawOutline = function (zoomedMin, zoomedMax, inverted, verb) { + var navigator = this, + maskInside = navigator.navigatorOptions.maskInside, + outlineWidth = navigator.outline.strokeWidth(), + halfOutline = outlineWidth / 2, + outlineCorrection = (outlineWidth % 2) / 2, // #5800 + outlineHeight = navigator.outlineHeight, + scrollbarHeight = navigator.scrollbarHeight || 0, + navigatorSize = navigator.size, + left = navigator.left - scrollbarHeight, + navigatorTop = navigator.top, + verticalMin, + path; + if (inverted) { + left -= halfOutline; + verticalMin = navigatorTop + zoomedMax + outlineCorrection; + zoomedMax = navigatorTop + zoomedMin + outlineCorrection; + path = [ + ['M', left + outlineHeight, navigatorTop - scrollbarHeight - outlineCorrection], + ['L', left + outlineHeight, verticalMin], + ['L', left, verticalMin], + ['L', left, zoomedMax], + ['L', left + outlineHeight, zoomedMax], + ['L', left + outlineHeight, navigatorTop + navigatorSize + scrollbarHeight] + ]; + if (maskInside) { + path.push(['M', left + outlineHeight, verticalMin - halfOutline], // upper left of zoomed range + ['L', left + outlineHeight, zoomedMax + halfOutline] // upper right of z.r. + ); + } + } + else { + zoomedMin += left + scrollbarHeight - outlineCorrection; + zoomedMax += left + scrollbarHeight - outlineCorrection; + navigatorTop += halfOutline; + path = [ + ['M', left, navigatorTop], + ['L', zoomedMin, navigatorTop], + ['L', zoomedMin, navigatorTop + outlineHeight], + ['L', zoomedMax, navigatorTop + outlineHeight], + ['L', zoomedMax, navigatorTop], + ['L', left + navigatorSize + scrollbarHeight * 2, navigatorTop] // right + ]; + if (maskInside) { + path.push(['M', zoomedMin - halfOutline, navigatorTop], // upper left of zoomed range + ['L', zoomedMax + halfOutline, navigatorTop] // upper right of z.r. + ); + } + } + navigator.outline[verb]({ + d: path + }); + }; + /** + * Render outline around the zoomed range + * + * @private + * @function Highcharts.Navigator#drawMasks + * + * @param {number} zoomedMin + * in pixels position where zoomed range starts + * + * @param {number} zoomedMax + * in pixels position where zoomed range ends + * + * @param {boolean|undefined} inverted + * flag if chart is inverted + * + * @param {string} verb + * use 'animate' or 'attr' + */ + Navigator.prototype.drawMasks = function (zoomedMin, zoomedMax, inverted, verb) { + var navigator = this, + left = navigator.left, + top = navigator.top, + navigatorHeight = navigator.height, + height, + width, + x, + y; + // Determine rectangle position & size + // According to (non)inverted position: + if (inverted) { + x = [left, left, left]; + y = [top, top + zoomedMin, top + zoomedMax]; + width = [navigatorHeight, navigatorHeight, navigatorHeight]; + height = [ + zoomedMin, + zoomedMax - zoomedMin, + navigator.size - zoomedMax + ]; + } + else { + x = [left, left + zoomedMin, left + zoomedMax]; + y = [top, top, top]; + width = [ + zoomedMin, + zoomedMax - zoomedMin, + navigator.size - zoomedMax + ]; + height = [navigatorHeight, navigatorHeight, navigatorHeight]; + } + navigator.shades.forEach(function (shade, i) { + shade[verb]({ + x: x[i], + y: y[i], + width: width[i], + height: height[i] + }); + }); + }; + /** + * Generate DOM elements for a navigator: + * + * - main navigator group + * + * - all shades + * + * - outline + * + * - handles + * + * @private + * @function Highcharts.Navigator#renderElements + */ + Navigator.prototype.renderElements = function () { + var navigator = this, + navigatorOptions = navigator.navigatorOptions, + maskInside = navigatorOptions.maskInside, + chart = navigator.chart, + inverted = chart.inverted, + renderer = chart.renderer, + navigatorGroup, + mouseCursor = { + cursor: inverted ? 'ns-resize' : 'ew-resize' + }; + // Create the main navigator group + navigator.navigatorGroup = navigatorGroup = renderer.g('navigator') + .attr({ + zIndex: 8, + visibility: 'hidden' + }) + .add(); + // Create masks, each mask will get events and fill: + [ + !maskInside, + maskInside, + !maskInside + ].forEach(function (hasMask, index) { + navigator.shades[index] = renderer.rect() + .addClass('highcharts-navigator-mask' + + (index === 1 ? '-inside' : '-outside')) + .add(navigatorGroup); + if (!chart.styledMode) { + navigator.shades[index] + .attr({ + fill: hasMask ? + navigatorOptions.maskFill : + 'rgba(0,0,0,0)' + }) + .css((index === 1) && mouseCursor); + } + }); + // Create the outline: + navigator.outline = renderer.path() + .addClass('highcharts-navigator-outline') + .add(navigatorGroup); + if (!chart.styledMode) { + navigator.outline.attr({ + 'stroke-width': navigatorOptions.outlineWidth, + stroke: navigatorOptions.outlineColor + }); + } + // Create the handlers: + if (navigatorOptions.handles.enabled) { + [0, 1].forEach(function (index) { + navigatorOptions.handles.inverted = chart.inverted; + navigator.handles[index] = renderer.symbol(navigatorOptions.handles.symbols[index], -navigatorOptions.handles.width / 2 - 1, 0, navigatorOptions.handles.width, navigatorOptions.handles.height, navigatorOptions.handles); + // zIndex = 6 for right handle, 7 for left. + // Can't be 10, because of the tooltip in inverted chart #2908 + navigator.handles[index].attr({ zIndex: 7 - index }) + .addClass('highcharts-navigator-handle ' + + 'highcharts-navigator-handle-' + + ['left', 'right'][index]).add(navigatorGroup); + if (!chart.styledMode) { + var handlesOptions = navigatorOptions.handles; + navigator.handles[index] + .attr({ + fill: handlesOptions.backgroundColor, + stroke: handlesOptions.borderColor, + 'stroke-width': handlesOptions.lineWidth + }) + .css(mouseCursor); + } + }); + } + }; + /** + * Update navigator + * + * @private + * @function Highcharts.Navigator#update + * + * @param {Highcharts.NavigatorOptions} options + * Options to merge in when updating navigator + */ + Navigator.prototype.update = function (options) { + // Remove references to old navigator series in base series + (this.series || []).forEach(function (series) { + if (series.baseSeries) { + delete series.baseSeries.navigatorSeries; + } + }); + // Destroy and rebuild navigator + this.destroy(); + var chartOptions = this.chart.options; + merge(true, chartOptions.navigator, this.options, options); + this.init(this.chart); + }; + /** + * Render the navigator + * + * @private + * @function Highcharts.Navigator#render + * @param {number} min + * X axis value minimum + * @param {number} max + * X axis value maximum + * @param {number} [pxMin] + * Pixel value minimum + * @param {number} [pxMax] + * Pixel value maximum + * @return {void} + */ + Navigator.prototype.render = function (min, max, pxMin, pxMax) { + var navigator = this, + chart = navigator.chart, + navigatorWidth, + scrollbarLeft, + scrollbarTop, + scrollbarHeight = navigator.scrollbarHeight, + navigatorSize, + xAxis = navigator.xAxis, + pointRange = xAxis.pointRange || 0, + scrollbarXAxis = xAxis.navigatorAxis.fake ? chart.xAxis[0] : xAxis, + navigatorEnabled = navigator.navigatorEnabled, + zoomedMin, + zoomedMax, + rendered = navigator.rendered, + inverted = chart.inverted, + verb, + newMin, + newMax, + currentRange, + minRange = chart.xAxis[0].minRange, + maxRange = chart.xAxis[0].options.maxRange; + // Don't redraw while moving the handles (#4703). + if (this.hasDragged && !defined(pxMin)) { + return; + } + min = correctFloat(min - pointRange / 2); + max = correctFloat(max + pointRange / 2); + // Don't render the navigator until we have data (#486, #4202, #5172). + if (!isNumber(min) || !isNumber(max)) { + // However, if navigator was already rendered, we may need to resize + // it. For example hidden series, but visible navigator (#6022). + if (rendered) { + pxMin = 0; + pxMax = pick(xAxis.width, scrollbarXAxis.width); + } + else { + return; + } + } + navigator.left = pick(xAxis.left, + // in case of scrollbar only, without navigator + chart.plotLeft + scrollbarHeight + + (inverted ? chart.plotWidth : 0)); + navigator.size = zoomedMax = navigatorSize = pick(xAxis.len, (inverted ? chart.plotHeight : chart.plotWidth) - + 2 * scrollbarHeight); + if (inverted) { + navigatorWidth = scrollbarHeight; + } + else { + navigatorWidth = navigatorSize + 2 * scrollbarHeight; + } + // Get the pixel position of the handles + pxMin = pick(pxMin, xAxis.toPixels(min, true)); + pxMax = pick(pxMax, xAxis.toPixels(max, true)); + // Verify (#1851, #2238) + if (!isNumber(pxMin) || Math.abs(pxMin) === Infinity) { + pxMin = 0; + pxMax = navigatorWidth; + } + // Are we below the minRange? (#2618, #6191) + newMin = xAxis.toValue(pxMin, true); + newMax = xAxis.toValue(pxMax, true); + currentRange = Math.abs(correctFloat(newMax - newMin)); + if (currentRange < minRange) { + if (this.grabbedLeft) { + pxMin = xAxis.toPixels(newMax - minRange - pointRange, true); + } + else if (this.grabbedRight) { + pxMax = xAxis.toPixels(newMin + minRange + pointRange, true); + } + } + else if (defined(maxRange) && + correctFloat(currentRange - pointRange) > maxRange) { + if (this.grabbedLeft) { + pxMin = xAxis.toPixels(newMax - maxRange - pointRange, true); + } + else if (this.grabbedRight) { + pxMax = xAxis.toPixels(newMin + maxRange + pointRange, true); + } + } + // Handles are allowed to cross, but never exceed the plot area + navigator.zoomedMax = clamp(Math.max(pxMin, pxMax), 0, zoomedMax); + navigator.zoomedMin = clamp(navigator.fixedWidth ? + navigator.zoomedMax - navigator.fixedWidth : + Math.min(pxMin, pxMax), 0, zoomedMax); + navigator.range = navigator.zoomedMax - navigator.zoomedMin; + zoomedMax = Math.round(navigator.zoomedMax); + zoomedMin = Math.round(navigator.zoomedMin); + if (navigatorEnabled) { + navigator.navigatorGroup.attr({ + visibility: 'visible' + }); + // Place elements + verb = rendered && !navigator.hasDragged ? 'animate' : 'attr'; + navigator.drawMasks(zoomedMin, zoomedMax, inverted, verb); + navigator.drawOutline(zoomedMin, zoomedMax, inverted, verb); + if (navigator.navigatorOptions.handles.enabled) { + navigator.drawHandle(zoomedMin, 0, inverted, verb); + navigator.drawHandle(zoomedMax, 1, inverted, verb); + } + } + if (navigator.scrollbar) { + if (inverted) { + scrollbarTop = navigator.top - scrollbarHeight; + scrollbarLeft = navigator.left - scrollbarHeight + + (navigatorEnabled || !scrollbarXAxis.opposite ? 0 : + // Multiple axes has offsets: + (scrollbarXAxis.titleOffset || 0) + + // Self margin from the axis.title + scrollbarXAxis.axisTitleMargin); + scrollbarHeight = navigatorSize + 2 * scrollbarHeight; + } + else { + scrollbarTop = navigator.top + (navigatorEnabled ? + navigator.height : + -scrollbarHeight); + scrollbarLeft = navigator.left - scrollbarHeight; + } + // Reposition scrollbar + navigator.scrollbar.position(scrollbarLeft, scrollbarTop, navigatorWidth, scrollbarHeight); + // Keep scale 0-1 + navigator.scrollbar.setRange( + // Use real value, not rounded because range can be very small + // (#1716) + navigator.zoomedMin / (navigatorSize || 1), navigator.zoomedMax / (navigatorSize || 1)); + } + navigator.rendered = true; + }; + /** + * Set up the mouse and touch events for the navigator + * + * @private + * @function Highcharts.Navigator#addMouseEvents + */ + Navigator.prototype.addMouseEvents = function () { + var navigator = this, + chart = navigator.chart, + container = chart.container, + eventsToUnbind = [], + mouseMoveHandler, + mouseUpHandler; + /** + * Create mouse events' handlers. + * Make them as separate functions to enable wrapping them: + */ + navigator.mouseMoveHandler = mouseMoveHandler = function (e) { + navigator.onMouseMove(e); + }; + navigator.mouseUpHandler = mouseUpHandler = function (e) { + navigator.onMouseUp(e); + }; + // Add shades and handles mousedown events + eventsToUnbind = navigator.getPartsEvents('mousedown'); + // Add mouse move and mouseup events. These are bind to doc/container, + // because Navigator.grabbedSomething flags are stored in mousedown + // events + eventsToUnbind.push(addEvent(chart.renderTo, 'mousemove', mouseMoveHandler), addEvent(container.ownerDocument, 'mouseup', mouseUpHandler)); + // Touch events + if (hasTouch) { + eventsToUnbind.push(addEvent(chart.renderTo, 'touchmove', mouseMoveHandler), addEvent(container.ownerDocument, 'touchend', mouseUpHandler)); + eventsToUnbind.concat(navigator.getPartsEvents('touchstart')); + } + navigator.eventsToUnbind = eventsToUnbind; + // Data events + if (navigator.series && navigator.series[0]) { + eventsToUnbind.push(addEvent(navigator.series[0].xAxis, 'foundExtremes', function () { + chart.navigator.modifyNavigatorAxisExtremes(); + })); + } + }; + /** + * Generate events for handles and masks + * + * @private + * @function Highcharts.Navigator#getPartsEvents + * + * @param {string} eventName + * Event name handler, 'mousedown' or 'touchstart' + * + * @return {Array} + * An array of functions to remove navigator functions from the + * events again. + */ + Navigator.prototype.getPartsEvents = function (eventName) { + var navigator = this, + events = []; + ['shades', 'handles'].forEach(function (name) { + navigator[name].forEach(function (navigatorItem, index) { + events.push(addEvent(navigatorItem.element, eventName, function (e) { + navigator[name + 'Mousedown'](e, index); + })); + }); + }); + return events; + }; + /** + * Mousedown on a shaded mask, either: + * + * - will be stored for future drag&drop + * + * - will directly shift to a new range + * + * @private + * @function Highcharts.Navigator#shadesMousedown + * + * @param {Highcharts.PointerEventObject} e + * Mouse event + * + * @param {number} index + * Index of a mask in Navigator.shades array + */ + Navigator.prototype.shadesMousedown = function (e, index) { + e = this.chart.pointer.normalize(e); + var navigator = this, + chart = navigator.chart, + xAxis = navigator.xAxis, + zoomedMin = navigator.zoomedMin, + navigatorPosition = navigator.left, + navigatorSize = navigator.size, + range = navigator.range, + chartX = e.chartX, + fixedMax, + fixedMin, + ext, + left; + // For inverted chart, swap some options: + if (chart.inverted) { + chartX = e.chartY; + navigatorPosition = navigator.top; + } + if (index === 1) { + // Store information for drag&drop + navigator.grabbedCenter = chartX; + navigator.fixedWidth = range; + navigator.dragOffset = chartX - zoomedMin; + } + else { + // Shift the range by clicking on shaded areas + left = chartX - navigatorPosition - range / 2; + if (index === 0) { + left = Math.max(0, left); + } + else if (index === 2 && left + range >= navigatorSize) { + left = navigatorSize - range; + if (navigator.reversedExtremes) { + // #7713 + left -= range; + fixedMin = navigator.getUnionExtremes().dataMin; + } + else { + // #2293, #3543 + fixedMax = navigator.getUnionExtremes().dataMax; + } + } + if (left !== zoomedMin) { // it has actually moved + navigator.fixedWidth = range; // #1370 + ext = xAxis.navigatorAxis.toFixedRange(left, left + range, fixedMin, fixedMax); + if (defined(ext.min)) { // #7411 + chart.xAxis[0].setExtremes(Math.min(ext.min, ext.max), Math.max(ext.min, ext.max), true, null, // auto animation + { trigger: 'navigator' }); + } + } + } + }; + /** + * Mousedown on a handle mask. + * Will store necessary information for drag&drop. + * + * @private + * @function Highcharts.Navigator#handlesMousedown + * @param {Highcharts.PointerEventObject} e + * Mouse event + * @param {number} index + * Index of a handle in Navigator.handles array + * @return {void} + */ + Navigator.prototype.handlesMousedown = function (e, index) { + e = this.chart.pointer.normalize(e); + var navigator = this, + chart = navigator.chart, + baseXAxis = chart.xAxis[0], + // For reversed axes, min and max are changed, + // so the other extreme should be stored + reverse = navigator.reversedExtremes; + if (index === 0) { + // Grab the left handle + navigator.grabbedLeft = true; + navigator.otherHandlePos = navigator.zoomedMax; + navigator.fixedExtreme = reverse ? baseXAxis.min : baseXAxis.max; + } + else { + // Grab the right handle + navigator.grabbedRight = true; + navigator.otherHandlePos = navigator.zoomedMin; + navigator.fixedExtreme = reverse ? baseXAxis.max : baseXAxis.min; + } + chart.fixedRange = null; + }; + /** + * Mouse move event based on x/y mouse position. + * + * @private + * @function Highcharts.Navigator#onMouseMove + * + * @param {Highcharts.PointerEventObject} e + * Mouse event + */ + Navigator.prototype.onMouseMove = function (e) { + var navigator = this, + chart = navigator.chart, + left = navigator.left, + navigatorSize = navigator.navigatorSize, + range = navigator.range, + dragOffset = navigator.dragOffset, + inverted = chart.inverted, + chartX; + // In iOS, a mousemove event with e.pageX === 0 is fired when holding + // the finger down in the center of the scrollbar. This should be + // ignored. + if (!e.touches || e.touches[0].pageX !== 0) { // #4696 + e = chart.pointer.normalize(e); + chartX = e.chartX; + // Swap some options for inverted chart + if (inverted) { + left = navigator.top; + chartX = e.chartY; + } + // Drag left handle or top handle + if (navigator.grabbedLeft) { + navigator.hasDragged = true; + navigator.render(0, 0, chartX - left, navigator.otherHandlePos); + // Drag right handle or bottom handle + } + else if (navigator.grabbedRight) { + navigator.hasDragged = true; + navigator.render(0, 0, navigator.otherHandlePos, chartX - left); + // Drag scrollbar or open area in navigator + } + else if (navigator.grabbedCenter) { + navigator.hasDragged = true; + if (chartX < dragOffset) { // outside left + chartX = dragOffset; + // outside right + } + else if (chartX > + navigatorSize + dragOffset - range) { + chartX = navigatorSize + dragOffset - range; + } + navigator.render(0, 0, chartX - dragOffset, chartX - dragOffset + range); + } + if (navigator.hasDragged && + navigator.scrollbar && + pick(navigator.scrollbar.options.liveRedraw, + // By default, don't run live redraw on VML, on touch + // devices or if the chart is in boost. + H.svg && !isTouchDevice && !this.chart.isBoosting)) { + e.DOMType = e.type; // DOMType is for IE8 + setTimeout(function () { + navigator.onMouseUp(e); + }, 0); + } + } + }; + /** + * Mouse up event based on x/y mouse position. + * + * @private + * @function Highcharts.Navigator#onMouseUp + * @param {Highcharts.PointerEventObject} e + * Mouse event + * @return {void} + */ + Navigator.prototype.onMouseUp = function (e) { + var navigator = this, + chart = navigator.chart, + xAxis = navigator.xAxis, + scrollbar = navigator.scrollbar, + DOMEvent = e.DOMEvent || e, + inverted = chart.inverted, + verb = navigator.rendered && !navigator.hasDragged ? + 'animate' : 'attr', + zoomedMax, + zoomedMin, + unionExtremes, + fixedMin, + fixedMax, + ext; + if ( + // MouseUp is called for both, navigator and scrollbar (that order), + // which causes calling afterSetExtremes twice. Prevent first call + // by checking if scrollbar is going to set new extremes (#6334) + (navigator.hasDragged && (!scrollbar || !scrollbar.hasDragged)) || + e.trigger === 'scrollbar') { + unionExtremes = navigator.getUnionExtremes(); + // When dragging one handle, make sure the other one doesn't change + if (navigator.zoomedMin === navigator.otherHandlePos) { + fixedMin = navigator.fixedExtreme; + } + else if (navigator.zoomedMax === navigator.otherHandlePos) { + fixedMax = navigator.fixedExtreme; + } + // Snap to right edge (#4076) + if (navigator.zoomedMax === navigator.size) { + fixedMax = navigator.reversedExtremes ? + unionExtremes.dataMin : + unionExtremes.dataMax; + } + // Snap to left edge (#7576) + if (navigator.zoomedMin === 0) { + fixedMin = navigator.reversedExtremes ? + unionExtremes.dataMax : + unionExtremes.dataMin; + } + ext = xAxis.navigatorAxis.toFixedRange(navigator.zoomedMin, navigator.zoomedMax, fixedMin, fixedMax); + if (defined(ext.min)) { + chart.xAxis[0].setExtremes(Math.min(ext.min, ext.max), Math.max(ext.min, ext.max), true, + // Run animation when clicking buttons, scrollbar track etc, + // but not when dragging handles or scrollbar + navigator.hasDragged ? false : null, { + trigger: 'navigator', + triggerOp: 'navigator-drag', + DOMEvent: DOMEvent // #1838 + }); + } + } + if (e.DOMType !== 'mousemove' && + e.DOMType !== 'touchmove') { + navigator.grabbedLeft = navigator.grabbedRight = + navigator.grabbedCenter = navigator.fixedWidth = + navigator.fixedExtreme = navigator.otherHandlePos = + navigator.hasDragged = navigator.dragOffset = null; + } + // Update position of navigator shades, outline and handles (#12573) + if (navigator.navigatorEnabled && + isNumber(navigator.zoomedMin) && + isNumber(navigator.zoomedMax)) { + zoomedMin = Math.round(navigator.zoomedMin); + zoomedMax = Math.round(navigator.zoomedMax); + if (navigator.shades) { + navigator.drawMasks(zoomedMin, zoomedMax, inverted, verb); + } + if (navigator.outline) { + navigator.drawOutline(zoomedMin, zoomedMax, inverted, verb); + } + if (navigator.navigatorOptions.handles.enabled && + Object.keys(navigator.handles).length === + navigator.handles.length) { + navigator.drawHandle(zoomedMin, 0, inverted, verb); + navigator.drawHandle(zoomedMax, 1, inverted, verb); + } + } + }; + /** + * Removes the event handlers attached previously with addEvents. + * + * @private + * @function Highcharts.Navigator#removeEvents + * @return {void} + */ + Navigator.prototype.removeEvents = function () { + if (this.eventsToUnbind) { + this.eventsToUnbind.forEach(function (unbind) { + unbind(); + }); + this.eventsToUnbind = void 0; + } + this.removeBaseSeriesEvents(); + }; + /** + * Remove data events. + * + * @private + * @function Highcharts.Navigator#removeBaseSeriesEvents + * @return {void} + */ + Navigator.prototype.removeBaseSeriesEvents = function () { + var baseSeries = this.baseSeries || []; + if (this.navigatorEnabled && baseSeries[0]) { + if (this.navigatorOptions.adaptToUpdatedData !== false) { + baseSeries.forEach(function (series) { + removeEvent(series, 'updatedData', this.updatedDataHandler); + }, this); + } + // We only listen for extremes-events on the first baseSeries + if (baseSeries[0].xAxis) { + removeEvent(baseSeries[0].xAxis, 'foundExtremes', this.modifyBaseAxisExtremes); + } + } + }; + /** + * Initialize the Navigator object + * + * @private + * @function Highcharts.Navigator#init + * + * @param {Highcharts.Chart} chart + */ + Navigator.prototype.init = function (chart) { + var chartOptions = chart.options, + navigatorOptions = chartOptions.navigator, + navigatorEnabled = navigatorOptions.enabled, + scrollbarOptions = chartOptions.scrollbar, + scrollbarEnabled = scrollbarOptions.enabled, + height = navigatorEnabled ? navigatorOptions.height : 0, + scrollbarHeight = scrollbarEnabled ? + scrollbarOptions.height : + 0; + this.handles = []; + this.shades = []; + this.chart = chart; + this.setBaseSeries(); + this.height = height; + this.scrollbarHeight = scrollbarHeight; + this.scrollbarEnabled = scrollbarEnabled; + this.navigatorEnabled = navigatorEnabled; + this.navigatorOptions = navigatorOptions; + this.scrollbarOptions = scrollbarOptions; + this.outlineHeight = height + scrollbarHeight; + this.opposite = pick(navigatorOptions.opposite, Boolean(!navigatorEnabled && chart.inverted)); // #6262 + var navigator = this, + baseSeries = navigator.baseSeries, + xAxisIndex = chart.xAxis.length, + yAxisIndex = chart.yAxis.length, + baseXaxis = baseSeries && baseSeries[0] && baseSeries[0].xAxis || + chart.xAxis[0] || { options: {} }; + chart.isDirtyBox = true; + if (navigator.navigatorEnabled) { + // an x axis is required for scrollbar also + navigator.xAxis = new Axis(chart, merge({ + // inherit base xAxis' break and ordinal options + breaks: baseXaxis.options.breaks, + ordinal: baseXaxis.options.ordinal + }, navigatorOptions.xAxis, { + id: 'navigator-x-axis', + yAxis: 'navigator-y-axis', + isX: true, + type: 'datetime', + index: xAxisIndex, + isInternal: true, + offset: 0, + keepOrdinalPadding: true, + startOnTick: false, + endOnTick: false, + minPadding: 0, + maxPadding: 0, + zoomEnabled: false + }, chart.inverted ? { + offsets: [scrollbarHeight, 0, -scrollbarHeight, 0], + width: height + } : { + offsets: [0, -scrollbarHeight, 0, scrollbarHeight], + height: height + })); + navigator.yAxis = new Axis(chart, merge(navigatorOptions.yAxis, { + id: 'navigator-y-axis', + alignTicks: false, + offset: 0, + index: yAxisIndex, + isInternal: true, + zoomEnabled: false + }, chart.inverted ? { + width: height + } : { + height: height + })); + // If we have a base series, initialize the navigator series + if (baseSeries || navigatorOptions.series.data) { + navigator.updateNavigatorSeries(false); + // If not, set up an event to listen for added series + } + else if (chart.series.length === 0) { + navigator.unbindRedraw = addEvent(chart, 'beforeRedraw', function () { + // We've got one, now add it as base + if (chart.series.length > 0 && !navigator.series) { + navigator.setBaseSeries(); + navigator.unbindRedraw(); // reset + } + }); + } + navigator.reversedExtremes = (chart.inverted && !navigator.xAxis.reversed) || (!chart.inverted && navigator.xAxis.reversed); + // Render items, so we can bind events to them: + navigator.renderElements(); + // Add mouse events + navigator.addMouseEvents(); + // in case of scrollbar only, fake an x axis to get translation + } + else { + navigator.xAxis = { + chart: chart, + navigatorAxis: { + fake: true + }, + translate: function (value, reverse) { + var axis = chart.xAxis[0], ext = axis.getExtremes(), scrollTrackWidth = axis.len - 2 * scrollbarHeight, min = numExt('min', axis.options.min, ext.dataMin), valueRange = numExt('max', axis.options.max, ext.dataMax) - min; + return reverse ? + // from pixel to value + (value * valueRange / scrollTrackWidth) + min : + // from value to pixel + scrollTrackWidth * (value - min) / valueRange; + }, + toPixels: function (value) { + return this.translate(value); + }, + toValue: function (value) { + return this.translate(value, true); + } + }; + navigator.xAxis.navigatorAxis.axis = navigator.xAxis; + navigator.xAxis.navigatorAxis.toFixedRange = (NavigatorAxis.AdditionsClass.prototype.toFixedRange.bind(navigator.xAxis.navigatorAxis)); + } + // Initialize the scrollbar + if (chart.options.scrollbar.enabled) { + chart.scrollbar = navigator.scrollbar = new Scrollbar(chart.renderer, merge(chart.options.scrollbar, { + margin: navigator.navigatorEnabled ? 0 : 10, + vertical: chart.inverted + }), chart); + addEvent(navigator.scrollbar, 'changed', function (e) { + var range = navigator.size, + to = range * this.to, + from = range * this.from; + navigator.hasDragged = navigator.scrollbar.hasDragged; + navigator.render(0, 0, from, to); + if (chart.options.scrollbar.liveRedraw || + (e.DOMType !== 'mousemove' && + e.DOMType !== 'touchmove')) { + setTimeout(function () { + navigator.onMouseUp(e); + }); + } + }); + } + // Add data events + navigator.addBaseSeriesEvents(); + // Add redraw events + navigator.addChartEvents(); + }; + /** + * Get the union data extremes of the chart - the outer data extremes of the + * base X axis and the navigator axis. + * + * @private + * @function Highcharts.Navigator#getUnionExtremes + * @param {boolean} [returnFalseOnNoBaseSeries] + * as the param says. + * @return {Highcharts.Dictionary<(number|undefined)>|undefined} + */ + Navigator.prototype.getUnionExtremes = function (returnFalseOnNoBaseSeries) { + var baseAxis = this.chart.xAxis[0], + navAxis = this.xAxis, + navAxisOptions = navAxis.options, + baseAxisOptions = baseAxis.options, + ret; + if (!returnFalseOnNoBaseSeries || baseAxis.dataMin !== null) { + ret = { + dataMin: pick(// #4053 + navAxisOptions && navAxisOptions.min, numExt('min', baseAxisOptions.min, baseAxis.dataMin, navAxis.dataMin, navAxis.min)), + dataMax: pick(navAxisOptions && navAxisOptions.max, numExt('max', baseAxisOptions.max, baseAxis.dataMax, navAxis.dataMax, navAxis.max)) + }; + } + return ret; + }; + /** + * Set the base series and update the navigator series from this. With a bit + * of modification we should be able to make this an API method to be called + * from the outside + * + * @private + * @function Highcharts.Navigator#setBaseSeries + * @param {Highcharts.SeriesOptionsType} [baseSeriesOptions] + * Additional series options for a navigator + * @param {boolean} [redraw] + * Whether to redraw after update. + * @return {void} + */ + Navigator.prototype.setBaseSeries = function (baseSeriesOptions, redraw) { + var chart = this.chart, + baseSeries = this.baseSeries = []; + baseSeriesOptions = (baseSeriesOptions || + chart.options && chart.options.navigator.baseSeries || + (chart.series.length ? + // Find the first non-navigator series (#8430) + find(chart.series, function (s) { + return !s.options.isInternal; + }).index : + 0)); + // Iterate through series and add the ones that should be shown in + // navigator. + (chart.series || []).forEach(function (series, i) { + if ( + // Don't include existing nav series + !series.options.isInternal && + (series.options.showInNavigator || + (i === baseSeriesOptions || + series.options.id === baseSeriesOptions) && + series.options.showInNavigator !== false)) { + baseSeries.push(series); + } + }); + // When run after render, this.xAxis already exists + if (this.xAxis && !this.xAxis.navigatorAxis.fake) { + this.updateNavigatorSeries(true, redraw); + } + }; + /** + * Update series in the navigator from baseSeries, adding new if does not + * exist. + * + * @private + * @function Highcharts.Navigator.updateNavigatorSeries + * @param {boolean} addEvents + * @param {boolean} [redraw] + * @return {void} + */ + Navigator.prototype.updateNavigatorSeries = function (addEvents, redraw) { + var navigator = this, + chart = navigator.chart, + baseSeries = navigator.baseSeries, + baseOptions, + mergedNavSeriesOptions, + chartNavigatorSeriesOptions = navigator.navigatorOptions.series, + baseNavigatorOptions, + navSeriesMixin = { + enableMouseTracking: false, + index: null, + linkedTo: null, + group: 'nav', + padXAxis: false, + xAxis: 'navigator-x-axis', + yAxis: 'navigator-y-axis', + showInLegend: false, + stacking: void 0, + isInternal: true, + states: { + inactive: { + opacity: 1 + } + } + }, + // Remove navigator series that are no longer in the baseSeries + navigatorSeries = navigator.series = + (navigator.series || []).filter(function (navSeries) { + var base = navSeries.baseSeries; + if (baseSeries.indexOf(base) < 0) { // Not in array + // If there is still a base series connected to this + // series, remove event handler and reference. + if (base) { + removeEvent(base, 'updatedData', navigator.updatedDataHandler); + delete base.navigatorSeries; + } + // Kill the nav series. It may already have been + // destroyed (#8715). + if (navSeries.chart) { + navSeries.destroy(); + } + return false; + } + return true; + }); + // Go through each base series and merge the options to create new + // series + if (baseSeries && baseSeries.length) { + baseSeries.forEach(function eachBaseSeries(base) { + var linkedNavSeries = base.navigatorSeries, + userNavOptions = extend( + // Grab color and visibility from base as default + { + color: base.color, + visible: base.visible + }, !isArray(chartNavigatorSeriesOptions) ? + chartNavigatorSeriesOptions : + defaultOptions.navigator.series); + // Don't update if the series exists in nav and we have disabled + // adaptToUpdatedData. + if (linkedNavSeries && + navigator.navigatorOptions.adaptToUpdatedData === false) { + return; + } + navSeriesMixin.name = 'Navigator ' + baseSeries.length; + baseOptions = base.options || {}; + baseNavigatorOptions = baseOptions.navigatorOptions || {}; + mergedNavSeriesOptions = merge(baseOptions, navSeriesMixin, userNavOptions, baseNavigatorOptions); + // Once nav series type is resolved, pick correct pointRange + mergedNavSeriesOptions.pointRange = pick( + // Stricte set pointRange in options + userNavOptions.pointRange, baseNavigatorOptions.pointRange, + // Fallback to default values, e.g. `null` for column + defaultOptions.plotOptions[mergedNavSeriesOptions.type || 'line'].pointRange); + // Merge data separately. Do a slice to avoid mutating the + // navigator options from base series (#4923). + var navigatorSeriesData = baseNavigatorOptions.data || userNavOptions.data; + navigator.hasNavigatorData = + navigator.hasNavigatorData || !!navigatorSeriesData; + mergedNavSeriesOptions.data = + navigatorSeriesData || + baseOptions.data && baseOptions.data.slice(0); + // Update or add the series + if (linkedNavSeries && linkedNavSeries.options) { + linkedNavSeries.update(mergedNavSeriesOptions, redraw); + } + else { + base.navigatorSeries = chart.initSeries(mergedNavSeriesOptions); + base.navigatorSeries.baseSeries = base; // Store ref + navigatorSeries.push(base.navigatorSeries); + } + }); + } + // If user has defined data (and no base series) or explicitly defined + // navigator.series as an array, we create these series on top of any + // base series. + if (chartNavigatorSeriesOptions.data && + !(baseSeries && baseSeries.length) || + isArray(chartNavigatorSeriesOptions)) { + navigator.hasNavigatorData = false; + // Allow navigator.series to be an array + chartNavigatorSeriesOptions = + splat(chartNavigatorSeriesOptions); + chartNavigatorSeriesOptions.forEach(function (userSeriesOptions, i) { + navSeriesMixin.name = + 'Navigator ' + (navigatorSeries.length + 1); + mergedNavSeriesOptions = merge(defaultOptions.navigator.series, { + // Since we don't have a base series to pull color from, + // try to fake it by using color from series with same + // index. Otherwise pull from the colors array. We need + // an explicit color as otherwise updates will increment + // color counter and we'll get a new color for each + // update of the nav series. + color: chart.series[i] && + !chart.series[i].options.isInternal && + chart.series[i].color || + chart.options.colors[i] || + chart.options.colors[0] + }, navSeriesMixin, userSeriesOptions); + mergedNavSeriesOptions.data = userSeriesOptions.data; + if (mergedNavSeriesOptions.data) { + navigator.hasNavigatorData = true; + navigatorSeries.push(chart.initSeries(mergedNavSeriesOptions)); + } + }); + } + if (addEvents) { + this.addBaseSeriesEvents(); + } + }; + /** + * Add data events. + * For example when main series is updated we need to recalculate extremes + * + * @private + * @function Highcharts.Navigator#addBaseSeriesEvent + * @return {void} + */ + Navigator.prototype.addBaseSeriesEvents = function () { + var navigator = this, + baseSeries = navigator.baseSeries || []; + // Bind modified extremes event to first base's xAxis only. + // In event of > 1 base-xAxes, the navigator will ignore those. + // Adding this multiple times to the same axis is no problem, as + // duplicates should be discarded by the browser. + if (baseSeries[0] && baseSeries[0].xAxis) { + addEvent(baseSeries[0].xAxis, 'foundExtremes', this.modifyBaseAxisExtremes); + } + baseSeries.forEach(function (base) { + // Link base series show/hide to navigator series visibility + addEvent(base, 'show', function () { + if (this.navigatorSeries) { + this.navigatorSeries.setVisible(true, false); + } + }); + addEvent(base, 'hide', function () { + if (this.navigatorSeries) { + this.navigatorSeries.setVisible(false, false); + } + }); + // Respond to updated data in the base series, unless explicitily + // not adapting to data changes. + if (this.navigatorOptions.adaptToUpdatedData !== false) { + if (base.xAxis) { + addEvent(base, 'updatedData', this.updatedDataHandler); + } + } + // Handle series removal + addEvent(base, 'remove', function () { + if (this.navigatorSeries) { + erase(navigator.series, this.navigatorSeries); + if (defined(this.navigatorSeries.options)) { + this.navigatorSeries.remove(false); + } + delete this.navigatorSeries; + } + }); + }, this); + }; + /** + * Get minimum from all base series connected to the navigator + * @private + * @param {number} currentSeriesMin + * Minium from the current series + * @return {number} Minimum from all series + */ + Navigator.prototype.getBaseSeriesMin = function (currentSeriesMin) { + return this.baseSeries.reduce(function (min, series) { + // (#10193) + return Math.min(min, series.xData ? series.xData[0] : min); + }, currentSeriesMin); + }; + /** + * Set the navigator x axis extremes to reflect the total. The navigator + * extremes should always be the extremes of the union of all series in the + * chart as well as the navigator series. + * + * @private + * @function Highcharts.Navigator#modifyNavigatorAxisExtremes + */ + Navigator.prototype.modifyNavigatorAxisExtremes = function () { + var xAxis = this.xAxis, + unionExtremes; + if (typeof xAxis.getExtremes !== 'undefined') { + unionExtremes = this.getUnionExtremes(true); + if (unionExtremes && + (unionExtremes.dataMin !== xAxis.min || + unionExtremes.dataMax !== xAxis.max)) { + xAxis.min = unionExtremes.dataMin; + xAxis.max = unionExtremes.dataMax; + } + } + }; + /** + * Hook to modify the base axis extremes with information from the Navigator + * + * @private + * @function Highcharts.Navigator#modifyBaseAxisExtremes + */ + Navigator.prototype.modifyBaseAxisExtremes = function () { + var baseXAxis = this, + navigator = baseXAxis.chart.navigator, + baseExtremes = baseXAxis.getExtremes(), + baseMin = baseExtremes.min, + baseMax = baseExtremes.max, + baseDataMin = baseExtremes.dataMin, + baseDataMax = baseExtremes.dataMax, + range = baseMax - baseMin, + stickToMin = navigator.stickToMin, + stickToMax = navigator.stickToMax, + overscroll = pick(baseXAxis.options.overscroll, 0), + newMax, + newMin, + navigatorSeries = navigator.series && navigator.series[0], + hasSetExtremes = !!baseXAxis.setExtremes, + // When the extremes have been set by range selector button, don't + // stick to min or max. The range selector buttons will handle the + // extremes. (#5489) + unmutable = baseXAxis.eventArgs && + baseXAxis.eventArgs.trigger === 'rangeSelectorButton'; + if (!unmutable) { + // If the zoomed range is already at the min, move it to the right + // as new data comes in + if (stickToMin) { + newMin = baseDataMin; + newMax = newMin + range; + } + // If the zoomed range is already at the max, move it to the right + // as new data comes in + if (stickToMax) { + newMax = baseDataMax + overscroll; + // If stickToMin is true, the new min value is set above + if (!stickToMin) { + newMin = Math.max(baseDataMin, // don't go below data extremes (#13184) + newMax - range, navigator.getBaseSeriesMin(navigatorSeries && navigatorSeries.xData ? + navigatorSeries.xData[0] : + -Number.MAX_VALUE)); + } + } + // Update the extremes + if (hasSetExtremes && (stickToMin || stickToMax)) { + if (isNumber(newMin)) { + baseXAxis.min = baseXAxis.userMin = newMin; + baseXAxis.max = baseXAxis.userMax = newMax; + } + } + } + // Reset + navigator.stickToMin = + navigator.stickToMax = null; + }; + /** + * Handler for updated data on the base series. When data is modified, the + * navigator series must reflect it. This is called from the Chart.redraw + * function before axis and series extremes are computed. + * + * @private + * @function Highcharts.Navigator#updateDataHandler + */ + Navigator.prototype.updatedDataHandler = function () { + var navigator = this.chart.navigator, + baseSeries = this, + navigatorSeries = this.navigatorSeries, + xDataMin = navigator.getBaseSeriesMin(baseSeries.xData[0]); + // If the scrollbar is scrolled all the way to the right, keep right as + // new data comes in. + navigator.stickToMax = navigator.reversedExtremes ? + Math.round(navigator.zoomedMin) === 0 : + Math.round(navigator.zoomedMax) >= Math.round(navigator.size); + // Detect whether the zoomed area should stick to the minimum or + // maximum. If the current axis minimum falls outside the new updated + // dataset, we must adjust. + navigator.stickToMin = isNumber(baseSeries.xAxis.min) && + (baseSeries.xAxis.min <= xDataMin) && + (!this.chart.fixedRange || !navigator.stickToMax); + // Set the navigator series data to the new data of the base series + if (navigatorSeries && !navigator.hasNavigatorData) { + navigatorSeries.options.pointStart = baseSeries.xData[0]; + navigatorSeries.setData(baseSeries.options.data, false, null, false); // #5414 + } + }; + /** + * Add chart events, like redrawing navigator, when chart requires that. + * + * @private + * @function Highcharts.Navigator#addChartEvents + * @return {void} + */ + Navigator.prototype.addChartEvents = function () { + if (!this.eventsToUnbind) { + this.eventsToUnbind = []; + } + this.eventsToUnbind.push( + // Move the scrollbar after redraw, like after data updata even if + // axes don't redraw + addEvent(this.chart, 'redraw', function () { + var navigator = this.navigator, + xAxis = navigator && (navigator.baseSeries && + navigator.baseSeries[0] && + navigator.baseSeries[0].xAxis || + this.xAxis[0]); // #5709, #13114 + if (xAxis) { + navigator.render(xAxis.min, + xAxis.max); + } + }), + // Make room for the navigator, can be placed around the chart: + addEvent(this.chart, 'getMargins', function () { + var chart = this, + navigator = chart.navigator, + marginName = navigator.opposite ? + 'plotTop' : 'marginBottom'; + if (chart.inverted) { + marginName = navigator.opposite ? + 'marginRight' : 'plotLeft'; + } + chart[marginName] = + (chart[marginName] || 0) + (navigator.navigatorEnabled || !chart.inverted ? + navigator.outlineHeight : + 0) + navigator.navigatorOptions.margin; + })); + }; + /** + * Destroys allocated elements. + * + * @private + * @function Highcharts.Navigator#destroy + */ + Navigator.prototype.destroy = function () { + // Disconnect events added in addEvents + this.removeEvents(); + if (this.xAxis) { + erase(this.chart.xAxis, this.xAxis); + erase(this.chart.axes, this.xAxis); + } + if (this.yAxis) { + erase(this.chart.yAxis, this.yAxis); + erase(this.chart.axes, this.yAxis); + } + // Destroy series + (this.series || []).forEach(function (s) { + if (s.destroy) { + s.destroy(); + } + }); + // Destroy properties + [ + 'series', 'xAxis', 'yAxis', 'shades', 'outline', 'scrollbarTrack', + 'scrollbarRifles', 'scrollbarGroup', 'scrollbar', 'navigatorGroup', + 'rendered' + ].forEach(function (prop) { + if (this[prop] && this[prop].destroy) { + this[prop].destroy(); + } + this[prop] = null; + }, this); + // Destroy elements in collection + [this.handles].forEach(function (coll) { + destroyObjectProperties(coll); + }, this); + }; + return Navigator; + }()); + // End of prototype + if (!H.Navigator) { + H.Navigator = Navigator; + NavigatorAxis.compose(Axis); + // For Stock charts. For x only zooming, do not to create the zoom button + // because X axis zooming is already allowed by the Navigator and Range + // selector. (#9285) + addEvent(Chart, 'beforeShowResetZoom', function () { + var chartOptions = this.options, + navigator = chartOptions.navigator, + rangeSelector = chartOptions.rangeSelector; + if (((navigator && navigator.enabled) || + (rangeSelector && rangeSelector.enabled)) && + ((!isTouchDevice && chartOptions.chart.zoomType === 'x') || + (isTouchDevice && chartOptions.chart.pinchType === 'x'))) { + return false; + } + }); + // Initialize navigator for stock charts + addEvent(Chart, 'beforeRender', function () { + var options = this.options; + if (options.navigator.enabled || + options.scrollbar.enabled) { + this.scroller = this.navigator = new Navigator(this); + } + }); + // For stock charts, extend the Chart.setChartSize method so that we can set + // the final top position of the navigator once the height of the chart, + // including the legend, is determined. #367. We can't use Chart.getMargins, + // because labels offsets are not calculated yet. + addEvent(Chart, 'afterSetChartSize', function () { + var legend = this.legend, + navigator = this.navigator, + scrollbarHeight, + legendOptions, + xAxis, + yAxis; + if (navigator) { + legendOptions = legend && legend.options; + xAxis = navigator.xAxis; + yAxis = navigator.yAxis; + scrollbarHeight = navigator.scrollbarHeight; + // Compute the top position + if (this.inverted) { + navigator.left = navigator.opposite ? + this.chartWidth - scrollbarHeight - + navigator.height : + this.spacing[3] + scrollbarHeight; + navigator.top = this.plotTop + scrollbarHeight; + } + else { + navigator.left = this.plotLeft + scrollbarHeight; + navigator.top = navigator.navigatorOptions.top || + this.chartHeight - + navigator.height - + scrollbarHeight - + this.spacing[2] - + (this.rangeSelector && this.extraBottomMargin ? + this.rangeSelector.getHeight() : + 0) - + ((legendOptions && + legendOptions.verticalAlign === 'bottom' && + legendOptions.layout !== 'proximate' && // #13392 + legendOptions.enabled && + !legendOptions.floating) ? + legend.legendHeight + + pick(legendOptions.margin, 10) : + 0) - + (this.titleOffset ? this.titleOffset[2] : 0); + } + if (xAxis && yAxis) { // false if navigator is disabled (#904) + if (this.inverted) { + xAxis.options.left = yAxis.options.left = navigator.left; + } + else { + xAxis.options.top = yAxis.options.top = navigator.top; + } + xAxis.setAxisSize(); + yAxis.setAxisSize(); + } + } + }); + // Merge options, if no scrolling exists yet + addEvent(Chart, 'update', function (e) { + var navigatorOptions = (e.options.navigator || {}), + scrollbarOptions = (e.options.scrollbar || {}); + if (!this.navigator && !this.scroller && + (navigatorOptions.enabled || scrollbarOptions.enabled)) { + merge(true, this.options.navigator, navigatorOptions); + merge(true, this.options.scrollbar, scrollbarOptions); + delete e.options.navigator; + delete e.options.scrollbar; + } + }); + // Initialize navigator, if no scrolling exists yet + addEvent(Chart, 'afterUpdate', function (event) { + if (!this.navigator && !this.scroller && + (this.options.navigator.enabled || + this.options.scrollbar.enabled)) { + this.scroller = this.navigator = new Navigator(this); + if (pick(event.redraw, true)) { + this.redraw(event.animation); // #7067 + } + } + }); + // Handle adding new series + addEvent(Chart, 'afterAddSeries', function () { + if (this.navigator) { + // Recompute which series should be shown in navigator, and add them + this.navigator.setBaseSeries(null, false); + } + }); + // Handle updating series + addEvent(Series, 'afterUpdate', function () { + if (this.chart.navigator && !this.options.isInternal) { + this.chart.navigator.setBaseSeries(null, false); + } + }); + Chart.prototype.callbacks.push(function (chart) { + var extremes, + navigator = chart.navigator; + // Initialize the navigator + if (navigator && chart.xAxis[0]) { + extremes = chart.xAxis[0].getExtremes(); + navigator.render(extremes.min, extremes.max); + } + }); + } + H.Navigator = Navigator; + + return H.Navigator; + }); + _registerModule(_modules, 'masters/modules/gantt.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/grid-axis.js b/highcharts/modules/grid-axis.js new file mode 100644 index 0000000..5b1f99c --- /dev/null +++ b/highcharts/modules/grid-axis.js @@ -0,0 +1,28 @@ +/* + Highcharts Gantt JS v8.2.0 (2020-08-20) + + GridAxis + + (c) 2016-2019 Lars A. V. Cabrera + + License: www.highcharts.com/license +*/ +(function(d){"object"===typeof module&&module.exports?(d["default"]=d,module.exports=d):"function"===typeof define&&define.amd?define("highcharts/modules/grid-axis",["highcharts"],function(n){d(n);d.Highcharts=n;return d}):d("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(d){function n(d,w,n,A){d.hasOwnProperty(w)||(d[w]=A.apply(null,n))}d=d?d._modules:{};n(d,"Core/Axis/GridAxis.js",[d["Core/Axis/Axis.js"],d["Core/Globals.js"],d["Core/Options.js"],d["Core/Axis/Tick.js"],d["Core/Utilities.js"]], +function(d,n,z,A,l){var w=z.dateFormat,f=l.addEvent,p=l.defined,C=l.erase,E=l.find,F=l.isArray,B=l.isNumber,x=l.merge,y=l.pick,G=l.timeUnits,D=l.wrap;z=n.Chart;var H=function(b){var a=b.options;a.labels||(a.labels={});a.labels.align=y(a.labels.align,"center");b.categories||(a.showLastLabel=!1);b.labelRotation=0;a.labels.rotation=0};"";d.prototype.getMaxLabelDimensions=function(b,a){var c={width:0,height:0};a.forEach(function(a){var e=b[a];a=0;if(l.isObject(e,!0)){var h=l.isObject(e.label,!0)?e.label: +{};e=h.getBBox?h.getBBox().height:0;h.textStr&&(a=Math.round(h.getBBox().width));c.height=Math.max(e,c.height);c.width=Math.max(a,c.width)}});return c};n.dateFormats.W=function(b){b=new this.Date(b);var a=(this.get("Day",b)+6)%7,c=new this.Date(b.valueOf());this.set("Date",c,this.get("Date",b)-a+3);a=new this.Date(this.get("FullYear",c),0,1);4!==this.get("Day",a)&&(this.set("Month",b,0),this.set("Date",b,1+(11-this.get("Day",a))%7));return(1+Math.floor((c.valueOf()-a.valueOf())/6048E5)).toString()}; +n.dateFormats.E=function(b){return w("%a",b,!0).charAt(0)};f(z,"afterSetChartSize",function(){this.axes.forEach(function(b){(b.grid&&b.grid.columns||[]).forEach(function(a){a.setAxisSize();a.setAxisTranslation()})})});f(A,"afterGetLabelPosition",function(b){var a=this.label,c=this.axis,h=c.reversed,e=c.chart,m=c.options.grid||{},g=c.options.labels,u=g.align,k=v.Side[c.side],d=b.tickmarkOffset,r=c.tickPositions,q=this.pos-d;r=B(r[b.index+1])?r[b.index+1]-d:c.max+d;var t=c.tickSize("tick");d=t?t[0]: +0;t=t?t[1]/2:0;if(!0===m.enabled){if("top"===k){m=c.top+c.offset;var f=m-d}else"bottom"===k?(f=e.chartHeight-c.bottom+c.offset,m=f+d):(m=c.top+c.len-c.translate(h?r:q),f=c.top+c.len-c.translate(h?q:r));"right"===k?(k=e.chartWidth-c.right+c.offset,h=k+d):"left"===k?(h=c.left+c.offset,k=h-d):(k=Math.round(c.left+c.translate(h?r:q))-t,h=Math.round(c.left+c.translate(h?q:r))-t);this.slotWidth=h-k;b.pos.x="left"===u?k:"right"===u?h:k+(h-k)/2;b.pos.y=f+(m-f)/2;e=e.renderer.fontMetrics(g.style.fontSize, +a.element);a=a.getBBox().height;g.useHTML?b.pos.y+=e.b+-(a/2):(a=Math.round(a/e.h),b.pos.y+=(e.b-(e.h-e.f))/2+-((a-1)*e.h/2));b.pos.x+=c.horiz&&g.x||0}});var I=function(){function b(a){this.axis=a}b.prototype.isOuterAxis=function(){var a=this.axis,c=a.grid.columnIndex,b=a.linkedParent&&a.linkedParent.grid.columns||a.grid.columns,e=c?a.linkedParent:a,d=-1,g=0;a.chart[a.coll].forEach(function(c,b){c.side!==a.side||c.options.isInternal||(g=b,c===e&&(d=b))});return g===d&&(B(c)?b.length===c:!0)};return b}(), +v=function(){function b(){}b.compose=function(a){d.keepProps.push("grid");D(a.prototype,"unsquish",b.wrapUnsquish);f(a,"init",b.onInit);f(a,"afterGetOffset",b.onAfterGetOffset);f(a,"afterGetTitlePosition",b.onAfterGetTitlePosition);f(a,"afterInit",b.onAfterInit);f(a,"afterRender",b.onAfterRender);f(a,"afterSetAxisTranslation",b.onAfterSetAxisTranslation);f(a,"afterSetOptions",b.onAfterSetOptions);f(a,"afterSetOptions",b.onAfterSetOptions2);f(a,"afterSetScale",b.onAfterSetScale);f(a,"afterTickSize", +b.onAfterTickSize);f(a,"trimTicks",b.onTrimTicks);f(a,"destroy",b.onDestroy)};b.onAfterGetOffset=function(){var a=this.grid;(a&&a.columns||[]).forEach(function(a){a.getOffset()})};b.onAfterGetTitlePosition=function(a){if(!0===(this.options.grid||{}).enabled){var c=this.axisTitle,h=this.height,e=this.horiz,d=this.left,g=this.offset,u=this.opposite,k=this.options.title,f=void 0===k?{}:k;k=this.top;var r=this.width,q=this.tickSize(),t=c&&c.getBBox().width,l=f.x||0,n=f.y||0,p=y(f.margin,e?5:10);c=this.chart.renderer.fontMetrics(f.style&& +f.style.fontSize,c).f;q=(e?k+h:d)+(e?1:-1)*(u?-1:1)*(q?q[0]/2:0)+(this.side===b.Side.bottom?c:0);a.titlePosition.x=e?d-t/2-p+l:q+(u?r:0)+g+l;a.titlePosition.y=e?q-(u?h:0)+(u?c:-c)/2+g+n:k-p+n}};b.onAfterInit=function(){var a=this.chart,c=this.options.grid;c=void 0===c?{}:c;var b=this.userOptions;c.enabled&&(H(this),D(this,"labelFormatter",function(a){var c=this.axis,b=this.value,e=c.tickPositions,d=(c.isLinked?c.linkedParent:c).series[0],h=b===e[0];e=b===e[e.length-1];d=d&&E(d.options.data,function(a){return a[c.isXAxis? +"x":"y"]===b});this.isFirst=h;this.isLast=e;this.point=d;return a.call(this)}));if(c.columns)for(var e=this.grid.columns=[],m=this.grid.columnIndex=0;++mg&&!a.startOnTick&&(b[0]=g),f> +l&&f-k} + * @apioption xAxis.grid.columns + */ + /** + * Set border color for the label grid lines. + * + * @type {Highcharts.ColorString} + * @apioption xAxis.grid.borderColor + */ + /** + * Set border width of the label grid lines. + * + * @type {number} + * @default 1 + * @apioption xAxis.grid.borderWidth + */ + /** + * Set cell height for grid axis labels. By default this is calculated from font + * size. This option only applies to horizontal axes. + * + * @sample gantt/grid-axis/cellheight + * Gant chart with custom cell height + * @type {number} + * @apioption xAxis.grid.cellHeight + */ + ''; // detach doclets above + /** + * Get the largest label width and height. + * + * @private + * @function Highcharts.Axis#getMaxLabelDimensions + * + * @param {Highcharts.Dictionary} ticks + * All the ticks on one axis. + * + * @param {Array} tickPositions + * All the tick positions on one axis. + * + * @return {Highcharts.SizeObject} + * Object containing the properties height and width. + * + * @todo Move this to the generic axis implementation, as it is used there. + */ + Axis.prototype.getMaxLabelDimensions = function (ticks, tickPositions) { + var dimensions = { + width: 0, + height: 0 + }; + tickPositions.forEach(function (pos) { + var tick = ticks[pos], + tickHeight = 0, + tickWidth = 0, + label; + if (isObject(tick)) { + label = isObject(tick.label) ? tick.label : {}; + // Find width and height of tick + tickHeight = label.getBBox ? label.getBBox().height : 0; + if (label.textStr) { + // Set the tickWidth same as the label width after ellipsis + // applied #10281 + tickWidth = Math.round(label.getBBox().width); + } + // Update the result if width and/or height are larger + dimensions.height = Math.max(tickHeight, dimensions.height); + dimensions.width = Math.max(tickWidth, dimensions.width); + } + }); + return dimensions; + }; + // Adds week date format + H.dateFormats.W = function (timestamp) { + var d = new this.Date(timestamp); + var firstDay = (this.get('Day', + d) + 6) % 7; + var thursday = new this.Date(d.valueOf()); + this.set('Date', thursday, this.get('Date', d) - firstDay + 3); + var firstThursday = new this.Date(this.get('FullYear', + thursday), 0, 1); + if (this.get('Day', firstThursday) !== 4) { + this.set('Month', d, 0); + this.set('Date', d, 1 + (11 - this.get('Day', firstThursday)) % 7); + } + return (1 + + Math.floor((thursday.valueOf() - firstThursday.valueOf()) / 604800000)).toString(); + }; + // First letter of the day of the week, e.g. 'M' for 'Monday'. + H.dateFormats.E = function (timestamp) { + return dateFormat('%a', timestamp, true).charAt(0); + }; + /* eslint-disable no-invalid-this */ + addEvent(Chart, 'afterSetChartSize', function () { + this.axes.forEach(function (axis) { + (axis.grid && axis.grid.columns || []).forEach(function (column) { + column.setAxisSize(); + column.setAxisTranslation(); + }); + }); + }); + // Center tick labels in cells. + addEvent(Tick, 'afterGetLabelPosition', function (e) { + var tick = this, + label = tick.label, + axis = tick.axis, + reversed = axis.reversed, + chart = axis.chart, + options = axis.options, + gridOptions = options.grid || {}, + labelOpts = axis.options.labels, + align = labelOpts.align, + // verticalAlign is currently not supported for axis.labels. + verticalAlign = 'middle', // labelOpts.verticalAlign, + side = GridAxis.Side[axis.side], + tickmarkOffset = e.tickmarkOffset, + tickPositions = axis.tickPositions, + tickPos = tick.pos - tickmarkOffset, + nextTickPos = (isNumber(tickPositions[e.index + 1]) ? + tickPositions[e.index + 1] - tickmarkOffset : + axis.max + tickmarkOffset), + tickSize = axis.tickSize('tick'), + tickWidth = tickSize ? tickSize[0] : 0, + crispCorr = tickSize ? tickSize[1] / 2 : 0, + labelHeight, + lblMetrics, + lines, + bottom, + top, + left, + right; + // Only center tick labels in grid axes + if (gridOptions.enabled === true) { + // Calculate top and bottom positions of the cell. + if (side === 'top') { + bottom = axis.top + axis.offset; + top = bottom - tickWidth; + } + else if (side === 'bottom') { + top = chart.chartHeight - axis.bottom + axis.offset; + bottom = top + tickWidth; + } + else { + bottom = axis.top + axis.len - axis.translate(reversed ? nextTickPos : tickPos); + top = axis.top + axis.len - axis.translate(reversed ? tickPos : nextTickPos); + } + // Calculate left and right positions of the cell. + if (side === 'right') { + left = chart.chartWidth - axis.right + axis.offset; + right = left + tickWidth; + } + else if (side === 'left') { + right = axis.left + axis.offset; + left = right - tickWidth; + } + else { + left = Math.round(axis.left + axis.translate(reversed ? nextTickPos : tickPos)) - crispCorr; + right = Math.round(axis.left + axis.translate(reversed ? tickPos : nextTickPos)) - crispCorr; + } + tick.slotWidth = right - left; + // Calculate the positioning of the label based on + // alignment. + e.pos.x = (align === 'left' ? + left : + align === 'right' ? + right : + left + ((right - left) / 2) // default to center + ); + e.pos.y = (verticalAlign === 'top' ? + top : + verticalAlign === 'bottom' ? + bottom : + top + ((bottom - top) / 2) // default to middle + ); + lblMetrics = chart.renderer.fontMetrics(labelOpts.style.fontSize, label.element); + labelHeight = label.getBBox().height; + // Adjustment to y position to align the label correctly. + // Would be better to have a setter or similar for this. + if (!labelOpts.useHTML) { + lines = Math.round(labelHeight / lblMetrics.h); + e.pos.y += ( + // Center the label + // TODO: why does this actually center the label? + ((lblMetrics.b - (lblMetrics.h - lblMetrics.f)) / 2) + + // Adjust for height of additional lines. + -(((lines - 1) * lblMetrics.h) / 2)); + } + else { + e.pos.y += ( + // Readjust yCorr in htmlUpdateTransform + lblMetrics.b + + // Adjust for height of html label + -(labelHeight / 2)); + } + e.pos.x += (axis.horiz && labelOpts.x || 0); + } + }); + /* eslint-enable no-invalid-this */ + /** + * Additions for grid axes. + * @private + * @class + */ + var GridAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function GridAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Checks if an axis is the outer axis in its dimension. Since + * axes are placed outwards in order, the axis with the highest + * index is the outermost axis. + * + * Example: If there are multiple x-axes at the top of the chart, + * this function returns true if the axis supplied is the last + * of the x-axes. + * + * @private + * + * @return {boolean} + * True if the axis is the outermost axis in its dimension; false if + * not. + */ + GridAxisAdditions.prototype.isOuterAxis = function () { + var axis = this.axis; + var chart = axis.chart; + var columnIndex = axis.grid.columnIndex; + var columns = (axis.linkedParent && axis.linkedParent.grid.columns || + axis.grid.columns); + var parentAxis = columnIndex ? axis.linkedParent : axis; + var thisIndex = -1, + lastIndex = 0; + chart[axis.coll].forEach(function (otherAxis, index) { + if (otherAxis.side === axis.side && !otherAxis.options.isInternal) { + lastIndex = index; + if (otherAxis === parentAxis) { + // Get the index of the axis in question + thisIndex = index; + } + } + }); + return (lastIndex === thisIndex && + (isNumber(columnIndex) ? columns.length === columnIndex : true)); + }; + return GridAxisAdditions; + }()); + /** + * Axis with grid support. + * @private + * @class + */ + var GridAxis = /** @class */ (function () { + function GridAxis() { + } + /* * + * + * Static Functions + * + * */ + /* eslint-disable valid-jsdoc */ + /** + * Extends axis class with grid support. + * @private + */ + GridAxis.compose = function (AxisClass) { + Axis.keepProps.push('grid'); + wrap(AxisClass.prototype, 'unsquish', GridAxis.wrapUnsquish); + // Add event handlers + addEvent(AxisClass, 'init', GridAxis.onInit); + addEvent(AxisClass, 'afterGetOffset', GridAxis.onAfterGetOffset); + addEvent(AxisClass, 'afterGetTitlePosition', GridAxis.onAfterGetTitlePosition); + addEvent(AxisClass, 'afterInit', GridAxis.onAfterInit); + addEvent(AxisClass, 'afterRender', GridAxis.onAfterRender); + addEvent(AxisClass, 'afterSetAxisTranslation', GridAxis.onAfterSetAxisTranslation); + addEvent(AxisClass, 'afterSetOptions', GridAxis.onAfterSetOptions); + addEvent(AxisClass, 'afterSetOptions', GridAxis.onAfterSetOptions2); + addEvent(AxisClass, 'afterSetScale', GridAxis.onAfterSetScale); + addEvent(AxisClass, 'afterTickSize', GridAxis.onAfterTickSize); + addEvent(AxisClass, 'trimTicks', GridAxis.onTrimTicks); + addEvent(AxisClass, 'destroy', GridAxis.onDestroy); + }; + /** + * Handle columns and getOffset. + * @private + */ + GridAxis.onAfterGetOffset = function () { + var grid = this.grid; + (grid && grid.columns || []).forEach(function (column) { + column.getOffset(); + }); + }; + /** + * @private + */ + GridAxis.onAfterGetTitlePosition = function (e) { + var axis = this; + var options = axis.options; + var gridOptions = options.grid || {}; + if (gridOptions.enabled === true) { + // compute anchor points for each of the title align options + var title = axis.axisTitle, + axisHeight = axis.height, + horiz = axis.horiz, + axisLeft = axis.left, + offset = axis.offset, + opposite = axis.opposite, + _a = axis.options.title, + axisTitleOptions = _a === void 0 ? {} : _a, + axisTop = axis.top, + axisWidth = axis.width; + var tickSize = axis.tickSize(); + var titleWidth = title && title.getBBox().width; + var xOption = axisTitleOptions.x || 0; + var yOption = axisTitleOptions.y || 0; + var titleMargin = pick(axisTitleOptions.margin, + horiz ? 5 : 10); + var titleFontSize = axis.chart.renderer.fontMetrics(axisTitleOptions.style && + axisTitleOptions.style.fontSize, + title).f; + var crispCorr = tickSize ? tickSize[0] / 2 : 0; + // TODO account for alignment + // the position in the perpendicular direction of the axis + var offAxis = ((horiz ? axisTop + axisHeight : axisLeft) + + (horiz ? 1 : -1) * // horizontal axis reverses the margin + (opposite ? -1 : 1) * // so does opposite axes + crispCorr + + (axis.side === GridAxis.Side.bottom ? titleFontSize : 0)); + e.titlePosition.x = horiz ? + axisLeft - titleWidth / 2 - titleMargin + xOption : + offAxis + (opposite ? axisWidth : 0) + offset + xOption; + e.titlePosition.y = horiz ? + (offAxis - + (opposite ? axisHeight : 0) + + (opposite ? titleFontSize : -titleFontSize) / 2 + + offset + + yOption) : + axisTop - titleMargin + yOption; + } + }; + /** + * @private + */ + GridAxis.onAfterInit = function () { + var axis = this; + var chart = axis.chart, + _a = axis.options.grid, + gridOptions = _a === void 0 ? {} : _a, + userOptions = axis.userOptions; + if (gridOptions.enabled) { + applyGridOptions(axis); + /* eslint-disable no-invalid-this */ + // TODO: wrap the axis instead + wrap(axis, 'labelFormatter', function (proceed) { + var _a = this, + axis = _a.axis, + value = _a.value; + var tickPos = axis.tickPositions; + var series = (axis.isLinked ? + axis.linkedParent : + axis).series[0]; + var isFirst = value === tickPos[0]; + var isLast = value === tickPos[tickPos.length - 1]; + var point = series && find(series.options.data, + function (p) { + return p[axis.isXAxis ? 'x' : 'y'] === value; + }); + // Make additional properties available for the + // formatter + this.isFirst = isFirst; + this.isLast = isLast; + this.point = point; + // Call original labelFormatter + return proceed.call(this); + }); + /* eslint-enable no-invalid-this */ + } + if (gridOptions.columns) { + var columns = axis.grid.columns = [], + columnIndex = axis.grid.columnIndex = 0; + // Handle columns, each column is a grid axis + while (++columnIndex < gridOptions.columns.length) { + var columnOptions = merge(userOptions, + gridOptions.columns[gridOptions.columns.length - columnIndex - 1], { + linkedTo: 0, + // Force to behave like category axis + type: 'category', + // Disable by default the scrollbar on the grid axis + scrollbar: { + enabled: false + } + }); + delete columnOptions.grid.columns; // Prevent recursion + var column = new Axis(axis.chart, + columnOptions); + column.grid.isColumn = true; + column.grid.columnIndex = columnIndex; + // Remove column axis from chart axes array, and place it + // in the columns array. + erase(chart.axes, column); + erase(chart[axis.coll], column); + columns.push(column); + } + } + }; + /** + * Draw an extra line on the far side of the outermost axis, + * creating floor/roof/wall of a grid. And some padding. + * ``` + * Make this: + * (axis.min) __________________________ (axis.max) + * | | | | | + * Into this: + * (axis.min) __________________________ (axis.max) + * ___|____|____|____|____|__ + * ``` + * @private + */ + GridAxis.onAfterRender = function () { + var axis = this; + var grid = axis.grid; + var options = axis.options; + var renderer = axis.chart.renderer; + var gridOptions = options.grid || {}; + var yStartIndex, + yEndIndex, + xStartIndex, + xEndIndex; + if (gridOptions.enabled === true) { + // @todo acutual label padding (top, bottom, left, right) + axis.maxLabelDimensions = axis.getMaxLabelDimensions(axis.ticks, axis.tickPositions); + // Remove right wall before rendering if updating + if (axis.rightWall) { + axis.rightWall.destroy(); + } + /* + Draw an extra axis line on outer axes + > + Make this: |______|______|______|___ + + > _________________________ + Into this: |______|______|______|__| + */ + if (axis.grid && axis.grid.isOuterAxis() && axis.axisLine) { + var lineWidth = options.lineWidth; + if (lineWidth) { + var linePath = axis.getLinePath(lineWidth); + var startPoint = linePath[0]; + var endPoint = linePath[1]; + // Negate distance if top or left axis + // Subtract 1px to draw the line at the end of the tick + var tickLength = (axis.tickSize('tick') || [1])[0]; + var distance = (tickLength - 1) * ((axis.side === GridAxis.Side.top || + axis.side === GridAxis.Side.left) ? -1 : 1); + // If axis is horizontal, reposition line path vertically + if (startPoint[0] === 'M' && endPoint[0] === 'L') { + if (axis.horiz) { + startPoint[2] += distance; + endPoint[2] += distance; + } + else { + // If axis is vertical, reposition line path + // horizontally + startPoint[1] += distance; + endPoint[1] += distance; + } + } + if (!axis.grid.axisLineExtra) { + axis.grid.axisLineExtra = renderer + .path(linePath) + .attr({ + zIndex: 7 + }) + .addClass('highcharts-axis-line') + .add(axis.axisGroup); + if (!renderer.styledMode) { + axis.grid.axisLineExtra.attr({ + stroke: options.lineColor, + 'stroke-width': lineWidth + }); + } + } + else { + axis.grid.axisLineExtra.animate({ + d: linePath + }); + } + // show or hide the line depending on + // options.showEmpty + axis.axisLine[axis.showAxis ? 'show' : 'hide'](true); + } + } + (grid && grid.columns || []).forEach(function (column) { + column.render(); + }); + } + }; + /** + * @private + */ + GridAxis.onAfterSetAxisTranslation = function () { + var axis = this; + var tickInfo = axis.tickPositions && axis.tickPositions.info; + var options = axis.options; + var gridOptions = options.grid || {}; + var userLabels = axis.userOptions.labels || {}; + if (axis.horiz) { + if (gridOptions.enabled === true) { + axis.series.forEach(function (series) { + series.options.pointRange = 0; + }); + } + // Lower level time ticks, like hours or minutes, represent + // points in time and not ranges. These should be aligned + // left in the grid cell by default. The same applies to + // years of higher order. + if (tickInfo && + options.dateTimeLabelFormats && + options.labels && + !defined(userLabels.align) && + (options.dateTimeLabelFormats[tickInfo.unitName].range === false || + tickInfo.count > 1 // years + )) { + options.labels.align = 'left'; + if (!defined(userLabels.x)) { + options.labels.x = 3; + } + } + } + }; + /** + * Creates a left and right wall on horizontal axes: + * - Places leftmost tick at the start of the axis, to create a left + * wall + * - Ensures that the rightmost tick is at the end of the axis, to + * create a right wall. + * @private + */ + GridAxis.onAfterSetOptions = function (e) { + var options = this.options, + userOptions = e.userOptions, + gridAxisOptions, + gridOptions = ((options && isObject(options.grid)) ? options.grid : {}); + if (gridOptions.enabled === true) { + // Merge the user options into default grid axis options so + // that when a user option is set, it takes presedence. + gridAxisOptions = merge(true, { + className: ('highcharts-grid-axis ' + (userOptions.className || '')), + dateTimeLabelFormats: { + hour: { + list: ['%H:%M', '%H'] + }, + day: { + list: ['%A, %e. %B', '%a, %e. %b', '%E'] + }, + week: { + list: ['Week %W', 'W%W'] + }, + month: { + list: ['%B', '%b', '%o'] + } + }, + grid: { + borderWidth: 1 + }, + labels: { + padding: 2, + style: { + fontSize: '13px' + } + }, + margin: 0, + title: { + text: null, + reserveSpace: false, + rotation: 0 + }, + // In a grid axis, only allow one unit of certain types, + // for example we shouln't have one grid cell spanning + // two days. + units: [[ + 'millisecond', + [1, 10, 100] + ], [ + 'second', + [1, 10] + ], [ + 'minute', + [1, 5, 15] + ], [ + 'hour', + [1, 6] + ], [ + 'day', + [1] + ], [ + 'week', + [1] + ], [ + 'month', + [1] + ], [ + 'year', + null + ]] + }, userOptions); + // X-axis specific options + if (this.coll === 'xAxis') { + // For linked axes, tickPixelInterval is used only if + // the tickPositioner below doesn't run or returns + // undefined (like multiple years) + if (defined(userOptions.linkedTo) && + !defined(userOptions.tickPixelInterval)) { + gridAxisOptions.tickPixelInterval = 350; + } + // For the secondary grid axis, use the primary axis' + // tick intervals and return ticks one level higher. + if ( + // Check for tick pixel interval in options + !defined(userOptions.tickPixelInterval) && + // Only for linked axes + defined(userOptions.linkedTo) && + !defined(userOptions.tickPositioner) && + !defined(userOptions.tickInterval)) { + gridAxisOptions.tickPositioner = function (min, max) { + var parentInfo = (this.linkedParent && + this.linkedParent.tickPositions && + this.linkedParent.tickPositions.info); + if (parentInfo) { + var unitIdx, + count, + unitName, + i, + units = gridAxisOptions.units, + unitRange; + for (i = 0; i < units.length; i++) { + if (units[i][0] === + parentInfo.unitName) { + unitIdx = i; + break; + } + } + // Get the first allowed count on the next + // unit. + if (units[unitIdx + 1]) { + unitName = units[unitIdx + 1][0]; + count = + (units[unitIdx + 1][1] || [1])[0]; + // In case the base X axis shows years, make + // the secondary axis show ten times the + // years (#11427) + } + else if (parentInfo.unitName === 'year') { + unitName = 'year'; + count = parentInfo.count * 10; + } + unitRange = timeUnits[unitName]; + this.tickInterval = unitRange * count; + return this.getTimeTicks({ + unitRange: unitRange, + count: count, + unitName: unitName + }, min, max, this.options.startOfWeek); + } + }; + } + } + // Now merge the combined options into the axis options + merge(true, this.options, gridAxisOptions); + if (this.horiz) { + /* _________________________ + Make this: ___|_____|_____|_____|__| + ^ ^ + _________________________ + Into this: |_____|_____|_____|_____| + ^ ^ */ + options.minPadding = pick(userOptions.minPadding, 0); + options.maxPadding = pick(userOptions.maxPadding, 0); + } + // If borderWidth is set, then use its value for tick and + // line width. + if (isNumber(options.grid.borderWidth)) { + options.tickWidth = options.lineWidth = gridOptions.borderWidth; + } + } + }; + /** + * @private + */ + GridAxis.onAfterSetOptions2 = function (e) { + var axis = this; + var userOptions = e.userOptions; + var gridOptions = userOptions && userOptions.grid || {}; + var columns = gridOptions.columns; + // Add column options to the parent axis. Children has their column + // options set on init in onGridAxisAfterInit. + if (gridOptions.enabled && columns) { + merge(true, axis.options, columns[columns.length - 1]); + } + }; + /** + * Handle columns and setScale. + * @private + */ + GridAxis.onAfterSetScale = function () { + var axis = this; + (axis.grid.columns || []).forEach(function (column) { + column.setScale(); + }); + }; + /** + * Draw vertical axis ticks extra long to create cell floors and roofs. + * Overrides the tickLength for vertical axes. + * @private + */ + GridAxis.onAfterTickSize = function (e) { + var defaultLeftAxisOptions = Axis.defaultLeftAxisOptions; + var _a = this, + horiz = _a.horiz, + maxLabelDimensions = _a.maxLabelDimensions, + _b = _a.options.grid, + gridOptions = _b === void 0 ? {} : _b; + if (gridOptions.enabled && maxLabelDimensions) { + var labelPadding = (Math.abs(defaultLeftAxisOptions.labels.x) * 2); + var distance = horiz ? + gridOptions.cellHeight || labelPadding + maxLabelDimensions.height : + labelPadding + maxLabelDimensions.width; + if (isArray(e.tickSize)) { + e.tickSize[0] = distance; + } + else { + e.tickSize = [distance, 0]; + } + } + }; + /** + * @private + */ + GridAxis.onDestroy = function (e) { + var grid = this.grid; + (grid.columns || []).forEach(function (column) { + column.destroy(e.keepEvents); + }); + grid.columns = void 0; + }; + /** + * Wraps axis init to draw cell walls on vertical axes. + * @private + */ + GridAxis.onInit = function (e) { + var axis = this; + var userOptions = e.userOptions || {}; + var gridOptions = userOptions.grid || {}; + if (gridOptions.enabled && defined(gridOptions.borderColor)) { + userOptions.tickColor = userOptions.lineColor = gridOptions.borderColor; + } + if (!axis.grid) { + axis.grid = new GridAxisAdditions(axis); + } + }; + /** + * Makes tick labels which are usually ignored in a linked axis + * displayed if they are within range of linkedParent.min. + * ``` + * _____________________________ + * | | | | | + * Make this: | | 2 | 3 | 4 | + * |___|_______|_______|_______| + * ^ + * _____________________________ + * | | | | | + * Into this: | 1 | 2 | 3 | 4 | + * |___|_______|_______|_______| + * ^ + * ``` + * @private + * @todo Does this function do what the drawing says? Seems to affect + * ticks and not the labels directly? + */ + GridAxis.onTrimTicks = function () { + var axis = this; + var options = axis.options; + var gridOptions = options.grid || {}; + var categoryAxis = axis.categories; + var tickPositions = axis.tickPositions; + var firstPos = tickPositions[0]; + var lastPos = tickPositions[tickPositions.length - 1]; + var linkedMin = axis.linkedParent && axis.linkedParent.min; + var linkedMax = axis.linkedParent && axis.linkedParent.max; + var min = linkedMin || axis.min; + var max = linkedMax || axis.max; + var tickInterval = axis.tickInterval; + var endMoreThanMin = (firstPos < min && + firstPos + tickInterval > min); + var startLessThanMax = (lastPos > max && + lastPos - tickInterval < max); + if (gridOptions.enabled === true && + !categoryAxis && + (axis.horiz || axis.isLinked)) { + if (endMoreThanMin && !options.startOnTick) { + tickPositions[0] = min; + } + if (startLessThanMax && !options.endOnTick) { + tickPositions[tickPositions.length - 1] = max; + } + } + }; + /** + * Avoid altering tickInterval when reserving space. + * @private + */ + GridAxis.wrapUnsquish = function (proceed) { + var axis = this; + var _a = axis.options.grid, + gridOptions = _a === void 0 ? {} : _a; + if (gridOptions.enabled === true && axis.categories) { + return axis.tickInterval; + } + return proceed.apply(axis, argsToArray(arguments)); + }; + return GridAxis; + }()); + (function (GridAxis) { + /** + * Enum for which side the axis is on. Maps to axis.side. + * @private + */ + var Side; + (function (Side) { + Side[Side["top"] = 0] = "top"; + Side[Side["right"] = 1] = "right"; + Side[Side["bottom"] = 2] = "bottom"; + Side[Side["left"] = 3] = "left"; + })(Side = GridAxis.Side || (GridAxis.Side = {})); + })(GridAxis || (GridAxis = {})); + GridAxis.compose(Axis); + + return GridAxis; + }); + _registerModule(_modules, 'masters/modules/grid-axis.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/heatmap.js b/highcharts/modules/heatmap.js new file mode 100644 index 0000000..006800f --- /dev/null +++ b/highcharts/modules/heatmap.js @@ -0,0 +1,40 @@ +/* + Highmaps JS v8.2.0 (2020-08-20) + + (c) 2009-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/heatmap",["highcharts"],function(p){a(p);a.Highcharts=p;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function p(a,t,m,k){a.hasOwnProperty(t)||(a[t]=k.apply(null,m))}a=a?a._modules:{};p(a,"Mixins/ColorSeries.js",[a["Core/Globals.js"]],function(a){a.colorPointMixin={setVisible:function(a){var m=this,k=a?"show":"hide"; +m.visible=m.options.visible=!!a;["graphic","dataLabel"].forEach(function(a){if(m[a])m[a][k]()});this.series.buildKDTree()}};a.colorSeriesMixin={optionalAxis:"colorAxis",colorAxis:0,translateColors:function(){var a=this,m=this.options.nullColor,k=this.colorAxis,x=this.colorKey;(this.data.length?this.data:this.points).forEach(function(q){var v=q.getNestedProperty(x);(v=q.options.color||(q.isNull||null===q.value?m:k&&"undefined"!==typeof v?k.toColor(v,q):q.color||a.color))&&q.color!==v&&(q.color=v,"point"=== +a.options.legendType&&q.legendItem&&a.chart.legend.colorizeItem(q,q.visible))})}}});p(a,"Core/Axis/ColorAxis.js",[a["Core/Axis/Axis.js"],a["Core/Chart/Chart.js"],a["Core/Color.js"],a["Core/Globals.js"],a["Core/Legend.js"],a["Mixins/LegendSymbol.js"],a["Core/Series/Point.js"],a["Core/Utilities.js"]],function(a,t,m,k,y,q,v,r){var x=this&&this.__extends||function(){var c=function(b,d){c=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(d,b){d.__proto__=b}||function(d,b){for(var f in b)b.hasOwnProperty(f)&& +(d[f]=b[f])};return c(b,d)};return function(b,d){function e(){this.constructor=b}c(b,d);b.prototype=null===d?Object.create(d):(e.prototype=d.prototype,new e)}}(),p=m.parse,B=k.noop;m=r.addEvent;var u=r.erase,w=r.extend,c=r.Fx,g=r.isNumber,C=r.merge,A=r.pick,n=r.splat;"";var l=k.Series;r=k.colorPointMixin;w(l.prototype,k.colorSeriesMixin);w(v.prototype,r);t.prototype.collectionsWithUpdate.push("colorAxis");t.prototype.collectionsWithInit.colorAxis=[t.prototype.addColorAxis];var h=function(c){function b(d, +b){var e=c.call(this,d,b)||this;e.beforePadding=!1;e.chart=void 0;e.coll="colorAxis";e.dataClasses=void 0;e.legendItem=void 0;e.legendItems=void 0;e.name="";e.options=void 0;e.stops=void 0;e.visible=!0;e.init(d,b);return e}x(b,c);b.buildOptions=function(d,e,b){d=d.options.legend||{};var f=b.layout?"vertical"!==b.layout:"vertical"!==d.layout;return C(e,{side:f?2:1,reversed:!f},b,{opposite:!f,showEmpty:!1,title:null,visible:d.enabled&&(b?!1!==b.visible:!0)})};b.prototype.init=function(d,e){var D=b.buildOptions(d, +b.defaultOptions,e);this.coll="colorAxis";c.prototype.init.call(this,d,D);e.dataClasses&&this.initDataClasses(e);this.initStops();this.horiz=!D.opposite;this.zoomEnabled=!1};b.prototype.initDataClasses=function(d){var b=this.chart,c,f=0,a=b.options.chart.colorCount,g=this.options,l=d.dataClasses.length;this.dataClasses=c=[];this.legendItems=[];d.dataClasses.forEach(function(d,e){d=C(d);c.push(d);if(b.styledMode||!d.color)"category"===g.dataClassColor?(b.styledMode||(e=b.options.colors,a=e.length, +d.color=e[f]),d.colorIndex=f,f++,f===a&&(f=0)):d.color=p(g.minColor).tweenTo(p(g.maxColor),2>l?.5:e/(l-1))})};b.prototype.hasData=function(){return!!(this.tickPositions||[]).length};b.prototype.setTickPositions=function(){if(!this.dataClasses)return c.prototype.setTickPositions.call(this)};b.prototype.initStops=function(){this.stops=this.options.stops||[[0,this.options.minColor],[1,this.options.maxColor]];this.stops.forEach(function(d){d.color=p(d[1])})};b.prototype.setOptions=function(d){c.prototype.setOptions.call(this, +d);this.options.crosshair=this.options.marker};b.prototype.setAxisSize=function(){var d=this.legendSymbol,e=this.chart,c=e.options.legend||{},f,a;d?(this.left=c=d.attr("x"),this.top=f=d.attr("y"),this.width=a=d.attr("width"),this.height=d=d.attr("height"),this.right=e.chartWidth-c-a,this.bottom=e.chartHeight-f-d,this.len=this.horiz?a:d,this.pos=this.horiz?c:f):this.len=(this.horiz?c.symbolWidth:c.symbolHeight)||b.defaultLegendLength};b.prototype.normalizedValue=function(d){this.logarithmic&&(d=this.logarithmic.log2lin(d)); +return 1-(this.max-d)/(this.max-this.min||1)};b.prototype.toColor=function(d,b){var c=this.dataClasses,e=this.stops,a;if(c)for(a=c.length;a--;){var g=c[a];var l=g.from;e=g.to;if(("undefined"===typeof l||d>=l)&&("undefined"===typeof e||d<=e)){var h=g.color;b&&(b.dataClass=a,b.colorIndex=g.colorIndex);break}}else{d=this.normalizedValue(d);for(a=e.length;a--&&!(d>e[a][0]););l=e[a]||e[a+1];e=e[a+1]||l;d=1-(e[0]-d)/(e[0]-l[0]||1);h=l.color.tweenTo(e.color,d)}return h};b.prototype.getOffset=function(){var d= +this.legendGroup,b=this.chart.axisOffset[this.side];d&&(this.axisParent=d,c.prototype.getOffset.call(this),this.added||(this.added=!0,this.labelLeft=0,this.labelRight=this.width),this.chart.axisOffset[this.side]=b)};b.prototype.setLegendColor=function(){var d=this.reversed,b=d?1:0;d=d?0:1;b=this.horiz?[b,0,d,0]:[0,d,0,b];this.legendColor={linearGradient:{x1:b[0],y1:b[1],x2:b[2],y2:b[3]},stops:this.stops}};b.prototype.drawLegendSymbol=function(d,c){var e=d.padding,f=d.options,a=this.horiz,g=A(f.symbolWidth, +a?b.defaultLegendLength:12),l=A(f.symbolHeight,a?12:b.defaultLegendLength),h=A(f.labelPadding,a?16:30);f=A(f.itemDistance,10);this.setLegendColor();c.legendSymbol=this.chart.renderer.rect(0,d.baseline-11,g,l).attr({zIndex:1}).add(c.legendGroup);this.legendItemWidth=g+e+(a?f:h);this.legendItemHeight=l+e+(a?h:0)};b.prototype.setState=function(d){this.series.forEach(function(b){b.setState(d)})};b.prototype.setVisible=function(){};b.prototype.getSeriesExtremes=function(){var b=this.series,c=b.length, +a;this.dataMin=Infinity;for(this.dataMax=-Infinity;c--;){var f=b[c];var g=f.colorKey=A(f.options.colorKey,f.colorKey,f.pointValKey,f.zoneAxis,"y");var h=f.pointArrayMap;var z=f[g+"Min"]&&f[g+"Max"];if(f[g+"Data"])var n=f[g+"Data"];else if(h){n=[];h=h.indexOf(g);var k=f.yData;if(0<=h&&k)for(a=0;ag+l&&(h=g+l+2);e.plotX=h;e.plotY=this.len-h;c.prototype.drawCrosshair.call(this,b,e);e.plotX=d;e.plotY=a;this.cross&&!this.cross.addedToColorAxis&&this.legendGroup&& +(this.cross.addClass("highcharts-coloraxis-marker").add(this.legendGroup),this.cross.addedToColorAxis=!0,!this.chart.styledMode&&this.crosshair&&this.cross.attr({fill:this.crosshair.color}))}};b.prototype.getPlotLinePath=function(b){var d=this.left,a=b.translatedValue,f=this.top;return g(a)?this.horiz?[["M",a-4,f-6],["L",a+4,f-6],["L",a,f],["Z"]]:[["M",d,a],["L",d-6,a+6],["L",d-6,a-6],["Z"]]:c.prototype.getPlotLinePath.call(this,b)};b.prototype.update=function(d,a){var e=this.chart,g=e.legend,l=b.buildOptions(e, +{},d);this.series.forEach(function(b){b.isDirtyData=!0});(d.dataClasses&&g.allItems||this.dataClasses)&&this.destroyItems();e.options[this.coll]=C(this.userOptions,l);c.prototype.update.call(this,l,a);this.legendItem&&(this.setLegendColor(),g.colorizeItem(this,!0))};b.prototype.destroyItems=function(){var b=this.chart;this.legendItem?b.legend.destroyItem(this):this.legendItems&&this.legendItems.forEach(function(d){b.legend.destroyItem(d)});b.isDirtyLegend=!0};b.prototype.remove=function(b){this.destroyItems(); +c.prototype.remove.call(this,b)};b.prototype.getDataClassLegendSymbols=function(){var b=this,c=b.chart,a=b.legendItems,g=c.options.legend,l=g.valueDecimals,h=g.valueSuffix||"",n;a.length||b.dataClasses.forEach(function(d,g){var e=!0,f=d.from,z=d.to,k=c.numberFormatter;n="";"undefined"===typeof f?n="< ":"undefined"===typeof z&&(n="> ");"undefined"!==typeof f&&(n+=k(f,l)+h);"undefined"!==typeof f&&"undefined"!==typeof z&&(n+=" - ");"undefined"!==typeof z&&(n+=k(z,l)+h);a.push(w({chart:c,name:n,options:{}, +drawLegendSymbol:q.drawRectangle,visible:!0,setState:B,isDataClass:!0,setVisible:function(){e=b.visible=!e;b.series.forEach(function(b){b.points.forEach(function(b){b.dataClass===g&&b.setVisible(e)})});c.legend.colorizeItem(this,e)}},d))});return a};b.defaultLegendLength=200;b.defaultOptions={lineWidth:0,minPadding:0,maxPadding:0,gridLineWidth:1,tickPixelInterval:72,startOnTick:!0,endOnTick:!0,offset:0,marker:{animation:{duration:50},width:.01,color:"#999999"},labels:{overflow:"justify",rotation:0}, +minColor:"#e6ebf5",maxColor:"#003399",tickLength:5,showInLegend:!0};b.keepProps=["legendGroup","legendItemHeight","legendItemWidth","legendItem","legendSymbol"];return b}(a);Array.prototype.push.apply(a.keepProps,h.keepProps);k.ColorAxis=h;["fill","stroke"].forEach(function(a){c.prototype[a+"Setter"]=function(){this.elem.attr(a,p(this.start).tweenTo(p(this.end),this.pos),null,!0)}});m(t,"afterGetAxes",function(){var c=this,b=c.options;this.colorAxis=[];b.colorAxis&&(b.colorAxis=n(b.colorAxis),b.colorAxis.forEach(function(b, +a){b.index=a;new h(c,b)}))});m(l,"bindAxes",function(){var c=this.axisTypes;c?-1===c.indexOf("colorAxis")&&c.push("colorAxis"):this.axisTypes=["colorAxis"]});m(y,"afterGetAllItems",function(c){var b=[],d,a;(this.chart.colorAxis||[]).forEach(function(a){(d=a.options)&&d.showInLegend&&(d.dataClasses&&d.visible?b=b.concat(a.getDataClassLegendSymbols()):d.visible&&b.push(a),a.series.forEach(function(b){if(!b.options.showInLegend||d.dataClasses)"point"===b.options.legendType?b.points.forEach(function(b){u(c.allItems, +b)}):u(c.allItems,b)}))});for(a=b.length;a--;)c.allItems.unshift(b[a])});m(y,"afterColorizeItem",function(c){c.visible&&c.item.legendColor&&c.item.legendSymbol.attr({fill:c.item.legendColor})});m(y,"afterUpdate",function(){var c=this.chart.colorAxis;c&&c.forEach(function(b,c,a){b.update({},a)})});m(l,"afterTranslate",function(){(this.chart.colorAxis&&this.chart.colorAxis.length||this.colorAttribs)&&this.translateColors()});return h});p(a,"Mixins/ColorMapSeries.js",[a["Core/Globals.js"],a["Core/Series/Point.js"], +a["Core/Utilities.js"]],function(a,p,m){var k=m.defined;m=a.noop;var x=a.seriesTypes;a.colorMapPointMixin={dataLabelOnNull:!0,isValid:function(){return null!==this.value&&Infinity!==this.value&&-Infinity!==this.value},setState:function(a){p.prototype.setState.call(this,a);this.graphic&&this.graphic.attr({zIndex:"hover"===a?1:0})}};a.colorMapSeriesMixin={pointArrayMap:["value"],axisTypes:["xAxis","yAxis","colorAxis"],trackerGroups:["group","markerGroup","dataLabelsGroup"],getSymbol:m,parallelArrays:["x", +"y","value"],colorKey:"value",pointAttribs:x.column.prototype.pointAttribs,colorAttribs:function(a){var m={};k(a.color)&&(m[this.colorProp||"fill"]=a.color);return m}}});p(a,"Series/HeatmapSeries.js",[a["Core/Globals.js"],a["Mixins/LegendSymbol.js"],a["Core/Renderer/SVG/SVGRenderer.js"],a["Core/Utilities.js"]],function(a,p,m,k){var y=k.clamp,q=k.extend,v=k.fireEvent,r=k.isNumber,t=k.merge,x=k.pick;k=k.seriesType;"";var B=a.colorMapPointMixin,u=a.Series,w=m.prototype.symbols;k("heatmap","scatter", +{animation:!1,borderWidth:0,nullColor:"#f7f7f7",dataLabels:{formatter:function(){return this.point.value},inside:!0,verticalAlign:"middle",crop:!1,overflow:!1,padding:0},marker:{symbol:"rect",radius:0,lineColor:void 0,states:{hover:{lineWidthPlus:0},select:{}}},clip:!0,pointRange:null,tooltip:{pointFormat:"{point.x}, {point.y}: {point.value}
    "},states:{hover:{halo:!1,brightness:.2}}},t(a.colorMapSeriesMixin,{pointArrayMap:["y","value"],hasPointSpecificOptions:!0,getExtremesFromAll:!0,directTouch:!0, +init:function(){u.prototype.init.apply(this,arguments);var a=this.options;a.pointRange=x(a.pointRange,a.colsize||1);this.yAxis.axisPointRange=a.rowsize||1;q(w,{ellipse:w.circle,rect:w.square})},getSymbol:u.prototype.getSymbol,setClip:function(a){var c=this.chart;u.prototype.setClip.apply(this,arguments);(!1!==this.options.clip||a)&&this.markerGroup.clip((a||this.clipBox)&&this.sharedClipKey?c[this.sharedClipKey]:c.clipRect)},translate:function(){var a=this.options,g=a.marker&&a.marker.symbol||"", +k=w[g]?g:"rect";a=this.options;var m=-1!==["circle","square"].indexOf(k);this.generatePoints();this.points.forEach(function(a){var c=a.getCellAttributes(),h={x:Math.min(c.x1,c.x2),y:Math.min(c.y1,c.y2),width:Math.max(Math.abs(c.x2-c.x1),0),height:Math.max(Math.abs(c.y2-c.y1),0)};var n=a.hasImage=0===(a.marker&&a.marker.symbol||g||"").indexOf("url");if(m){var b=Math.abs(h.width-h.height);h.x=Math.min(c.x1,c.x2)+(h.width= from) && + (typeof to === 'undefined' || value <= to)) { + color = dataClass.color; + if (point) { + point.dataClass = i; + point.colorIndex = dataClass.colorIndex; + } + break; + } + } + } + else { + pos = axis.normalizedValue(value); + i = stops.length; + while (i--) { + if (pos > stops[i][0]) { + break; + } + } + from = stops[i] || stops[i + 1]; + to = stops[i + 1] || from; + // The position within the gradient + pos = 1 - (to[0] - pos) / ((to[0] - from[0]) || 1); + color = from.color.tweenTo(to.color, pos); + } + return color; + }; + /** + * Override the getOffset method to add the whole axis groups inside the + * legend. + * @private + */ + ColorAxis.prototype.getOffset = function () { + var axis = this; + var group = axis.legendGroup; + var sideOffset = axis.chart.axisOffset[axis.side]; + if (group) { + // Hook for the getOffset method to add groups to this parent + // group + axis.axisParent = group; + // Call the base + _super.prototype.getOffset.call(this); + // First time only + if (!axis.added) { + axis.added = true; + axis.labelLeft = 0; + axis.labelRight = axis.width; + } + // Reset it to avoid color axis reserving space + axis.chart.axisOffset[axis.side] = sideOffset; + } + }; + /** + * Create the color gradient. + * @private + */ + ColorAxis.prototype.setLegendColor = function () { + var axis = this; + var horiz = axis.horiz; + var reversed = axis.reversed; + var one = reversed ? 1 : 0; + var zero = reversed ? 0 : 1; + var grad = horiz ? [one, 0, + zero, 0] : [0, + zero, 0, + one]; // #3190 + axis.legendColor = { + linearGradient: { + x1: grad[0], + y1: grad[1], + x2: grad[2], + y2: grad[3] + }, + stops: axis.stops + }; + }; + /** + * The color axis appears inside the legend and has its own legend symbol. + * @private + */ + ColorAxis.prototype.drawLegendSymbol = function (legend, item) { + var axis = this; + var padding = legend.padding; + var legendOptions = legend.options; + var horiz = axis.horiz; + var width = pick(legendOptions.symbolWidth, + horiz ? ColorAxis.defaultLegendLength : 12); + var height = pick(legendOptions.symbolHeight, + horiz ? 12 : ColorAxis.defaultLegendLength); + var labelPadding = pick(legendOptions.labelPadding, + horiz ? 16 : 30); + var itemDistance = pick(legendOptions.itemDistance, 10); + this.setLegendColor(); + // Create the gradient + item.legendSymbol = this.chart.renderer.rect(0, legend.baseline - 11, width, height).attr({ + zIndex: 1 + }).add(item.legendGroup); + // Set how much space this legend item takes up + axis.legendItemWidth = width + padding + (horiz ? itemDistance : labelPadding); + axis.legendItemHeight = height + padding + (horiz ? labelPadding : 0); + }; + /** + * Fool the legend. + * @private + */ + ColorAxis.prototype.setState = function (state) { + this.series.forEach(function (series) { + series.setState(state); + }); + }; + /** + * @private + */ + ColorAxis.prototype.setVisible = function () { + }; + /** + * @private + */ + ColorAxis.prototype.getSeriesExtremes = function () { + var axis = this; + var series = axis.series; + var colorValArray, + colorKey, + colorValIndex, + pointArrayMap, + calculatedExtremes, + cSeries, + i = series.length, + yData, + j; + this.dataMin = Infinity; + this.dataMax = -Infinity; + while (i--) { // x, y, value, other + cSeries = series[i]; + colorKey = cSeries.colorKey = pick(cSeries.options.colorKey, cSeries.colorKey, cSeries.pointValKey, cSeries.zoneAxis, 'y'); + pointArrayMap = cSeries.pointArrayMap; + calculatedExtremes = cSeries[colorKey + 'Min'] && + cSeries[colorKey + 'Max']; + if (cSeries[colorKey + 'Data']) { + colorValArray = cSeries[colorKey + 'Data']; + } + else { + if (!pointArrayMap) { + colorValArray = cSeries.yData; + } + else { + colorValArray = []; + colorValIndex = pointArrayMap.indexOf(colorKey); + yData = cSeries.yData; + if (colorValIndex >= 0 && yData) { + for (j = 0; j < yData.length; j++) { + colorValArray.push(pick(yData[j][colorValIndex], yData[j])); + } + } + } + } + // If color key extremes are already calculated, use them. + if (calculatedExtremes) { + cSeries.minColorValue = cSeries[colorKey + 'Min']; + cSeries.maxColorValue = cSeries[colorKey + 'Max']; + } + else { + var cExtremes = Series.prototype.getExtremes.call(cSeries, + colorValArray); + cSeries.minColorValue = cExtremes.dataMin; + cSeries.maxColorValue = cExtremes.dataMax; + } + if (typeof cSeries.minColorValue !== 'undefined') { + this.dataMin = + Math.min(this.dataMin, cSeries.minColorValue); + this.dataMax = + Math.max(this.dataMax, cSeries.maxColorValue); + } + if (!calculatedExtremes) { + Series.prototype.applyExtremes.call(cSeries); + } + } + }; + /** + * Internal function to draw a crosshair. + * + * @function Highcharts.ColorAxis#drawCrosshair + * + * @param {Highcharts.PointerEventObject} [e] + * The event arguments from the modified pointer event, extended with + * `chartX` and `chartY` + * + * @param {Highcharts.Point} [point] + * The Point object if the crosshair snaps to points. + * + * @fires Highcharts.ColorAxis#event:afterDrawCrosshair + * @fires Highcharts.ColorAxis#event:drawCrosshair + */ + ColorAxis.prototype.drawCrosshair = function (e, point) { + var axis = this; + var plotX = point && point.plotX; + var plotY = point && point.plotY; + var axisPos = axis.pos; + var axisLen = axis.len; + var crossPos; + if (point) { + crossPos = axis.toPixels(point.getNestedProperty(point.series.colorKey)); + if (crossPos < axisPos) { + crossPos = axisPos - 2; + } + else if (crossPos > axisPos + axisLen) { + crossPos = axisPos + axisLen + 2; + } + point.plotX = crossPos; + point.plotY = axis.len - crossPos; + _super.prototype.drawCrosshair.call(this, e, point); + point.plotX = plotX; + point.plotY = plotY; + if (axis.cross && + !axis.cross.addedToColorAxis && + axis.legendGroup) { + axis.cross + .addClass('highcharts-coloraxis-marker') + .add(axis.legendGroup); + axis.cross.addedToColorAxis = true; + if (!axis.chart.styledMode && + axis.crosshair) { + axis.cross.attr({ + fill: axis.crosshair.color + }); + } + } + } + }; + /** + * @private + */ + ColorAxis.prototype.getPlotLinePath = function (options) { + var axis = this, + left = axis.left, + pos = options.translatedValue, + top = axis.top; + // crosshairs only + return isNumber(pos) ? // pos can be 0 (#3969) + (axis.horiz ? [ + ['M', pos - 4, top - 6], + ['L', pos + 4, top - 6], + ['L', pos, top], + ['Z'] + ] : [ + ['M', left, pos], + ['L', left - 6, pos + 6], + ['L', left - 6, pos - 6], + ['Z'] + ]) : + _super.prototype.getPlotLinePath.call(this, options); + }; + /** + * Updates a color axis instance with a new set of options. The options are + * merged with the existing options, so only new or altered options need to + * be specified. + * + * @function Highcharts.ColorAxis#update + * + * @param {Highcharts.ColorAxisOptions} newOptions + * The new options that will be merged in with existing options on the color + * axis. + * + * @param {boolean} [redraw] + * Whether to redraw the chart after the color axis is altered. If doing + * more operations on the chart, it is a good idea to set redraw to `false` + * and call {@link Highcharts.Chart#redraw} after. + */ + ColorAxis.prototype.update = function (newOptions, redraw) { + var axis = this, + chart = axis.chart, + legend = chart.legend, + updatedOptions = ColorAxis.buildOptions(chart, {}, + newOptions); + this.series.forEach(function (series) { + // Needed for Axis.update when choropleth colors change + series.isDirtyData = true; + }); + // When updating data classes, destroy old items and make sure new + // ones are created (#3207) + if (newOptions.dataClasses && legend.allItems || axis.dataClasses) { + axis.destroyItems(); + } + // Keep the options structure updated for export. Unlike xAxis and + // yAxis, the colorAxis is not an array. (#3207) + chart.options[axis.coll] = + merge(axis.userOptions, updatedOptions); + _super.prototype.update.call(this, updatedOptions, redraw); + if (axis.legendItem) { + axis.setLegendColor(); + legend.colorizeItem(this, true); + } + }; + /** + * Destroy color axis legend items. + * @private + */ + ColorAxis.prototype.destroyItems = function () { + var axis = this; + var chart = axis.chart; + if (axis.legendItem) { + chart.legend.destroyItem(axis); + } + else if (axis.legendItems) { + axis.legendItems.forEach(function (item) { + chart.legend.destroyItem(item); + }); + } + chart.isDirtyLegend = true; + }; + /** + * Removes the color axis and the related legend item. + * + * @function Highcharts.ColorAxis#remove + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart following the remove. + */ + ColorAxis.prototype.remove = function (redraw) { + this.destroyItems(); + _super.prototype.remove.call(this, redraw); + }; + /** + * Get the legend item symbols for data classes. + * @private + */ + ColorAxis.prototype.getDataClassLegendSymbols = function () { + var axis = this; + var chart = axis.chart; + var legendItems = axis.legendItems; + var legendOptions = chart.options.legend; + var valueDecimals = legendOptions.valueDecimals; + var valueSuffix = legendOptions.valueSuffix || ''; + var name; + if (!legendItems.length) { + axis.dataClasses.forEach(function (dataClass, i) { + var vis = true, + from = dataClass.from, + to = dataClass.to; + var numberFormatter = chart.numberFormatter; + // Assemble the default name. This can be overridden + // by legend.options.labelFormatter + name = ''; + if (typeof from === 'undefined') { + name = '< '; + } + else if (typeof to === 'undefined') { + name = '> '; + } + if (typeof from !== 'undefined') { + name += numberFormatter(from, valueDecimals) + valueSuffix; + } + if (typeof from !== 'undefined' && typeof to !== 'undefined') { + name += ' - '; + } + if (typeof to !== 'undefined') { + name += numberFormatter(to, valueDecimals) + valueSuffix; + } + // Add a mock object to the legend items + legendItems.push(extend({ + chart: chart, + name: name, + options: {}, + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + visible: true, + setState: noop, + isDataClass: true, + setVisible: function () { + vis = axis.visible = !vis; + axis.series.forEach(function (series) { + series.points.forEach(function (point) { + if (point.dataClass === i) { + point.setVisible(vis); + } + }); + }); + chart.legend.colorizeItem(this, vis); + } + }, dataClass)); + }); + } + return legendItems; + }; + /* * + * + * Static Functions + * + * */ + ColorAxis.defaultLegendLength = 200; + /** + * A color axis for series. Visually, the color + * axis will appear as a gradient or as separate items inside the + * legend, depending on whether the axis is scalar or based on data + * classes. + * + * For supported color formats, see the + * [docs article about colors](https://www.highcharts.com/docs/chart-design-and-style/colors). + * + * A scalar color axis is represented by a gradient. The colors either + * range between the [minColor](#colorAxis.minColor) and the + * [maxColor](#colorAxis.maxColor), or for more fine grained control the + * colors can be defined in [stops](#colorAxis.stops). Often times, the + * color axis needs to be adjusted to get the right color spread for the + * data. In addition to stops, consider using a logarithmic + * [axis type](#colorAxis.type), or setting [min](#colorAxis.min) and + * [max](#colorAxis.max) to avoid the colors being determined by + * outliers. + * + * When [dataClasses](#colorAxis.dataClasses) are used, the ranges are + * subdivided into separate classes like categories based on their + * values. This can be used for ranges between two values, but also for + * a true category. However, when your data is categorized, it may be as + * convenient to add each category to a separate series. + * + * Color axis does not work with: `sankey`, `sunburst`, `dependencywheel`, + * `networkgraph`, `wordcloud`, `venn`, `gauge` and `solidgauge` series + * types. + * + * Since v7.2.0 `colorAxis` can also be an array of options objects. + * + * See [the Axis object](/class-reference/Highcharts.Axis) for + * programmatic access to the axis. + * + * @sample {highcharts} highcharts/coloraxis/custom-color-key + * Column chart with color axis + * @sample {highcharts} highcharts/coloraxis/horizontal-layout + * Horizontal layout + * @sample {highmaps} maps/coloraxis/dataclasscolor + * With data classes + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor + * Min color and max color + * + * @extends xAxis + * @excluding alignTicks, allowDecimals, alternateGridColor, breaks, + * categories, crosshair, dateTimeLabelFormats, height, left, + * lineWidth, linkedTo, maxZoom, minRange, minTickInterval, + * offset, opposite, pane, plotBands, plotLines, + * reversedStacks, showEmpty, title, top, width, zoomEnabled + * @product highcharts highstock highmaps + * @type {*|Array<*>} + * @optionparent colorAxis + * @ignore + */ + ColorAxis.defaultOptions = { + /** + * Whether to allow decimals on the color axis. + * @type {boolean} + * @default true + * @product highcharts highstock highmaps + * @apioption colorAxis.allowDecimals + */ + /** + * Determines how to set each data class' color if no individual + * color is set. The default value, `tween`, computes intermediate + * colors between `minColor` and `maxColor`. The other possible + * value, `category`, pulls colors from the global or chart specific + * [colors](#colors) array. + * + * @sample {highmaps} maps/coloraxis/dataclasscolor/ + * Category colors + * + * @type {string} + * @default tween + * @product highcharts highstock highmaps + * @validvalue ["tween", "category"] + * @apioption colorAxis.dataClassColor + */ + /** + * An array of data classes or ranges for the choropleth map. If + * none given, the color axis is scalar and values are distributed + * as a gradient between the minimum and maximum colors. + * + * @sample {highmaps} maps/demo/data-class-ranges/ + * Multiple ranges + * + * @sample {highmaps} maps/demo/data-class-two-ranges/ + * Two ranges + * + * @type {Array<*>} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses + */ + /** + * The layout of the color axis. Can be `'horizontal'` or `'vertical'`. + * If none given, the color axis has the same layout as the legend. + * + * @sample highcharts/coloraxis/horizontal-layout/ + * Horizontal color axis layout with vertical legend + * + * @type {string|undefined} + * @since 7.2.0 + * @product highcharts highstock highmaps + * @apioption colorAxis.layout + */ + /** + * The color of each data class. If not set, the color is pulled + * from the global or chart-specific [colors](#colors) array. In + * styled mode, this option is ignored. Instead, use colors defined + * in CSS. + * + * @sample {highmaps} maps/demo/data-class-two-ranges/ + * Explicit colors + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.color + */ + /** + * The start of the value range that the data class represents, + * relating to the point value. + * + * The range of each `dataClass` is closed in both ends, but can be + * overridden by the next `dataClass`. + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.from + */ + /** + * The name of the data class as it appears in the legend. + * If no name is given, it is automatically created based on the + * `from` and `to` values. For full programmatic control, + * [legend.labelFormatter](#legend.labelFormatter) can be used. + * In the formatter, `this.from` and `this.to` can be accessed. + * + * @sample {highmaps} maps/coloraxis/dataclasses-name/ + * Named data classes + * + * @sample {highmaps} maps/coloraxis/dataclasses-labelformatter/ + * Formatted data classes + * + * @type {string} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.name + */ + /** + * The end of the value range that the data class represents, + * relating to the point value. + * + * The range of each `dataClass` is closed in both ends, but can be + * overridden by the next `dataClass`. + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.to + */ + /** @ignore-option */ + lineWidth: 0, + /** + * Padding of the min value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. + * + * @product highcharts highstock highmaps + */ + minPadding: 0, + /** + * The maximum value of the axis in terms of map point values. If + * `null`, the max value is automatically calculated. If the + * `endOnTick` option is true, the max value might be rounded up. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Explicit min and max to reduce the effect of outliers + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.max + */ + /** + * The minimum value of the axis in terms of map point values. If + * `null`, the min value is automatically calculated. If the + * `startOnTick` option is true, the min value might be rounded + * down. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Explicit min and max to reduce the effect of outliers + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.min + */ + /** + * Padding of the max value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. + * + * @product highcharts highstock highmaps + */ + maxPadding: 0, + /** + * Color of the grid lines extending from the axis across the + * gradient. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Grid lines demonstrated + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #e6e6e6 + * @product highcharts highstock highmaps + * @apioption colorAxis.gridLineColor + */ + /** + * The width of the grid lines extending from the axis across the + * gradient of a scalar color axis. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Grid lines demonstrated + * + * @product highcharts highstock highmaps + */ + gridLineWidth: 1, + /** + * The interval of the tick marks in axis units. When `null`, the + * tick interval is computed to approximately follow the + * `tickPixelInterval`. + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.tickInterval + */ + /** + * If [tickInterval](#colorAxis.tickInterval) is `null` this option + * sets the approximate pixel interval of the tick marks. + * + * @product highcharts highstock highmaps + */ + tickPixelInterval: 72, + /** + * Whether to force the axis to start on a tick. Use this option + * with the `maxPadding` option to control the axis start. + * + * @product highcharts highstock highmaps + */ + startOnTick: true, + /** + * Whether to force the axis to end on a tick. Use this option with + * the [maxPadding](#colorAxis.maxPadding) option to control the + * axis end. + * + * @product highcharts highstock highmaps + */ + endOnTick: true, + /** @ignore */ + offset: 0, + /** + * The triangular marker on a scalar color axis that points to the + * value of the hovered area. To disable the marker, set + * `marker: null`. + * + * @sample {highmaps} maps/coloraxis/marker/ + * Black marker + * + * @declare Highcharts.PointMarkerOptionsObject + * @product highcharts highstock highmaps + */ + marker: { + /** + * Animation for the marker as it moves between values. Set to + * `false` to disable animation. Defaults to `{ duration: 50 }`. + * + * @type {boolean|Partial} + * @product highcharts highstock highmaps + */ + animation: { + /** @internal */ + duration: 50 + }, + /** @internal */ + width: 0.01, + /** + * The color of the marker. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + */ + color: '#999999' + }, + /** + * The axis labels show the number for each tick. + * + * For more live examples on label options, see [xAxis.labels in the + * Highcharts API.](/highcharts#xAxis.labels) + * + * @extends xAxis.labels + * @product highcharts highstock highmaps + */ + labels: { + /** + * How to handle overflowing labels on horizontal color axis. If set + * to `"allow"`, it will not be aligned at all. By default it + * `"justify"` labels inside the chart area. If there is room to + * move it, it will be aligned to the edge, else it will be removed. + * + * @validvalue ["allow", "justify"] + * @product highcharts highstock highmaps + */ + overflow: 'justify', + rotation: 0 + }, + /** + * The color to represent the minimum of the color axis. Unless + * [dataClasses](#colorAxis.dataClasses) or + * [stops](#colorAxis.stops) are set, the gradient starts at this + * value. + * + * If dataClasses are set, the color is based on minColor and + * maxColor unless a color is set for each data class, or the + * [dataClassColor](#colorAxis.dataClassColor) is set. + * + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor/ + * Min and max colors on scalar (gradient) axis + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor-dataclasses/ + * On data classes + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + */ + minColor: '#e6ebf5', + /** + * The color to represent the maximum of the color axis. Unless + * [dataClasses](#colorAxis.dataClasses) or + * [stops](#colorAxis.stops) are set, the gradient ends at this + * value. + * + * If dataClasses are set, the color is based on minColor and + * maxColor unless a color is set for each data class, or the + * [dataClassColor](#colorAxis.dataClassColor) is set. + * + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor/ + * Min and max colors on scalar (gradient) axis + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor-dataclasses/ + * On data classes + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + */ + maxColor: '#003399', + /** + * Color stops for the gradient of a scalar color axis. Use this in + * cases where a linear gradient between a `minColor` and `maxColor` + * is not sufficient. The stops is an array of tuples, where the + * first item is a float between 0 and 1 assigning the relative + * position in the gradient, and the second item is the color. + * + * @sample {highmaps} maps/demo/heatmap/ + * Heatmap with three color stops + * + * @type {Array>} + * @product highcharts highstock highmaps + * @apioption colorAxis.stops + */ + /** + * The pixel length of the main tick marks on the color axis. + */ + tickLength: 5, + /** + * The type of interpolation to use for the color axis. Can be + * `linear` or `logarithmic`. + * + * @sample highcharts/coloraxis/logarithmic-with-emulate-negative-values/ + * Logarithmic color axis with extension to emulate negative + * values + * + * @type {Highcharts.ColorAxisTypeValue} + * @default linear + * @product highcharts highstock highmaps + * @apioption colorAxis.type + */ + /** + * Whether to reverse the axis so that the highest number is closest + * to the origin. Defaults to `false` in a horizontal legend and + * `true` in a vertical legend, where the smallest value starts on + * top. + * + * @type {boolean} + * @product highcharts highstock highmaps + * @apioption colorAxis.reversed + */ + /** + * @product highcharts highstock highmaps + * @excluding afterBreaks, pointBreak, pointInBreak + * @apioption colorAxis.events + */ + /** + * Fires when the legend item belonging to the colorAxis is clicked. + * One parameter, `event`, is passed to the function. + * + * @type {Function} + * @product highcharts highstock highmaps + * @apioption colorAxis.events.legendItemClick + */ + /** + * Whether to display the colorAxis in the legend. + * + * @sample highcharts/coloraxis/hidden-coloraxis-with-3d-chart/ + * Hidden color axis with 3d chart + * + * @see [heatmap.showInLegend](#series.heatmap.showInLegend) + * + * @since 4.2.7 + * @product highcharts highstock highmaps + */ + showInLegend: true + }; + /** + * @private + */ + ColorAxis.keepProps = [ + 'legendGroup', + 'legendItemHeight', + 'legendItemWidth', + 'legendItem', + 'legendSymbol' + ]; + return ColorAxis; + }(Axis)); + // Properties to preserve after destroy, for Axis.update (#5881, #6025). + Array.prototype.push.apply(Axis.keepProps, ColorAxis.keepProps); + H.ColorAxis = ColorAxis; + /** + * Handle animation of the color attributes directly + * + * @private + * @function Highcharts.Fx#fillSetter + */ /** + * Handle animation of the color attributes directly + * + * @private + * @function Highcharts.Fx#strokeSetter + */ + ['fill', 'stroke'].forEach(function (prop) { + Fx.prototype[prop + 'Setter'] = function () { + this.elem.attr(prop, color(this.start).tweenTo(color(this.end), this.pos), null, true); + }; + }); + // Extend the chart getAxes method to also get the color axis + addEvent(Chart, 'afterGetAxes', function () { + var chart = this, + options = chart.options; + this.colorAxis = []; + if (options.colorAxis) { + options.colorAxis = splat(options.colorAxis); + options.colorAxis.forEach(function (axisOptions, i) { + axisOptions.index = i; + new ColorAxis(chart, axisOptions); // eslint-disable-line no-new + }); + } + }); + // Add colorAxis to series axisTypes + addEvent(Series, 'bindAxes', function () { + var axisTypes = this.axisTypes; + if (!axisTypes) { + this.axisTypes = ['colorAxis']; + } + else if (axisTypes.indexOf('colorAxis') === -1) { + axisTypes.push('colorAxis'); + } + }); + // Add the color axis. This also removes the axis' own series to prevent + // them from showing up individually. + addEvent(Legend, 'afterGetAllItems', function (e) { + var colorAxisItems = [], + colorAxes = this.chart.colorAxis || [], + options, + i; + colorAxes.forEach(function (colorAxis) { + options = colorAxis.options; + if (options && options.showInLegend) { + // Data classes + if (options.dataClasses && options.visible) { + colorAxisItems = colorAxisItems.concat(colorAxis.getDataClassLegendSymbols()); + // Gradient legend + } + else if (options.visible) { + // Add this axis on top + colorAxisItems.push(colorAxis); + } + // If dataClasses are defined or showInLegend option is not set to + // true, do not add color axis' series to legend. + colorAxis.series.forEach(function (series) { + if (!series.options.showInLegend || options.dataClasses) { + if (series.options.legendType === 'point') { + series.points.forEach(function (point) { + erase(e.allItems, point); + }); + } + else { + erase(e.allItems, series); + } + } + }); + } + }); + i = colorAxisItems.length; + while (i--) { + e.allItems.unshift(colorAxisItems[i]); + } + }); + addEvent(Legend, 'afterColorizeItem', function (e) { + if (e.visible && e.item.legendColor) { + e.item.legendSymbol.attr({ + fill: e.item.legendColor + }); + } + }); + // Updates in the legend need to be reflected in the color axis (6888) + addEvent(Legend, 'afterUpdate', function () { + var colorAxes = this.chart.colorAxis; + if (colorAxes) { + colorAxes.forEach(function (colorAxis) { + colorAxis.update({}, arguments[2]); + }); + } + }); + // Calculate and set colors for points + addEvent(Series, 'afterTranslate', function () { + if (this.chart.colorAxis && + this.chart.colorAxis.length || + this.colorAttribs) { + this.translateColors(); + } + }); + + return ColorAxis; + }); + _registerModule(_modules, 'Mixins/ColorMapSeries.js', [_modules['Core/Globals.js'], _modules['Core/Series/Point.js'], _modules['Core/Utilities.js']], function (H, Point, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var defined = U.defined; + var noop = H.noop, + seriesTypes = H.seriesTypes; + /** + * Mixin for maps and heatmaps + * + * @private + * @mixin Highcharts.colorMapPointMixin + */ + H.colorMapPointMixin = { + dataLabelOnNull: true, + /* eslint-disable valid-jsdoc */ + /** + * Color points have a value option that determines whether or not it is + * a null point + * @private + * @function Highcharts.colorMapPointMixin.isValid + * @return {boolean} + */ + isValid: function () { + // undefined is allowed + return (this.value !== null && + this.value !== Infinity && + this.value !== -Infinity); + }, + /** + * @private + * @function Highcharts.colorMapPointMixin.setState + * @param {string} state + * @return {void} + */ + setState: function (state) { + Point.prototype.setState.call(this, state); + if (this.graphic) { + this.graphic.attr({ + zIndex: state === 'hover' ? 1 : 0 + }); + } + } + /* eslint-enable valid-jsdoc */ + }; + /** + * @private + * @mixin Highcharts.colorMapSeriesMixin + */ + H.colorMapSeriesMixin = { + pointArrayMap: ['value'], + axisTypes: ['xAxis', 'yAxis', 'colorAxis'], + trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'], + getSymbol: noop, + parallelArrays: ['x', 'y', 'value'], + colorKey: 'value', + pointAttribs: seriesTypes.column.prototype.pointAttribs, + /* eslint-disable valid-jsdoc */ + /** + * Get the color attibutes to apply on the graphic + * @private + * @function Highcharts.colorMapSeriesMixin.colorAttribs + * @param {Highcharts.Point} point + * @return {Highcharts.SVGAttributes} + */ + colorAttribs: function (point) { + var ret = {}; + if (defined(point.color)) { + ret[this.colorProp || 'fill'] = point.color; + } + return ret; + } + }; + + }); + _registerModule(_modules, 'Series/HeatmapSeries.js', [_modules['Core/Globals.js'], _modules['Mixins/LegendSymbol.js'], _modules['Core/Renderer/SVG/SVGRenderer.js'], _modules['Core/Utilities.js']], function (H, LegendSymbolMixin, SVGRenderer, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var clamp = U.clamp, + extend = U.extend, + fireEvent = U.fireEvent, + isNumber = U.isNumber, + merge = U.merge, + pick = U.pick, + seriesType = U.seriesType; + /* * + * @interface Highcharts.PointOptionsObject in parts/Point.ts + */ /** + * Heatmap series only. Point padding for a single point. + * @name Highcharts.PointOptionsObject#pointPadding + * @type {number|undefined} + */ /** + * Heatmap series only. The value of the point, resulting in a color controled + * by options as set in the colorAxis configuration. + * @name Highcharts.PointOptionsObject#value + * @type {number|null|undefined} + */ + ''; // detach doclets above + var colorMapPointMixin = H.colorMapPointMixin, + colorMapSeriesMixin = H.colorMapSeriesMixin, + noop = H.noop, + Series = H.Series, + seriesTypes = H.seriesTypes, + symbols = SVGRenderer.prototype.symbols; + /** + * @private + * @class + * @name Highcharts.seriesTypes.heatmap + * + * @augments Highcharts.Series + */ + seriesType('heatmap', 'scatter', + /** + * A heatmap is a graphical representation of data where the individual + * values contained in a matrix are represented as colors. + * + * @productdesc {highcharts} + * Requires `modules/heatmap`. + * + * @sample highcharts/demo/heatmap/ + * Simple heatmap + * @sample highcharts/demo/heatmap-canvas/ + * Heavy heatmap + * + * @extends plotOptions.scatter + * @excluding animationLimit, connectEnds, connectNulls, cropThreshold, + * dashStyle, findNearestPointBy, getExtremesFromAll, jitter, + * linecap, lineWidth, pointInterval, pointIntervalUnit, + * pointRange, pointStart, shadow, softThreshold, stacking, + * step, threshold, cluster + * @product highcharts highmaps + * @optionparent plotOptions.heatmap + */ + { + /** + * Animation is disabled by default on the heatmap series. + */ + animation: false, + /** + * The border width for each heat map item. + */ + borderWidth: 0, + /** + * Padding between the points in the heatmap. + * + * @type {number} + * @default 0 + * @since 6.0 + * @apioption plotOptions.heatmap.pointPadding + */ + /** + * @default value + * @apioption plotOptions.heatmap.colorKey + */ + /** + * The main color of the series. In heat maps this color is rarely used, + * as we mostly use the color to denote the value of each point. Unless + * options are set in the [colorAxis](#colorAxis), the default value + * is pulled from the [options.colors](#colors) array. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 4.0 + * @product highcharts + * @apioption plotOptions.heatmap.color + */ + /** + * The column size - how many X axis units each column in the heatmap + * should span. + * + * @sample {highcharts} maps/demo/heatmap/ + * One day + * @sample {highmaps} maps/demo/heatmap/ + * One day + * + * @type {number} + * @default 1 + * @since 4.0 + * @product highcharts highmaps + * @apioption plotOptions.heatmap.colsize + */ + /** + * The row size - how many Y axis units each heatmap row should span. + * + * @sample {highcharts} maps/demo/heatmap/ + * 1 by default + * @sample {highmaps} maps/demo/heatmap/ + * 1 by default + * + * @type {number} + * @default 1 + * @since 4.0 + * @product highcharts highmaps + * @apioption plotOptions.heatmap.rowsize + */ + /** + * The color applied to null points. In styled mode, a general CSS class + * is applied instead. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + nullColor: '#f7f7f7', + dataLabels: { + formatter: function () { + return this.point.value; + }, + inside: true, + verticalAlign: 'middle', + crop: false, + overflow: false, + padding: 0 // #3837 + }, + /** + * @excluding radius, enabledThreshold + * @since 8.1 + */ + marker: { + /** + * A predefined shape or symbol for the marker. When undefined, the + * symbol is pulled from options.symbols. Other possible values are + * `'circle'`, `'square'`,`'diamond'`, `'triangle'`, + * `'triangle-down'`, `'rect'`, and `'ellipse'`. + * + * Additionally, the URL to a graphic can be given on this form: + * `'url(graphic.png)'`. Note that for the image to be applied to + * exported charts, its URL needs to be accessible by the export + * server. + * + * Custom callbacks for symbol path generation can also be added to + * `Highcharts.SVGRenderer.prototype.symbols`. The callback is then + * used by its method name, as shown in the demo. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-symbol/ + * Predefined, graphic and custom markers + * @sample {highstock} highcharts/plotoptions/series-marker-symbol/ + * Predefined, graphic and custom markers + */ + symbol: 'rect', + /** @ignore-option */ + radius: 0, + lineColor: void 0, + states: { + /** + * @excluding radius, radiusPlus + */ + hover: { + /** + * Set the marker's fixed width on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.hover.width + */ + /** + * Set the marker's fixed height on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.hover.height + */ + /** + * The number of pixels to increase the width of the + * selected point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * 20px greater width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.hover.widthPlus + */ + /** + * The number of pixels to increase the height of the + * selected point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * 20px greater width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.hover.heightPlus + */ + /** + * The additional line width for a hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-linewidthplus + * 5 pixels wider lineWidth on hover + * @sample {highmaps} maps/plotoptions/heatmap-marker-states-hover-linewidthplus + * 5 pixels wider lineWidth on hover + */ + lineWidthPlus: 0 + }, + /** + * @excluding radius + */ + select: { + /** + * Set the marker's fixed width on select state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.select.width + */ + /** + * Set the marker's fixed height on select state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.select.height + */ + /** + * The number of pixels to increase the width of the + * selected point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * 20px greater width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.select.widthPlus + */ + /** + * The number of pixels to increase the height of the + * selected point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * 20px greater width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.select.heightPlus + */ + } + } + }, + clip: true, + /** @ignore-option */ + pointRange: null, + tooltip: { + pointFormat: '{point.x}, {point.y}: {point.value}
    ' + }, + states: { + hover: { + /** @ignore-option */ + halo: false, + /** + * How much to brighten the point on interaction. Requires the + * main color to be defined in hex or rgb(a) format. + * + * In styled mode, the hover brightening is by default replaced + * with a fill-opacity set in the `.highcharts-point:hover` + * rule. + */ + brightness: 0.2 + } + } + }, merge(colorMapSeriesMixin, { + pointArrayMap: ['y', 'value'], + hasPointSpecificOptions: true, + getExtremesFromAll: true, + directTouch: true, + /* eslint-disable valid-jsdoc */ + /** + * Override the init method to add point ranges on both axes. + * + * @private + * @function Highcharts.seriesTypes.heatmap#init + * @return {void} + */ + init: function () { + var options; + Series.prototype.init.apply(this, arguments); + options = this.options; + // #3758, prevent resetting in setData + options.pointRange = pick(options.pointRange, options.colsize || 1); + // general point range + this.yAxis.axisPointRange = options.rowsize || 1; + // Bind new symbol names + extend(symbols, { + ellipse: symbols.circle, + rect: symbols.square + }); + }, + getSymbol: Series.prototype.getSymbol, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#setClip + * @return {void} + */ + setClip: function (animation) { + var series = this, + chart = series.chart; + Series.prototype.setClip.apply(series, arguments); + if (series.options.clip !== false || animation) { + series.markerGroup + .clip((animation || series.clipBox) && series.sharedClipKey ? + chart[series.sharedClipKey] : + chart.clipRect); + } + }, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#translate + * @return {void} + */ + translate: function () { + var series = this, options = series.options, symbol = options.marker && options.marker.symbol || '', shape = symbols[symbol] ? symbol : 'rect', options = series.options, hasRegularShape = ['circle', 'square'].indexOf(shape) !== -1; + series.generatePoints(); + series.points.forEach(function (point) { + var pointAttr, + sizeDiff, + hasImage, + cellAttr = point.getCellAttributes(), + shapeArgs = { + x: Math.min(cellAttr.x1, + cellAttr.x2), + y: Math.min(cellAttr.y1, + cellAttr.y2), + width: Math.max(Math.abs(cellAttr.x2 - cellAttr.x1), 0), + height: Math.max(Math.abs(cellAttr.y2 - cellAttr.y1), 0) + }; + hasImage = point.hasImage = + (point.marker && point.marker.symbol || symbol || '') + .indexOf('url') === 0; + // If marker shape is regular (symetric), find shorter + // cell's side. + if (hasRegularShape) { + sizeDiff = Math.abs(shapeArgs.width - shapeArgs.height); + shapeArgs.x = Math.min(cellAttr.x1, cellAttr.x2) + + (shapeArgs.width < shapeArgs.height ? 0 : sizeDiff / 2); + shapeArgs.y = Math.min(cellAttr.y1, cellAttr.y2) + + (shapeArgs.width < shapeArgs.height ? sizeDiff / 2 : 0); + shapeArgs.width = shapeArgs.height = + Math.min(shapeArgs.width, shapeArgs.height); + } + pointAttr = { + plotX: (cellAttr.x1 + cellAttr.x2) / 2, + plotY: (cellAttr.y1 + cellAttr.y2) / 2, + clientX: (cellAttr.x1 + cellAttr.x2) / 2, + shapeType: 'path', + shapeArgs: merge(true, shapeArgs, { + d: symbols[shape](shapeArgs.x, shapeArgs.y, shapeArgs.width, shapeArgs.height) + }) + }; + if (hasImage) { + point.marker = { + width: shapeArgs.width, + height: shapeArgs.height + }; + } + extend(point, pointAttr); + }); + fireEvent(series, 'afterTranslate'); + }, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#pointAttribs + * @param {Highcharts.HeatmapPoint} point + * @param {string} state + * @return {Highcharts.SVGAttributes} + */ + pointAttribs: function (point, state) { + var series = this, + attr = Series.prototype.pointAttribs + .call(series, + point, + state), + seriesOptions = series.options || {}, + plotOptions = series.chart.options.plotOptions || {}, + seriesPlotOptions = plotOptions.series || {}, + heatmapPlotOptions = plotOptions.heatmap || {}, + stateOptions, + brightness, + // Get old properties in order to keep backward compatibility + borderColor = seriesOptions.borderColor || + heatmapPlotOptions.borderColor || + seriesPlotOptions.borderColor, + borderWidth = seriesOptions.borderWidth || + heatmapPlotOptions.borderWidth || + seriesPlotOptions.borderWidth || + attr['stroke-width']; + // Apply lineColor, or set it to default series color. + attr.stroke = ((point && point.marker && point.marker.lineColor) || + (seriesOptions.marker && seriesOptions.marker.lineColor) || + borderColor || + this.color); + // Apply old borderWidth property if exists. + attr['stroke-width'] = borderWidth; + if (state) { + stateOptions = + merge(seriesOptions.states[state], seriesOptions.marker && + seriesOptions.marker.states[state], point.options.states && + point.options.states[state] || {}); + brightness = stateOptions.brightness; + attr.fill = + stateOptions.color || + H.color(attr.fill).brighten(brightness || 0).get(); + attr.stroke = stateOptions.lineColor; + } + return attr; + }, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#markerAttribs + * @param {Highcharts.HeatmapPoint} point + * @return {Highcharts.SVGAttributes} + */ + markerAttribs: function (point, state) { + var pointMarkerOptions = point.marker || {}, + seriesMarkerOptions = this.options.marker || {}, + seriesStateOptions, + pointStateOptions, + shapeArgs = point.shapeArgs || {}, + hasImage = point.hasImage, + attribs = {}; + if (hasImage) { + return { + x: point.plotX, + y: point.plotY + }; + } + // Setting width and height attributes on image does not affect + // on its dimensions. + if (state) { + seriesStateOptions = seriesMarkerOptions.states[state] || {}; + pointStateOptions = pointMarkerOptions.states && + pointMarkerOptions.states[state] || {}; + [['width', 'x'], ['height', 'y']].forEach(function (dimension) { + // Set new width and height basing on state options. + attribs[dimension[0]] = (pointStateOptions[dimension[0]] || + seriesStateOptions[dimension[0]] || + shapeArgs[dimension[0]]) + (pointStateOptions[dimension[0] + 'Plus'] || + seriesStateOptions[dimension[0] + 'Plus'] || 0); + // Align marker by a new size. + attribs[dimension[1]] = shapeArgs[dimension[1]] + + (shapeArgs[dimension[0]] - attribs[dimension[0]]) / 2; + }); + } + return state ? attribs : shapeArgs; + }, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#drawPoints + * @return {void} + */ + drawPoints: function () { + var _this = this; + // In styled mode, use CSS, otherwise the fill used in the style + // sheet will take precedence over the fill attribute. + var seriesMarkerOptions = this.options.marker || {}; + if (seriesMarkerOptions.enabled || this._hasPointMarkers) { + Series.prototype.drawPoints.call(this); + this.points.forEach(function (point) { + point.graphic && + point.graphic[_this.chart.styledMode ? 'css' : 'animate'](_this.colorAttribs(point)); + }); + } + }, + // Define hasData function for non-cartesian series. + // Returns true if the series has points at all. + hasData: function () { + return !!this.processedXData.length; // != 0 + }, + // Override to also allow null points, used when building the k-d-tree + // for tooltips in boost mode. + getValidPoints: function (points, insideOnly) { + return Series.prototype.getValidPoints.call(this, points, insideOnly, true); + }, + /** + * @ignore + * @deprecated + * @function Highcharts.seriesTypes.heatmap#getBox + */ + getBox: noop, + /** + * @private + * @borrows Highcharts.LegendSymbolMixin.drawRectangle as Highcharts.seriesTypes.heatmap#drawLegendSymbol + */ + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + /** + * @private + * @borrows Highcharts.seriesTypes.column#alignDataLabel as Highcharts.seriesTypes.heatmap#alignDataLabel + */ + alignDataLabel: seriesTypes.column.prototype.alignDataLabel, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#getExtremes + * @return {void} + */ + getExtremes: function () { + // Get the extremes from the value data + var _a = Series.prototype.getExtremes + .call(this, + this.valueData), + dataMin = _a.dataMin, + dataMax = _a.dataMax; + if (isNumber(dataMin)) { + this.valueMin = dataMin; + } + if (isNumber(dataMax)) { + this.valueMax = dataMax; + } + // Get the extremes from the y data + return Series.prototype.getExtremes.call(this); + } + /* eslint-enable valid-jsdoc */ + }), merge(colorMapPointMixin, { + /** + * Heatmap series only. Padding between the points in the heatmap. + * @name Highcharts.Point#pointPadding + * @type {number|undefined} + */ + /** + * Heatmap series only. The value of the point, resulting in a color + * controled by options as set in the colorAxis configuration. + * @name Highcharts.Point#value + * @type {number|null|undefined} + */ + /* eslint-disable valid-jsdoc */ + /** + * @private + * @function Highcharts.Point#applyOptions + * @param {Highcharts.HeatmapPointOptions} options + * @param {number} x + * @return {Highcharts.SVGPathArray} + */ + applyOptions: function (options, x) { + var point = H.Point.prototype + .applyOptions.call(this, + options, + x); + point.formatPrefix = + point.isNull || point.value === null ? + 'null' : 'point'; + return point; + }, + /** + * Color points have a value option that determines whether or not it is + * a null point + * @private + * @function Highcharts.HeatmapPoint.isValid + * @return {boolean} + */ + isValid: function () { + // undefined is allowed + return (this.value !== Infinity && + this.value !== -Infinity); + }, + /** + * @private + * @function Highcharts.Point#haloPath + * @param {number} size + * @return {Highcharts.SVGPathArray} + */ + haloPath: function (size) { + if (!size) { + return []; + } + var rect = this.shapeArgs; + return [ + 'M', + rect.x - size, + rect.y - size, + 'L', + rect.x - size, + rect.y + rect.height + size, + rect.x + rect.width + size, + rect.y + rect.height + size, + rect.x + rect.width + size, + rect.y - size, + 'Z' + ]; + }, + getCellAttributes: function () { + var point = this, + series = point.series, + seriesOptions = series.options, + xPad = (seriesOptions.colsize || 1) / 2, + yPad = (seriesOptions.rowsize || 1) / 2, + xAxis = series.xAxis, + yAxis = series.yAxis, + markerOptions = point.options.marker || series.options.marker, + pointPlacement = series.pointPlacementToXValue(), // #7860 + pointPadding = pick(point.pointPadding, + seriesOptions.pointPadding, 0), + cellAttr = { + x1: clamp(Math.round(xAxis.len - + (xAxis.translate(point.x - xPad, + false, + true, + false, + true, -pointPlacement) || 0)), -xAxis.len, 2 * xAxis.len), + x2: clamp(Math.round(xAxis.len - + (xAxis.translate(point.x + xPad, + false, + true, + false, + true, -pointPlacement) || 0)), -xAxis.len, 2 * xAxis.len), + y1: clamp(Math.round((yAxis.translate(point.y - yPad, + false, + true, + false, + true) || 0)), -yAxis.len, 2 * yAxis.len), + y2: clamp(Math.round((yAxis.translate(point.y + yPad, + false, + true, + false, + true) || 0)), -yAxis.len, 2 * yAxis.len) + }; + // Handle marker's fixed width, and height values including border + // and pointPadding while calculating cell attributes. + [['width', 'x'], ['height', 'y']].forEach(function (dimension) { + var prop = dimension[0], + direction = dimension[1]; + var start = direction + '1', end = direction + '2'; + var side = Math.abs(cellAttr[start] - cellAttr[end]), + borderWidth = markerOptions && + markerOptions.lineWidth || 0, + plotPos = Math.abs(cellAttr[start] + cellAttr[end]) / 2; + if (markerOptions[prop] && + markerOptions[prop] < side) { + cellAttr[start] = plotPos - (markerOptions[prop] / 2) - + (borderWidth / 2); + cellAttr[end] = plotPos + (markerOptions[prop] / 2) + + (borderWidth / 2); + } + // Handle pointPadding + if (pointPadding) { + if (direction === 'y') { + start = end; + end = direction + '1'; + } + cellAttr[start] += pointPadding; + cellAttr[end] -= pointPadding; + } + }); + return cellAttr; + } + /* eslint-enable valid-jsdoc */ + })); + /** + * A `heatmap` series. If the [type](#series.heatmap.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @productdesc {highcharts} + * Requires `modules/heatmap`. + * + * @extends series,plotOptions.heatmap + * @excluding cropThreshold, dataParser, dataURL, pointRange, stack, + * @product highcharts highmaps + * @apioption series.heatmap + */ + /** + * An array of data points for the series. For the `heatmap` series + * type, points can be given in the following ways: + * + * 1. An array of arrays with 3 or 2 values. In this case, the values + * correspond to `x,y,value`. If the first value is a string, it is + * applied as the name of the point, and the `x` value is inferred. + * The `x` value can also be omitted, in which case the inner arrays + * should be of length 2\. Then the `x` value is automatically calculated, + * either starting at 0 and incremented by 1, or from `pointStart` + * and `pointInterval` given in the series options. + * + * ```js + * data: [ + * [0, 9, 7], + * [1, 10, 4], + * [2, 6, 3] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' [turboThreshold](#series.heatmap.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * x: 1, + * y: 3, + * value: 10, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 7, + * value: 10, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|*>} + * @extends series.line.data + * @product highcharts highmaps + * @apioption series.heatmap.data + */ + /** + * The color of the point. In heat maps the point color is rarely set + * explicitly, as we use the color to denote the `value`. Options for + * this are set in the [colorAxis](#colorAxis) configuration. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highmaps + * @apioption series.heatmap.data.color + */ + /** + * The value of the point, resulting in a color controled by options + * as set in the [colorAxis](#colorAxis) configuration. + * + * @type {number} + * @product highcharts highmaps + * @apioption series.heatmap.data.value + */ + /** + * The x value of the point. For datetime axes, + * the X value is the timestamp in milliseconds since 1970. + * + * @type {number} + * @product highcharts highmaps + * @apioption series.heatmap.data.x + */ + /** + * The y value of the point. + * + * @type {number} + * @product highcharts highmaps + * @apioption series.heatmap.data.y + */ + /** + * Point padding for a single point. + * + * @sample maps/plotoptions/tilemap-pointpadding + * Point padding on tiles + * + * @type {number} + * @product highcharts highmaps + * @apioption series.heatmap.data.pointPadding + */ + /** + * @excluding radius, enabledThreshold + * @product highcharts highmaps + * @since 8.1 + * @apioption series.heatmap.data.marker + */ + /** + * @excluding radius, enabledThreshold + * @product highcharts highmaps + * @since 8.1 + * @apioption series.heatmap.marker + */ + /** + * @excluding radius, radiusPlus + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.hover + */ + /** + * @excluding radius + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.select + */ + /** + * @excluding radius, radiusPlus + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.hover + */ + /** + * @excluding radius + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.select + */ + /** + * Set the marker's fixed width on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-linewidthplus + * 5 pixels wider lineWidth on hover + * + * @type {number|undefined} + * @default 0 + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.hover.lineWidthPlus + */ + /** + * Set the marker's fixed width on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.hover.width + */ + /** + * Set the marker's fixed height on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.hover.height + */ + /** + * The number of pixels to increase the width of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.hover.widthPlus + */ + /** + * The number of pixels to increase the height of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.hover.heightPlus + */ + /** + * The number of pixels to increase the width of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.select.widthPlus + */ + /** + * The number of pixels to increase the height of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.select.heightPlus + */ + /** + * Set the marker's fixed width on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-linewidthplus + * 5 pixels wider lineWidth on hover + * + * @type {number|undefined} + * @default 0 + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.hover.lineWidthPlus + */ + /** + * Set the marker's fixed width on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.hover.width + */ + /** + * Set the marker's fixed height on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.hover.height + */ + /** + * The number of pixels to increase the width of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highstock + * @apioption series.heatmap.data.marker.states.hover.widthPlus + */ + /** + * The number of pixels to increase the height of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highstock + * @apioption series.heatmap.data.marker.states.hover.heightPlus + */ + /** + * Set the marker's fixed width on select state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.select.width + */ + /** + * Set the marker's fixed height on select state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.select.height + */ + /** + * The number of pixels to increase the width of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highstock + * @apioption series.heatmap.data.marker.states.select.widthPlus + */ + /** + * The number of pixels to increase the height of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highstock + * @apioption series.heatmap.data.marker.states.select.heightPlus + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/heatmap.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/histogram-bellcurve.js b/highcharts/modules/histogram-bellcurve.js new file mode 100644 index 0000000..fbed6df --- /dev/null +++ b/highcharts/modules/histogram-bellcurve.js @@ -0,0 +1,18 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + (c) 2010-2019 Highsoft AS + Author: Sebastian Domas + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/histogram-bellcurve",["highcharts"],function(c){a(c);a.Highcharts=c;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function c(f,a,d,c){f.hasOwnProperty(a)||(f[a]=c.apply(null,d))}a=a?a._modules:{};c(a,"Mixins/DerivedSeries.js",[a["Core/Globals.js"],a["Core/Utilities.js"]],function(a,c){var f=c.addEvent,p=c.defined, +l=a.Series;return{hasDerivedData:!0,init:function(){l.prototype.init.apply(this,arguments);this.initialised=!1;this.baseSeries=null;this.eventRemovers=[];this.addEvents()},setDerivedData:a.noop,setBaseSeries:function(){var b=this.chart,a=this.options.baseSeries;this.baseSeries=p(a)&&(b.series[a]||b.get(a))||null},addEvents:function(){var b=this;var a=f(this.chart,"afterLinkSeries",function(){b.setBaseSeries();b.baseSeries&&!b.initialised&&(b.setDerivedData(),b.addBaseSeriesEvents(),b.initialised= +!0)});this.eventRemovers.push(a)},addBaseSeriesEvents:function(){var a=this;var c=f(a.baseSeries,"updatedData",function(){a.setDerivedData()});var d=f(a.baseSeries,"destroy",function(){a.baseSeries=null;a.initialised=!1});a.eventRemovers.push(c,d)},destroy:function(){this.eventRemovers.forEach(function(a){a()});l.prototype.destroy.apply(this,arguments)}}});c(a,"Series/HistogramSeries.js",[a["Core/Utilities.js"],a["Mixins/DerivedSeries.js"]],function(a,c){function f(a){return function(h){for(var b= +1;a[b]<=h;)b++;return a[--b]}}var p=a.arrayMax,l=a.arrayMin,b=a.correctFloat,m=a.isNumber,k=a.merge,r=a.objectEach;a=a.seriesType;var g={"square-root":function(a){return Math.ceil(Math.sqrt(a.options.data.length))},sturges:function(a){return Math.ceil(Math.log(a.options.data.length)*Math.LOG2E)},rice:function(a){return Math.ceil(2*Math.pow(a.options.data.length,1/3))}};a("histogram","column",{binsNumber:"square-root",binWidth:void 0,pointPadding:0,groupPadding:0,grouping:!1,pointPlacement:"between", +tooltip:{headerFormat:"",pointFormat:'{point.x} - {point.x2}
    \u25cf {series.name} {point.y}
    '}},k(c,{setDerivedData:function(){var a=this.baseSeries.yData;a.length&&(a=this.derivedData(a,this.binsNumber(),this.options.binWidth),this.setData(a,!1))},derivedData:function(a,e,c){var h=p(a),g=b(l(a)),n=[],d={},k=[];c=this.binWidth=b(m(c)?c||1:(h-g)/e);this.options.pointRange=Math.max(c,0);for(e=g;e=c||0>=b(b(g+n.length*c)-e));e=b(e+c))n.push(e),d[e]=0;0!==d[g]&&(n.push(b(g)),d[b(g)]=0);var q=f(n.map(function(a){return parseFloat(a)}));a.forEach(function(a){a=b(q(a));d[a]++});r(d,function(a,h){k.push({x:Number(h),y:a,x2:b(Number(h)+c)})});k.sort(function(a,h){return a.x-h.x});return k},binsNumber:function(){var a=this.options.binsNumber,b=g[a]||"function"===typeof a&&a;return Math.ceil(b&&b(this.baseSeries)||(m(a)?a:g["square-root"](this.baseSeries)))}}));""});c(a,"Series/BellcurveSeries.js", +[a["Core/Utilities.js"],a["Mixins/DerivedSeries.js"]],function(a,c){function d(a){var b=a.length;a=a.reduce(function(a,b){return a+b},0);return 0} + * An array of data + */ + setDerivedData: noop, + /** + * Sets base series for the series + * + * @private + * @function derivedSeriesMixin.setBaseSeries + * @return {void} + */ + setBaseSeries: function () { + var chart = this.chart, + baseSeriesOptions = this.options.baseSeries, + baseSeries = (defined(baseSeriesOptions) && + (chart.series[baseSeriesOptions] || + chart.get(baseSeriesOptions))); + this.baseSeries = baseSeries || null; + }, + /** + * Adds events for the series + * + * @private + * @function derivedSeriesMixin.addEvents + * @return {void} + */ + addEvents: function () { + var derivedSeries = this, + chartSeriesLinked; + chartSeriesLinked = addEvent(this.chart, 'afterLinkSeries', function () { + derivedSeries.setBaseSeries(); + if (derivedSeries.baseSeries && !derivedSeries.initialised) { + derivedSeries.setDerivedData(); + derivedSeries.addBaseSeriesEvents(); + derivedSeries.initialised = true; + } + }); + this.eventRemovers.push(chartSeriesLinked); + }, + /** + * Adds events to the base series - it required for recalculating the data + * in the series if the base series is updated / removed / etc. + * + * @private + * @function derivedSeriesMixin.addBaseSeriesEvents + * @return {void} + */ + addBaseSeriesEvents: function () { + var derivedSeries = this, + updatedDataRemover, + destroyRemover; + updatedDataRemover = addEvent(derivedSeries.baseSeries, 'updatedData', function () { + derivedSeries.setDerivedData(); + }); + destroyRemover = addEvent(derivedSeries.baseSeries, 'destroy', function () { + derivedSeries.baseSeries = null; + derivedSeries.initialised = false; + }); + derivedSeries.eventRemovers.push(updatedDataRemover, destroyRemover); + }, + /** + * Destroys the series + * + * @private + * @function derivedSeriesMixin.destroy + */ + destroy: function () { + this.eventRemovers.forEach(function (remover) { + remover(); + }); + Series.prototype.destroy.apply(this, arguments); + } + /* eslint-disable valid-jsdoc */ + }; + + return derivedSeriesMixin; + }); + _registerModule(_modules, 'Series/HistogramSeries.js', [_modules['Core/Utilities.js'], _modules['Mixins/DerivedSeries.js']], function (U, derivedSeriesMixin) { + /* * + * + * Copyright (c) 2010-2017 Highsoft AS + * Author: Sebastian Domas + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var arrayMax = U.arrayMax, + arrayMin = U.arrayMin, + correctFloat = U.correctFloat, + isNumber = U.isNumber, + merge = U.merge, + objectEach = U.objectEach, + seriesType = U.seriesType; + /* ************************************************************************** * + * HISTOGRAM + * ************************************************************************** */ + /** + * A dictionary with formulas for calculating number of bins based on the + * base series + **/ + var binsNumberFormulas = { + 'square-root': function (baseSeries) { + return Math.ceil(Math.sqrt(baseSeries.options.data.length)); + }, + 'sturges': function (baseSeries) { + return Math.ceil(Math.log(baseSeries.options.data.length) * Math.LOG2E); + }, + 'rice': function (baseSeries) { + return Math.ceil(2 * Math.pow(baseSeries.options.data.length, 1 / 3)); + } + }; + /** + * Returns a function for mapping number to the closed (right opened) bins + * @private + * @param {Array} bins - Width of the bins + * @return {Function} + **/ + function fitToBinLeftClosed(bins) { + return function (y) { + var i = 1; + while (bins[i] <= y) { + i++; + } + return bins[--i]; + }; + } + /** + * Histogram class + * @private + * @class + * @name Highcharts.seriesTypes.histogram + * @augments Highcharts.Series + */ + seriesType('histogram', 'column', + /** + * A histogram is a column series which represents the distribution of the + * data set in the base series. Histogram splits data into bins and shows + * their frequencies. + * + * @sample {highcharts} highcharts/demo/histogram/ + * Histogram + * + * @extends plotOptions.column + * @excluding boostThreshold, dragDrop, pointInterval, pointIntervalUnit, + * stacking, boostBlending + * @product highcharts + * @since 6.0.0 + * @requires modules/histogram + * @optionparent plotOptions.histogram + */ + { + /** + * A preferable number of bins. It is a suggestion, so a histogram may + * have a different number of bins. By default it is set to the square + * root of the base series' data length. Available options are: + * `square-root`, `sturges`, `rice`. You can also define a function + * which takes a `baseSeries` as a parameter and should return a + * positive integer. + * + * @type {"square-root"|"sturges"|"rice"|number|function} + */ + binsNumber: 'square-root', + /** + * Width of each bin. By default the bin's width is calculated as + * `(max - min) / number of bins`. This option takes precedence over + * [binsNumber](#plotOptions.histogram.binsNumber). + * + * @type {number} + */ + binWidth: void 0, + pointPadding: 0, + groupPadding: 0, + grouping: false, + pointPlacement: 'between', + tooltip: { + headerFormat: '', + pointFormat: ('{point.x} - {point.x2}' + + '
    ' + + '\u25CF' + + ' {series.name} {point.y}
    ') + } + }, merge(derivedSeriesMixin, { + setDerivedData: function () { + var yData = this.baseSeries.yData; + if (!yData.length) { + return; + } + var data = this.derivedData(yData, + this.binsNumber(), + this.options.binWidth); + this.setData(data, false); + }, + derivedData: function (baseData, binsNumber, binWidth) { + var series = this, + max = arrayMax(baseData), + // Float correction needed, because first frequency value is not + // corrected when generating frequencies (within for loop). + min = correctFloat(arrayMin(baseData)), + frequencies = [], + bins = {}, + data = [], + x, + fitToBin; + binWidth = series.binWidth = (correctFloat(isNumber(binWidth) ? + (binWidth || 1) : + (max - min) / binsNumber)); + // #12077 negative pointRange causes wrong calculations, + // browser hanging. + series.options.pointRange = Math.max(binWidth, 0); + // If binWidth is 0 then max and min are equaled, + // increment the x with some positive value to quit the loop + for (x = min; + // This condition is needed because of the margin of error while + // operating on decimal numbers. Without that, additional bin + // was sometimes noticeable on the graph, because of too small + // precision of float correction. + x < max && + (series.userOptions.binWidth || + correctFloat(max - x) >= binWidth || + // #13069 - Every add and subtract operation should + // be corrected, due to general problems with + // operations on float numbers in JS. + correctFloat(correctFloat(min + (frequencies.length * binWidth)) - + x) <= 0); x = correctFloat(x + binWidth)) { + frequencies.push(x); + bins[x] = 0; + } + if (bins[min] !== 0) { + frequencies.push(correctFloat(min)); + bins[correctFloat(min)] = 0; + } + fitToBin = fitToBinLeftClosed(frequencies.map(function (elem) { + return parseFloat(elem); + })); + baseData.forEach(function (y) { + var x = correctFloat(fitToBin(y)); + bins[x]++; + }); + objectEach(bins, function (frequency, x) { + data.push({ + x: Number(x), + y: frequency, + x2: correctFloat(Number(x) + binWidth) + }); + }); + data.sort(function (a, b) { + return a.x - b.x; + }); + return data; + }, + binsNumber: function () { + var binsNumberOption = this.options.binsNumber; + var binsNumber = binsNumberFormulas[binsNumberOption] || + // #7457 + (typeof binsNumberOption === 'function' && binsNumberOption); + return Math.ceil((binsNumber && binsNumber(this.baseSeries)) || + (isNumber(binsNumberOption) ? + binsNumberOption : + binsNumberFormulas['square-root'](this.baseSeries))); + } + })); + /** + * A `histogram` series. If the [type](#series.histogram.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.histogram + * @excluding data, dataParser, dataURL, boostThreshold, boostBlending + * @product highcharts + * @since 6.0.0 + * @requires modules/histogram + * @apioption series.histogram + */ + /** + * An integer identifying the index to use for the base series, or a string + * representing the id of the series. + * + * @type {number|string} + * @apioption series.histogram.baseSeries + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'Series/BellcurveSeries.js', [_modules['Core/Utilities.js'], _modules['Mixins/DerivedSeries.js']], function (U, derivedSeriesMixin) { + /* * + * + * (c) 2010-2020 Highsoft AS + * + * Author: Sebastian Domas + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var correctFloat = U.correctFloat, + isNumber = U.isNumber, + merge = U.merge, + seriesType = U.seriesType; + /* ************************************************************************** * + * BELL CURVE * + * ************************************************************************** */ + /* eslint-disable valid-jsdoc */ + /** + * @private + */ + function mean(data) { + var length = data.length, + sum = data.reduce(function (sum, + value) { + return (sum += value); + }, 0); + return length > 0 && sum / length; + } + /** + * @private + */ + function standardDeviation(data, average) { + var len = data.length, + sum; + average = isNumber(average) ? average : mean(data); + sum = data.reduce(function (sum, value) { + var diff = value - average; + return (sum += diff * diff); + }, 0); + return len > 1 && Math.sqrt(sum / (len - 1)); + } + /** + * @private + */ + function normalDensity(x, mean, standardDeviation) { + var translation = x - mean; + return Math.exp(-(translation * translation) / + (2 * standardDeviation * standardDeviation)) / (standardDeviation * Math.sqrt(2 * Math.PI)); + } + /* eslint-enable valid-jsdoc */ + /** + * Bell curve class + * + * @private + * @class + * @name Highcharts.seriesTypes.bellcurve + * + * @augments Highcharts.Series + */ + seriesType('bellcurve', 'areaspline' + /** + * A bell curve is an areaspline series which represents the probability + * density function of the normal distribution. It calculates mean and + * standard deviation of the base series data and plots the curve according + * to the calculated parameters. + * + * @sample {highcharts} highcharts/demo/bellcurve/ + * Bell curve + * + * @extends plotOptions.areaspline + * @since 6.0.0 + * @product highcharts + * @excluding boostThreshold, connectNulls, dragDrop, stacking, + * pointInterval, pointIntervalUnit + * @requires modules/bellcurve + * @optionparent plotOptions.bellcurve + */ + , { + /** + * This option allows to define the length of the bell curve. A unit of + * the length of the bell curve is standard deviation. + * + * @sample highcharts/plotoptions/bellcurve-intervals-pointsininterval + * Intervals and points in interval + */ + intervals: 3, + /** + * Defines how many points should be plotted within 1 interval. See + * `plotOptions.bellcurve.intervals`. + * + * @sample highcharts/plotoptions/bellcurve-intervals-pointsininterval + * Intervals and points in interval + */ + pointsInInterval: 3, + marker: { + enabled: false + } + }, merge(derivedSeriesMixin, { + setMean: function () { + this.mean = correctFloat(mean(this.baseSeries.yData)); + }, + setStandardDeviation: function () { + this.standardDeviation = correctFloat(standardDeviation(this.baseSeries.yData, this.mean)); + }, + setDerivedData: function () { + if (this.baseSeries.yData.length > 1) { + this.setMean(); + this.setStandardDeviation(); + this.setData(this.derivedData(this.mean, this.standardDeviation), false); + } + return (void 0); + }, + derivedData: function (mean, standardDeviation) { + var intervals = this.options.intervals, + pointsInInterval = this.options.pointsInInterval, + x = mean - intervals * standardDeviation, + stop = intervals * pointsInInterval * 2 + 1, + increment = standardDeviation / pointsInInterval, + data = [], + i; + for (i = 0; i < stop; i++) { + data.push([x, normalDensity(x, mean, standardDeviation)]); + x += increment; + } + return data; + } + })); + /** + * A `bellcurve` series. If the [type](#series.bellcurve.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * For options that apply to multiple series, it is recommended to add + * them to the [plotOptions.series](#plotOptions.series) options structure. + * To apply to all series of this specific type, apply it to + * [plotOptions.bellcurve](#plotOptions.bellcurve). + * + * @extends series,plotOptions.bellcurve + * @since 6.0.0 + * @product highcharts + * @excluding dataParser, dataURL, data, boostThreshold, boostBlending + * @requires modules/bellcurve + * @apioption series.bellcurve + */ + /** + * An integer identifying the index to use for the base series, or a string + * representing the id of the series. + * + * @type {number|string} + * @apioption series.bellcurve.baseSeries + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/histogram-bellcurve.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/item-series.js b/highcharts/modules/item-series.js new file mode 100644 index 0000000..ff1dbd5 --- /dev/null +++ b/highcharts/modules/item-series.js @@ -0,0 +1,18 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Item series type for Highcharts + + (c) 2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/item-series",["highcharts"],function(d){b(d);b.Highcharts=d;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function d(b,d,c,C){b.hasOwnProperty(d)||(b[d]=C.apply(null,c))}b=b?b._modules:{};d(b,"Series/ItemSeries.js",[b["Core/Globals.js"],b["Core/Options.js"],b["Core/Utilities.js"]],function(b,d,c){var C=c.defined,F= +c.extend,G=c.fireEvent,D=c.isNumber,H=c.merge,I=c.objectEach,J=c.pick;c=c.seriesType;var m=b.seriesTypes.pie.prototype.pointClass.prototype;c("item","pie",{endAngle:void 0,innerSize:"40%",itemPadding:.1,layout:"vertical",marker:H(d.defaultOptions.plotOptions.line.marker,{radius:null}),rows:void 0,crisp:!1,showInLegend:!0,startAngle:void 0},{markerAttribs:void 0,translate:function(a){0===this.total&&(this.center=this.getCenter());this.slots||(this.slots=[]);D(this.options.startAngle)&&D(this.options.endAngle)? +(b.seriesTypes.pie.prototype.translate.apply(this,arguments),this.slots=this.getSlots()):(this.generatePoints(),G(this,"afterTranslate"))},getSlots:function(){function a(a){0this.total+(e&&E?e.length:0);)for(A=q,q=n.length=0,e=k,k=[],h++,p=c/h/2,g?(d=(p-g)/p*c,0<=d?p=g:(d=0,m=1)):p=Math.floor(p* +m),x=p;0b)break;a--}else for(a=Math.floor(a);a this.total + (rows && isCircle ? rows.length : 0)) { + finalItemCount = itemCount; + // Reset + slots.length = 0; + itemCount = 0; + // Now rows is the last successful run + rows = testRows; + testRows = []; + itemSize++; + // Total number of rows (arcs) from the center to the + // perimeter + rowCount = diameter / itemSize / 2; + if (rowsOption) { + innerSize = ((rowCount - rowsOption) / rowCount) * diameter; + if (innerSize >= 0) { + rowCount = rowsOption; + // If innerSize is negative, we are trying to set too + // many rows in the rows option, so fall back to + // treating it as innerSize 0 + } + else { + innerSize = 0; + rowFraction = 1; + } + } + else { + rowCount = Math.floor(rowCount * rowFraction); + } + for (row = rowCount; row > 0; row--) { + rowRadius = (innerSize + (row / rowCount) * + (diameter - innerSize - itemSize)) / 2; + rowLength = fullAngle * rowRadius; + colCount = Math.ceil(rowLength / itemSize); + testRows.push({ + rowRadius: rowRadius, + rowLength: rowLength, + colCount: colCount + }); + itemCount += colCount + 1; + } + } + if (!rows) { + return; + } + // We now have more slots than we have total items. Loop over + // the rows and remove the last slot until the count is correct. + // For each iteration we sort the last slot by the angle, and + // remove those with the highest angles. + var overshoot = finalItemCount - this.total - + (isCircle ? rows.length : 0); + /** + * @private + * @param {Highcharts.ItemRowContainerObject} item + * Wrapped object with angle and row + * @return {void} + */ + function cutOffRow(item) { + if (overshoot > 0) { + item.row.colCount--; + overshoot--; + } + } + while (overshoot > 0) { + rows + // Return a simplified representation of the angle of + // the last slot within each row. + .map(function (row) { + return { + angle: row.colCount / row.rowLength, + row: row + }; + }) + // Sort by the angles... + .sort(function (a, b) { + return b.angle - a.angle; + }) + // ...so that we can ignore the items with the lowest + // angles... + .slice(0, Math.min(overshoot, Math.ceil(rows.length / 2))) + // ...and remove the ones with the highest angles + .forEach(cutOffRow); + } + rows.forEach(function (row) { + var rowRadius = row.rowRadius, + colCount = row.colCount; + increment = colCount ? fullAngle / colCount : 0; + for (col = 0; col <= colCount; col += 1) { + angle = this.startAngleRad + col * increment; + x = center[0] + Math.cos(angle) * rowRadius; + y = center[1] + Math.sin(angle) * rowRadius; + slots.push({ x: x, y: y, angle: angle }); + } + }, this); + // Sort by angle + slots.sort(function (a, b) { + return a.angle - b.angle; + }); + this.itemSize = itemSize; + return slots; + }, + getRows: function () { + var rows = this.options.rows, + cols, + ratio; + // Get the row count that gives the most square cells + if (!rows) { + ratio = this.chart.plotWidth / this.chart.plotHeight; + rows = Math.sqrt(this.total); + if (ratio > 1) { + rows = Math.ceil(rows); + while (rows > 0) { + cols = this.total / rows; + if (cols / rows > ratio) { + break; + } + rows--; + } + } + else { + rows = Math.floor(rows); + while (rows < this.total) { + cols = this.total / rows; + if (cols / rows < ratio) { + break; + } + rows++; + } + } + } + return rows; + }, + drawPoints: function () { + var series = this, + options = this.options, + renderer = series.chart.renderer, + seriesMarkerOptions = options.marker, + borderWidth = this.borderWidth, + crisp = borderWidth % 2 ? 0.5 : 1, + i = 0, + rows = this.getRows(), + cols = Math.ceil(this.total / rows), + cellWidth = this.chart.plotWidth / cols, + cellHeight = this.chart.plotHeight / rows, + itemSize = this.itemSize || Math.min(cellWidth, + cellHeight); + /* + this.slots.forEach(slot => { + this.chart.renderer.circle(slot.x, slot.y, 6) + .attr({ + fill: 'silver' + }) + .add(this.group); + }); + //*/ + this.points.forEach(function (point) { + var attr, + graphics, + pointAttr, + pointMarkerOptions = point.marker || {}, + symbol = (pointMarkerOptions.symbol || + seriesMarkerOptions.symbol), + r = pick(pointMarkerOptions.radius, + seriesMarkerOptions.radius), + size = defined(r) ? 2 * r : itemSize, + padding = size * options.itemPadding, + x, + y, + width, + height; + point.graphics = graphics = point.graphics || {}; + if (!series.chart.styledMode) { + pointAttr = series.pointAttribs(point, point.selected && 'select'); + } + if (!point.isNull && point.visible) { + if (!point.graphic) { + point.graphic = renderer.g('point') + .add(series.group); + } + for (var val = 0; val < point.y; val++) { + // Semi-circle + if (series.center && series.slots) { + // Fill up the slots from left to right + var slot = series.slots.shift(); + x = slot.x - itemSize / 2; + y = slot.y - itemSize / 2; + } + else if (options.layout === 'horizontal') { + x = cellWidth * (i % cols); + y = cellHeight * Math.floor(i / cols); + } + else { + x = cellWidth * Math.floor(i / rows); + y = cellHeight * (i % rows); + } + x += padding; + y += padding; + width = Math.round(size - 2 * padding); + height = width; + if (series.options.crisp) { + x = Math.round(x) - crisp; + y = Math.round(y) + crisp; + } + attr = { + x: x, + y: y, + width: width, + height: height + }; + if (typeof r !== 'undefined') { + attr.r = r; + } + if (graphics[val]) { + graphics[val].animate(attr); + } + else { + graphics[val] = renderer + .symbol(symbol, null, null, null, null, { + backgroundSize: 'within' + }) + .attr(extend(attr, pointAttr)) + .add(point.graphic); + } + graphics[val].isActive = true; + i++; + } + } + objectEach(graphics, function (graphic, key) { + if (!graphic.isActive) { + graphic.destroy(); + delete graphics[key]; + } + else { + graphic.isActive = false; + } + }); + }); + }, + drawDataLabels: function () { + if (this.center && this.slots) { + H.seriesTypes.pie.prototype.drawDataLabels.call(this); + // else, it's just a dot chart with no natural place to put the + // data labels + } + else { + this.points.forEach(function (point) { + point.destroyElements({ dataLabel: 1 }); + }); + } + }, + // Fade in the whole chart + animate: function (init) { + if (init) { + this.group.attr({ + opacity: 0 + }); + } + else { + this.group.animate({ + opacity: 1 + }, this.options.animation); + } + } + }, + // Point class + { + connectorShapes: piePoint.connectorShapes, + getConnectorPath: piePoint.getConnectorPath, + setVisible: piePoint.setVisible, + getTranslate: piePoint.getTranslate + }); + /** + * An `item` series. If the [type](#series.item.type) option is not specified, + * it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.item + * @excluding dataParser, dataURL, stack, xAxis, yAxis, dataSorting, + * boostThreshold, boostBlending + * @product highcharts + * @requires modules/item-series + * @apioption series.item + */ + /** + * An array of data points for the series. For the `item` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.item.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * y: 1, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 7, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.pie.data + * @excludes sliced + * @product highcharts + * @apioption series.item.data + */ + /** + * The sequential index of the data point in the legend. + * + * @type {number} + * @product highcharts + * @apioption series.pie.data.legendIndex + */ + ''; // adds the doclets above to the transpiled file + + }); + _registerModule(_modules, 'masters/modules/item-series.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/lollipop.js b/highcharts/modules/lollipop.js new file mode 100644 index 0000000..99f92ce --- /dev/null +++ b/highcharts/modules/lollipop.js @@ -0,0 +1,11 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + (c) 2009-2019 Sebastian Bochan, Rafal Sebestjanski + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/lollipop",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,f,b,c){a.hasOwnProperty(f)||(a[f]=c.apply(null,b))}a=a?a._modules:{};b(a,"Series/LollipopSeries.js",[a["Core/Globals.js"],a["Core/Utilities.js"]],function(a,b){b=b.seriesType;var e=a.seriesTypes.area.prototype, +c=a.seriesTypes.column.prototype;b("lollipop","dumbbell",{lowColor:void 0,threshold:0,connectorWidth:1,groupPadding:.2,pointPadding:.1,states:{hover:{lineWidthPlus:0,connectorWidthPlus:1,halo:!1}},tooltip:{pointFormat:'\u25cf {series.name}: {point.y}
    '}},{pointArrayMap:["y"],pointValKey:"y",toYData:function(b){return[a.pick(b.y,b.low)]},translatePoint:e.translate,drawPoint:e.drawPoints,drawDataLabels:c.drawDataLabels,setShapeArgs:c.translate},{pointSetState:e.pointClass.prototype.setState, +setState:a.seriesTypes.dumbbell.prototype.pointClass.prototype.setState,init:function(b,d,c){a.isObject(d)&&"low"in d&&(d.y=d.low,delete d.low);return a.Point.prototype.init.apply(this,arguments)}});""});b(a,"masters/modules/lollipop.src.js",[],function(){})}); +//# sourceMappingURL=lollipop.js.map \ No newline at end of file diff --git a/highcharts/modules/lollipop.js.map b/highcharts/modules/lollipop.js.map new file mode 100644 index 0000000..8ae35be --- /dev/null +++ b/highcharts/modules/lollipop.js.map @@ -0,0 +1 @@ +{"version":3,"file":"lollipop.js.map","lineCount":10,"mappings":"A;;;;;;;AAQC,SAAS,CAACA,CAAD,CAAU,CACM,QAAtB,GAAI,MAAOC,OAAX,EAAkCA,MAAAC,QAAlC,EACIF,CAAA,CAAQ,SAAR,CACA,CADqBA,CACrB,CAAAC,MAAAC,QAAA,CAAiBF,CAFrB,EAG6B,UAAtB,GAAI,MAAOG,OAAX,EAAoCA,MAAAC,IAApC,CACHD,MAAA,CAAO,6BAAP,CAAsC,CAAC,YAAD,CAAtC,CAAsD,QAAS,CAACE,CAAD,CAAa,CACxEL,CAAA,CAAQK,CAAR,CACAL,EAAAK,WAAA,CAAqBA,CACrB,OAAOL,EAHiE,CAA5E,CADG,CAOHA,CAAA,CAA8B,WAAtB,GAAA,MAAOK,WAAP,CAAoCA,UAApC,CAAiDC,IAAAA,EAAzD,CAXY,CAAnB,CAAA,CAaC,QAAS,CAACD,CAAD,CAAa,CAEpBE,QAASA,EAAe,CAACC,CAAD,CAAMC,CAAN,CAAYC,CAAZ,CAAkBC,CAAlB,CAAsB,CACrCH,CAAAI,eAAA,CAAmBH,CAAnB,CAAL,GACID,CAAA,CAAIC,CAAJ,CADJ,CACgBE,CAAAE,MAAA,CAAS,IAAT,CAAeH,CAAf,CADhB,CAD0C,CAD1CI,CAAAA,CAAWT,CAAA,CAAaA,CAAAS,SAAb,CAAmC,EAMlDP,EAAA,CAAgBO,CAAhB,CAA0B,0BAA1B,CAAsD,CAACA,CAAA,CAAS,iBAAT,CAAD,CAA8BA,CAAA,CAAS,mBAAT,CAA9B,CAAtD,CAAoH,QAAS,CAACC,CAAD,CAAIC,CAAJ,CAAO,CAU5HC,CAAAA,CAAaD,CAAAC,WAV+G,KAW5HC,EAAYH,CAAAI,YAAAC,KAAAC,UAXgH;AAY5HC,EAAWP,CAAAI,YAAAI,OAAAF,UAmBfJ,EAAA,CAAW,UAAX,CAAuB,UAAvB,CAAmC,CAE/BO,SAAU,IAAK,EAFgB,CAI/BC,UAAW,CAJoB,CAM/BC,eAAgB,CANe,CAQ/BC,aAAc,EARiB,CAU/BC,aAAc,EAViB,CAY/BC,OAAQ,CACJC,MAAO,CAEHC,cAAe,CAFZ,CAIHC,mBAAoB,CAJjB,CAMHC,KAAM,CAAA,CANH,CADH,CAZuB,CAsB/BC,QAAS,CACLC,YAAa,uFADR,CAtBsB,CAAnC,CAyBG,CACCC,cAAe,CAAC,GAAD,CADhB,CAECC,YAAa,GAFd,CAGCC,QAASA,QAAS,CAACC,CAAD,CAAQ,CACtB,MAAO,CAACxB,CAAAyB,KAAA,CAAOD,CAAAE,EAAP,CAAgBF,CAAAG,IAAhB,CAAD,CADe,CAH3B,CAMCC,eAAgBzB,CAAA0B,UANjB,CAOCC,UAAW3B,CAAA4B,WAPZ,CAQCC,eAAgBzB,CAAAyB,eARjB,CASCC,aAAc1B,CAAAsB,UATf,CAzBH,CAmCG,CACCK,cAAe/B,CAAAgC,WAAA7B,UAAA8B,SADhB;AAECA,SAAUpC,CAAAI,YAAAiC,SAAA/B,UAAA6B,WAAA7B,UAAA8B,SAFX,CAGCE,KAAMA,QAAS,CAACC,CAAD,CAASC,CAAT,CAAkBC,CAAlB,CAAqB,CAC5BzC,CAAA0C,SAAA,CAAWF,CAAX,CAAJ,EAA2B,KAA3B,EAAoCA,EAApC,GACIA,CAAAd,EACA,CADYc,CAAAb,IACZ,CAAA,OAAOa,CAAAb,IAFX,CAIA,OAAO3B,EAAA2C,MAAArC,UAAAgC,KAAAxC,MAAA,CAA6B,IAA7B,CAAmC8C,SAAnC,CALyB,CAHrC,CAnCH,CA+HA,GA9JgI,CAApI,CAiKApD,EAAA,CAAgBO,CAAhB,CAA0B,iCAA1B,CAA6D,EAA7D,CAAiE,QAAS,EAAG,EAA7E,CAxKoB,CAbvB;","sources":["lollipop.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","seriesType","areaProto","seriesTypes","area","prototype","colProto","column","lowColor","threshold","connectorWidth","groupPadding","pointPadding","states","hover","lineWidthPlus","connectorWidthPlus","halo","tooltip","pointFormat","pointArrayMap","pointValKey","toYData","point","pick","y","low","translatePoint","translate","drawPoint","drawPoints","drawDataLabels","setShapeArgs","pointSetState","pointClass","setState","dumbbell","init","series","options","x","isObject","Point","arguments"]} \ No newline at end of file diff --git a/highcharts/modules/lollipop.src.js b/highcharts/modules/lollipop.src.js new file mode 100644 index 0000000..4a47192 --- /dev/null +++ b/highcharts/modules/lollipop.src.js @@ -0,0 +1,194 @@ +/** + * @license Highcharts JS v8.2.0 (2020-08-20) + * + * (c) 2009-2019 Sebastian Bochan, Rafal Sebestjanski + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/lollipop', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'Series/LollipopSeries.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Sebastian Bochan, Rafal Sebestjanski + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var seriesType = U.seriesType; + var areaProto = H.seriesTypes.area.prototype, + colProto = H.seriesTypes.column.prototype; + /** + * The lollipop series is a carteseian series with a line anchored from + * the x axis and a dot at the end to mark the value. + * Requires `highcharts-more.js`, `modules/dumbbell.js` and + * `modules/lollipop.js`. + * + * @sample {highcharts} highcharts/demo/lollipop/ + * Lollipop chart + * @sample {highcharts} highcharts/series-dumbbell/styled-mode-dumbbell/ + * Styled mode + * + * @extends plotOptions.dumbbell + * @product highcharts highstock + * @excluding fillColor, fillOpacity, lineWidth, stack, stacking, lowColor, + * stickyTracking, trackByArea + * @since 8.0.0 + * @optionparent plotOptions.lollipop + */ + seriesType('lollipop', 'dumbbell', { + /** @ignore-option */ + lowColor: void 0, + /** @ignore-option */ + threshold: 0, + /** @ignore-option */ + connectorWidth: 1, + /** @ignore-option */ + groupPadding: 0.2, + /** @ignore-option */ + pointPadding: 0.1, + /** @ignore-option */ + states: { + hover: { + /** @ignore-option */ + lineWidthPlus: 0, + /** @ignore-option */ + connectorWidthPlus: 1, + /** @ignore-option */ + halo: false + } + }, + tooltip: { + pointFormat: '● {series.name}: {point.y}
    ' + } + }, { + pointArrayMap: ['y'], + pointValKey: 'y', + toYData: function (point) { + return [H.pick(point.y, point.low)]; + }, + translatePoint: areaProto.translate, + drawPoint: areaProto.drawPoints, + drawDataLabels: colProto.drawDataLabels, + setShapeArgs: colProto.translate + }, { + pointSetState: areaProto.pointClass.prototype.setState, + setState: H.seriesTypes.dumbbell.prototype.pointClass.prototype.setState, + init: function (series, options, x) { + if (H.isObject(options) && 'low' in options) { + options.y = options.low; + delete options.low; + } + return H.Point.prototype.init.apply(this, arguments); + } + }); + /** + * The `lollipop` series. If the [type](#series.lollipop.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.lollipop, + * @excluding boostThreshold, boostBlending + * @product highcharts highstock + * @requires highcharts-more + * @requires modules/dumbbell + * @requires modules/lollipop + * @apioption series.lollipop + */ + /** + * An array of data points for the series. For the `lollipop` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 6], + * [1, 2], + * [2, 6] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.lollipop.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00", + * connectorWidth: 3, + * connectorColor: "#FF00FF" + * }, { + * x: 1, + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.dumbbell.data + * @excluding high, low, lowColor + * @product highcharts highstock + * @apioption series.lollipop.data + */ + /** + * The y value of the point. + * + * @type {number|null} + * @product highcharts highstock + * @apioption series.line.data.y + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/lollipop.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/highcharts/modules/marker-clusters.js b/highcharts/modules/marker-clusters.js new file mode 100644 index 0000000..a47ec78 --- /dev/null +++ b/highcharts/modules/marker-clusters.js @@ -0,0 +1,44 @@ +/* + Highcharts JS v8.2.0 (2020-08-20) + + Marker clusters module for Highcharts + + (c) 2010-2019 Wojciech Chmiel + + License: www.highcharts.com/license +*/ +(function(t){"object"===typeof module&&module.exports?(t["default"]=t,module.exports=t):"function"===typeof define&&define.amd?define("highcharts/modules/marker-clusters",["highcharts"],function(y){t(y);t.Highcharts=y;return t}):t("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(t){function y(t,F,C,y){t.hasOwnProperty(F)||(t[F]=y.apply(null,C))}t=t?t._modules:{};y(t,"Extensions/MarkerClusters.js",[t["Core/Chart/Chart.js"],t["Core/Globals.js"],t["Core/Options.js"],t["Core/Series/Point.js"], +t["Core/Renderer/SVG/SVGRenderer.js"],t["Core/Utilities.js"]],function(t,y,C,P,Z,v){function I(a){var b=a.length,e=0,f=0,c;for(c=0;cClustered points: {point.clusterPointsAmount}
    "}});Z.prototype.symbols.cluster=function(a,b,e,f){e/=2;f/=2;var c=this.arc(a+e,b+f,e-4,f-4,{start:.5*Math.PI,end:2.5*Math.PI,open:!1});var k=this.arc(a+e,b+f,e-3,f-3,{start:.5*Math.PI,end:2.5*Math.PI,innerR:e-2,open:!1});return this.arc(a+e,b+f,e-1,f-1,{start:.5*Math.PI,end:2.5*Math.PI,innerR:e,open:!1}).concat(k,c)};w.prototype.animateClusterPoint= +function(a){var b=this.xAxis,e=this.yAxis,f=this.chart,c=T((this.options.cluster||{}).animation),k=c.duration||500,h=(this.markerClusterInfo||{}).pointsState,m=(h||{}).newState,r=(h||{}).oldState,g=[],l=h=0,p=0,q=!1,u=!1;if(r&&m){var d=m[a.stateId];l=b.toPixels(d.x)-f.plotLeft;p=e.toPixels(d.y)-f.plotTop;if(1===d.parentsId.length){a=(m||{})[a.stateId].parentsId[0];var n=r[a];d.point&&d.point.graphic&&n&&n.point&&n.point.plotX&&n.point.plotY&&n.point.plotX!==d.point.plotX&&n.point.plotY!==d.point.plotY&& +(a=d.point.graphic.getBBox(),h=a.width/2,d.point.graphic.attr({x:n.point.plotX-h,y:n.point.plotY-h}),d.point.graphic.animate({x:l-(d.point.graphic.radius||0),y:p-(d.point.graphic.radius||0)},c,function(){u=!0;n.point&&n.point.destroy&&n.point.destroy()}),d.point.dataLabel&&d.point.dataLabel.alignAttr&&n.point.dataLabel&&n.point.dataLabel.alignAttr&&(d.point.dataLabel.attr({x:n.point.dataLabel.alignAttr.x,y:n.point.dataLabel.alignAttr.y}),d.point.dataLabel.animate({x:d.point.dataLabel.alignAttr.x, +y:d.point.dataLabel.alignAttr.y},c)))}else 0===d.parentsId.length?(R(d,!0,!0),J(function(){Q(d,.1,c,!0,!0)},k/2)):(R(d,!0,!0),d.parentsId.forEach(function(a){r&&r[a]&&(n=r[a],g.push(n),n.point&&n.point.graphic&&(q=!0,n.point.graphic.show(),n.point.graphic.animate({x:l-(n.point.graphic.radius||0),y:p-(n.point.graphic.radius||0),opacity:.4},c,function(){u=!0;L(d,g,c,.7)}),n.point.dataLabel&&-9999!==n.point.dataLabel.y&&d.point&&d.point.dataLabel&&d.point.dataLabel.alignAttr&&(n.point.dataLabel.show(), +n.point.dataLabel.animate({x:d.point.dataLabel.alignAttr.x,y:d.point.dataLabel.alignAttr.y,opacity:.4},c))))}),J(function(){u||L(d,g,c,.85)},k),q||J(function(){L(d,g,c,.1)},k/2))}};w.prototype.getGridOffset=function(){var a=this.chart,b=this.xAxis,e=this.yAxis;b=this.dataMinX&&this.dataMaxX?b.reversed?b.toPixels(this.dataMaxX):b.toPixels(this.dataMinX):a.plotLeft;a=this.dataMinY&&this.dataMaxY?e.reversed?e.toPixels(this.dataMinY):e.toPixels(this.dataMaxY):a.plotTop;return{plotLeft:b,plotTop:a}};w.prototype.getScaledGridSize= +function(a){var b=this.xAxis,e=!0,f=1,c=1;a=a.processedGridSize||E.layoutAlgorithm.gridSize;this.gridValueSize||(this.gridValueSize=Math.abs(b.toValue(a)-b.toValue(0)));b=b.toPixels(this.gridValueSize)-b.toPixels(0);for(b=+(a/b).toFixed(14);e&&1!==b;){var k=Math.pow(2,f);.75b?e=!1:b>=1/k&&b<1/k*2?(e=!1,c=k):b<=k&&b>k/2&&(e=!1,c=1/k);f++}return a/c/b};w.prototype.getRealExtremes=function(){var a=this.chart,b=this.xAxis,e=this.yAxis;var f=b?b.toValue(a.plotLeft):0;b=b?b.toValue(a.plotLeft+ +a.plotWidth):0;var c=e?e.toValue(a.plotTop):0;a=e?e.toValue(a.plotTop+a.plotHeight):0;f>b&&(f=[f,b],b=f[0],f=f[1]);c>a&&(c=[c,a],a=c[0],c=c[1]);return{minX:f,maxX:b,minY:c,maxY:a}};w.prototype.onDrillToCluster=function(a){(a.point||a.target).firePointEvent("drillToCluster",a,function(a){var b=a.point||a.target,f=b.series.xAxis,c=b.series.yAxis,k=b.series.chart;if((b.series.options.cluster||{}).drillToCluster&&b.clusteredData){var h=b.clusteredData.map(function(a){return a.x}).sort(function(a,b){return a- +b});var m=b.clusteredData.map(function(a){return a.y}).sort(function(a,b){return a-b});b=h[0];var r=h[h.length-1];h=m[0];var g=m[m.length-1];m=Math.abs(.1*(r-b));var l=Math.abs(.1*(g-h));k.pointer.zoomX=!0;k.pointer.zoomY=!0;b>r&&(r=[r,b],b=r[0],r=r[1]);h>g&&(g=[g,h],h=g[0],g=g[1]);k.zoom({originalEvent:a,xAxis:[{axis:f,min:b-m,max:r+m}],yAxis:[{axis:c,min:h-l,max:g+l}]})}})};w.prototype.getClusterDistancesFromPoint=function(a,b,e){var f=this.xAxis,c=this.yAxis,k=[],h;for(h=0;hc[d].oldX+1||c[d].posXc[d].oldY+1||c[d].posYr.minX||this.initMaxY&&this.initMaxYr.minY?(this.initMaxX=r.maxX,this.initMinX=r.minX,this.initMaxY=r.maxY,this.initMinY=r.minY,m=this.markerClusterAlgorithms?this.markerClusterAlgorithms.kmeans.call(this,a,b,e,f):{},this.baseClusters=null):(this.baseClusters||(this.baseClusters={clusters:this.markerClusterInfo.clusters,noise:this.markerClusterInfo.noise}),this.baseClusters.clusters.forEach(function(a){a.pointsOutside=[];a.pointsInside= +[];a.data.forEach(function(b){p=Math.sqrt(Math.pow(c.toPixels(b.x)-c.toPixels(a.x),2)+Math.pow(k.toPixels(b.y)-k.toPixels(a.y),2));q=a.clusterZone&&a.clusterZone.marker&&a.clusterZone.marker.radius?a.clusterZone.marker.radius:g&&g.radius?g.radius:E.marker.radius;l=0<=h-q?h-q:q;p>q+l&&D(a.pointsOutside)?a.pointsOutside.push(b):D(a.pointsInside)&&a.pointsInside.push(b)});a.pointsInside.length&&(m[a.id]=a.pointsInside);a.pointsOutside.forEach(function(b,f){m[a.id+"_noise"+f]=[b]})}),this.baseClusters.noise.forEach(function(a){m[a.id]= +a.data}));return m}};w.prototype.preventClusterCollisions=function(a){var b=this.xAxis,e=this.yAxis,f=a.key.split("-").map(parseFloat),c=f[0],k=f[1],h=a.gridSize,m=a.groupedData,r=a.defaultRadius,g=a.clusterRadius,l=k*h,p=c*h,q=b.toPixels(a.x),u=e.toPixels(a.y);f=[];var d=0,n=0,t=(this.options.cluster||{}).marker,x=(this.options.cluster||{}).zones,v=this.getGridOffset(),w,y,A,B,C,F,G;q-=v.plotLeft;u-=v.plotTop;for(A=1;5>A;A++){var H=A%2?-1:1;var z=3>A?-1:1;H=Math.floor((q+H*g)/h);z=Math.floor((u+ +z*g)/h);H=[z+"-"+H,z+"-"+k,c+"-"+H];for(z=0;z=x[A].from&&d<=x[A].to&&(n=D((x[A].marker||{}).radius)?x[A].marker.radius||0:t&&t.radius?t.radius:E.marker.radius);1B-k?l+g:l+h-g);C!==c&&Math.abs(u-y)C-c?p+g:p+h-g)}});f=b.toValue(q+v.plotLeft);z=e.toValue(u+v.plotTop);m[a.key].posX=f;m[a.key].posY=z;return{x:f,y:z}};w.prototype.isValidGroupedDataObject=function(a){var b=!1,e;if(!N(a))return!1;S(a,function(a){b=!0;if(V(a)&&a.length)for(e=0;e=r){var p=a[l];var q=Math.random().toString(36).substring(2,7)+"-"+Y++;var u=p.length;if(b.zones)for(g=0;g=b.zones[g].from&&u<=b.zones[g].to){var d=b.zones[g];d.zoneIndex=g;var n=b.zones[g].marker;var t=b.zones[g].className}var x= +I(p);"grid"!==b.layoutAlgorithm.type||b.allowOverlap?x={x:x.x,y:x.y}:(g=this.options.marker||{},x=this.preventClusterCollisions({x:x.x,y:x.y,key:l,groupedData:a,gridSize:this.getScaledGridSize(b.layoutAlgorithm),defaultRadius:g.radius||3+(g.lineWidth||0),clusterRadius:n&&n.radius?n.radius:(b.marker||{}).radius||E.marker.radius}));for(g=0;g=k.minX-e&&a.xData[q]<=k.maxX+e&&(a.yData[q]||k.minY)>=k.minY-f&&(a.yData[q]|| +k.maxY)<=k.maxY+f&&(h.push(a.xData[q]),m.push(a.yData[q]),r.push(q))}D(n)&&D(g)&&G(t)&&G(l)&&(a.dataMaxX=n,a.dataMinX=g,a.dataMaxY=t,a.dataMinY=l);k=M(u)?u:a.markerClusterAlgorithms?u&&a.markerClusterAlgorithms[u]?a.markerClusterAlgorithms[u]:h.length