src/controls/HelpButton.js
import $ from 'jquery'
import JSON5 from 'json5'
import { Control } from './Control'
import { checkFor, finishAllImages, mixin } from '../utilities'
import { Debug } from '../Debug'
import '../../less/helpbutton.less'
import 'polyfill!Array.prototype.includes'
import { ActivatableMixin } from './ActivatableMixin'
import { cssClasses } from '../globals'
/**
* @typedef {g4uControlOptions} HelpButtonOptions
* @property {object} [configControls={}]
* @property {string} fileName of the json with the helptexts
* @property {boolean} [active=false]
*/
/**
* Shows a help button. Loads an json file with the helptexts and images from the server.
*/
export class HelpButton extends mixin(Control, ActivatableMixin) {
/**
* @param {HelpButtonOptions} options
*/
constructor (options) {
options.element = $('<div>')[0]
options.className = options.className || 'g4u-helpbutton'
super(options)
this.setTitle(this.getTitle() || this.getLocaliser().localiseUsingDictionary('HelpButton title'))
this.setTipLabel(this.getTipLabel() || options.localiser.localiseUsingDictionary('HelpButton tipLabel'))
/**
* @type {object}
* @private
*/
this.configControls_ = options.configControls || {}
/**
* @type {string}
* @private
*/
this.documentationFileName_ = options.fileName
}
createContent_ () {
const localiser = this.getMap().get('localiser')
const documentationObject = JSON5.parse(this.contentData_)
if (checkFor(documentationObject, localiser.getCurrentLang())) {
this.language = localiser.getCurrentLang()
} else if (checkFor(documentationObject, localiser.getDefaultLang())) {
this.language = localiser.getDefaultLang()
} else {
this.language = 'de'
}
const makeDocumentationTable = (documentation, language) => {
const $table = $('<table>').addClass(this.className_ + '-table')
if (localiser.isRtl()) {
$table.prop('dir', 'rtl')
}
const documentationLocalized = documentationObject[language]
let id
let imgData
let descrData
let joinWith
let imgElements
let $row
let $td
let visibleControls = []
if (this.configControls_ && this.configControls_.hasOwnProperty('onMap')) {
const findContainedControls = controlNamesArr => {
visibleControls = visibleControls.concat(controlNamesArr.map(name => {
return this.configControls_.hasOwnProperty(name) && this.configControls_[name].hasOwnProperty('controlType')
? this.configControls_[name].controlType : name
}))
for (const controlName of controlNamesArr) {
if (this.configControls_.hasOwnProperty(controlName)) {
if (this.configControls_[controlName].hasOwnProperty('contains')) {
findContainedControls(this.configControls_[controlName].contains)
}
}
}
}
if (!this.getMap().get('mobile')) {
findContainedControls(this.configControls_.onMap.filter(c => c !== 'mobileControls'))
} else if (this.configControls_.hasOwnProperty('mobileControls') &&
this.configControls_.mobileControls.hasOwnProperty('contains')) {
findContainedControls(this.configControls_.mobileControls.contains)
}
}
if (documentationLocalized.hasOwnProperty('help-header') && documentationLocalized['help-header']) {
descrData = documentationLocalized['help-header'].descr || ''
joinWith = documentationLocalized['help-header'].joinWith || ''
$row = $('<tr>').addClass(this.className_ + '-header')
$td = $('<td>').addClass(this.className_ + '-descr').attr('colspan', 2)
if ($.isArray(descrData)) {
$td.append(descrData.join('<p>'))
} else {
$td.append(descrData)
}
$row.append($td)
$table.append($row)
}
for (id in documentationLocalized) {
if (documentationLocalized.hasOwnProperty(id) && documentationLocalized[id]) {
imgData = documentationLocalized[id].img
descrData = documentationLocalized[id].descr || ''
joinWith = documentationLocalized[id].joinWith || ''
if (visibleControls.includes(id)) {
$row = $('<tr>')
imgElements = `<td class="${this.className_}-img"><div class="${this.className_}-imgDiv">`
if (imgData) {
if ($.isArray(imgData)) {
for (let j = 0, jj = imgData.length; j < jj; j++) {
imgData[j] = `<img class="${this.className_}-docuImg" src="images/${imgData[j]}">`
}
imgElements += imgData.join(joinWith)
} else {
imgElements += `<img class="${this.className_}-docuImg" src="images/${imgData}">`
}
}
imgElements += '</div></td>'
$row.append(imgElements)
$td = $('<td>').addClass(this.className_ + '-descr')
if ($.isArray(descrData)) {
$td.append(descrData.join('<p>'))
} else {
$td.append(descrData)
}
$row.append($td)
$table.append($row)
}
}
}
return $table
}
this.get$Element().append(makeDocumentationTable(documentationObject, this.language))
}
/**
* @param {G4UMap} map
*/
setMap (map) {
super.setMap(map)
if (map) {
this.activateOnMapChange()
}
}
/**
* @param {boolean} active
*/
setActive (active) {
if (!this.loading_) {
if (active) {
if (!this.contentData_) {
this.loading_ = true
$.ajax(this.documentationFileName_, { dataType: 'text' })
.fail(() => {
const msg = 'Wasn\'t able to load the documentation file ' + this.documentationFileName_
Debug.error(msg)
throw new Error(msg)
})
.done(data => {
this.contentData_ = data
this.createContent_()
finishAllImages(this.get$Element()).then(() => {
this.loading_ = false
this.dispatchEvent('loaded')
super.setActive(active)
})
})
} else {
super.setActive(active)
}
} else {
super.setActive(active)
}
} else {
this.once('loaded', () => this.setActive(active))
}
this.get$Element().toggleClass(cssClasses.active, active)
}
}