summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/devtools/front_end/ui/XLink.js
blob: a29a72afdc36f6ddd56c00391f2d81a5fee537bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @extends {UI.XElement}
 */
UI.XLink = class extends UI.XElement {
  /**
   * @param {string} url
   * @param {string=} linkText
   * @param {string=} className
   * @param {boolean=} preventClick
   * @return {!Element}
   */
  static create(url, linkText, className, preventClick) {
    if (!linkText)
      linkText = url;
    className = className || '';
    // clang-format off
    // TODO(dgozman): migrate css from 'devtools-link' to 'x-link'.
    return UI.html`
        <x-link href='${url}' class='${className} devtools-link' ${preventClick ? 'no-click' : ''}
        >${linkText.trimMiddle(UI.MaxLengthForDisplayedURLs)}</x-link>`;
    // clang-format on
  }

  constructor() {
    super();

    this.style.setProperty('display', 'inline');
    UI.ARIAUtils.markAsLink(this);
    this.tabIndex = 0;
    this.setAttribute('target', '_blank');

    /** @type {?string} */
    this._href = null;
    this._clickable = true;

    this._onClick = event => {
      event.consume(true);
      InspectorFrontendHost.openInNewTab(/** @type {string} */ (this._href));
    };
    this._onKeyDown = event => {
      if (event.key !== ' ' && !isEnterKey(event))
        return;
      event.consume(true);
      InspectorFrontendHost.openInNewTab(/** @type {string} */ (this._href));
    };
  }

  /**
   * @return {!Array<string>}
   */
  static get observedAttributes() {
    // TODO(dgozman): should be super.observedAttributes, but it does not compile.
    return UI.XElement.observedAttributes.concat(['href', 'no-click']);
  }

  /**
   * @param {string} attr
   * @param {?string} oldValue
   * @param {?string} newValue
   * @override
   */
  attributeChangedCallback(attr, oldValue, newValue) {
    if (attr === 'no-click') {
      this._clickable = !newValue;
      this._updateClick();
      return;
    }

    if (attr === 'href') {
      let href = newValue;
      if (newValue.trim().toLowerCase().startsWith('javascript:'))
        href = null;
      if (Common.ParsedURL.isRelativeURL(newValue))
        href = null;

      this._href = href;
      this.title = newValue;
      this._updateClick();
      return;
    }

    super.attributeChangedCallback(attr, oldValue, newValue);
  }

  _updateClick() {
    if (this._href !== null && this._clickable) {
      this.addEventListener('click', this._onClick, false);
      this.addEventListener('keydown', this._onKeyDown, false);
      this.style.setProperty('cursor', 'pointer');
    } else {
      this.removeEventListener('click', this._onClick, false);
      this.removeEventListener('keydown', this._onKeyDown, false);
      this.style.removeProperty('cursor');
    }
  }
};

/**
 * @implements {UI.ContextMenu.Provider}
 */
UI.XLink.ContextMenuProvider = class {
  /**
   * @override
   * @param {!Event} event
   * @param {!UI.ContextMenu} contextMenu
   * @param {!Object} target
   */
  appendApplicableItems(event, contextMenu, target) {
    let targetNode = /** @type {!Node} */ (target);
    while (targetNode && !(targetNode instanceof UI.XLink))
      targetNode = targetNode.parentNodeOrShadowHost();
    if (!targetNode || !targetNode._href)
      return;
    contextMenu.revealSection().appendItem(
        UI.openLinkExternallyLabel(), () => InspectorFrontendHost.openInNewTab(targetNode._href));
    contextMenu.revealSection().appendItem(
        UI.copyLinkAddressLabel(), () => InspectorFrontendHost.copyText(targetNode._href));
  }
};

self.customElements.define('x-link', UI.XLink);