You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gristlabs_grist-core/app/client/widgets/HyperLinkTextBox.js

79 lines
2.5 KiB

var _ = require('underscore');
var dom = require('../lib/dom');
var dispose = require('../lib/dispose');
var kd = require('../lib/koDom');
var TextBox = require('./TextBox');
const G = require('../lib/browserGlobals').get('URL');
const {colors, testId} = require('app/client/ui2018/cssVars');
const {icon} = require('app/client/ui2018/icons');
const {styled} = require('grainjs');
/**
* Creates a widget for displaying links. Links can entered directly or following a title.
* The last entry following a space is used as the url.
* ie 'google https://www.google.com' would apears as 'google' to the user but link to the url.
*/
function HyperLinkTextBox(field) {
TextBox.call(this, field);
}
dispose.makeDisposable(HyperLinkTextBox);
_.extend(HyperLinkTextBox.prototype, TextBox.prototype);
HyperLinkTextBox.prototype.buildDom = function(row) {
var value = row[this.field.colId()];
return cssFieldClip(
kd.style('text-align', this.alignment),
kd.toggleClass('text_wrapping', this.wrapping),
kd.maybe(value, () =>
dom('a',
kd.attr('href', () => _constructUrl(value())),
kd.attr('target', '_blank'),
// As per Google and Mozilla recommendations to prevent opened links
// from running on the same process as Grist:
// https://developers.google.com/web/tools/lighthouse/audits/noopener
kd.attr('rel', 'noopener noreferrer'),
cssLinkIcon('FieldLink'),
testId('tb-link')
)
),
kd.text(() => _formatValue(value()))
);
};
/**
* Formats value like `foo bar baz` by discarding `baz` and returning `foo bar`.
*/
function _formatValue(value) {
// value might be null, at least transiently. Handle it to avoid an exception.
if (typeof value !== 'string') { return value; }
const index = value.lastIndexOf(' ');
return index >= 0 ? value.slice(0, index) : value;
}
/**
* Given value like `foo bar baz`, constructs URL by checking if `baz` is a valid URL and,
* if not, prepending `http://`.
*/
function _constructUrl(value) {
const url = value.slice(value.lastIndexOf(' ') + 1);
try {
// Try to construct a valid URL
return (new G.URL(url)).toString();
} catch (e) {
// Not a valid URL, so try to prefix it with http
return 'http://' + url;
}
}
const cssFieldClip = styled('div.field_clip', `
color: ${colors.lightGreen};
`);
const cssLinkIcon = styled(icon, `
background-color: ${colors.lightGreen};
margin: -1px 2px 2px 0;
`);
module.exports = HyperLinkTextBox;