inspector.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. window.onload = function () {
  2. // Use menu API to show context menu.
  3. window.InspectorFrontendHost.showContextMenuAtPoint = createMenu
  4. // Use dialog API to override file chooser dialog.
  5. window.WebInspector.createFileSelectorElement = createFileSelectorElement
  6. }
  7. const convertToMenuTemplate = function (items) {
  8. return items.map(function (item) {
  9. const transformed = item.type === 'subMenu' ? {
  10. type: 'submenu',
  11. label: item.label,
  12. enabled: item.enabled,
  13. submenu: convertToMenuTemplate(item.subItems)
  14. } : item.type === 'separator' ? {
  15. type: 'separator'
  16. } : item.type === 'checkbox' ? {
  17. type: 'checkbox',
  18. label: item.label,
  19. enabled: item.enabled,
  20. checked: item.checked
  21. } : {
  22. type: 'normal',
  23. label: item.label,
  24. enabled: item.enabled
  25. }
  26. if (item.id != null) {
  27. transformed.click = function () {
  28. window.DevToolsAPI.contextMenuItemSelected(item.id)
  29. return window.DevToolsAPI.contextMenuCleared()
  30. }
  31. }
  32. return transformed
  33. })
  34. }
  35. const createMenu = function (x, y, items) {
  36. const {remote} = require('electron')
  37. const {Menu} = remote
  38. let template = convertToMenuTemplate(items)
  39. if (useEditMenuItems(x, y, template)) {
  40. template = getEditMenuItems()
  41. }
  42. const menu = Menu.buildFromTemplate(template)
  43. // The menu is expected to show asynchronously.
  44. setTimeout(function () {
  45. menu.popup(remote.getCurrentWindow())
  46. })
  47. }
  48. const useEditMenuItems = function (x, y, items) {
  49. return items.length === 0 && document.elementsFromPoint(x, y).some(function (element) {
  50. return element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA' || element.isContentEditable
  51. })
  52. }
  53. const getEditMenuItems = function () {
  54. return [
  55. {
  56. role: 'undo'
  57. },
  58. {
  59. role: 'redo'
  60. },
  61. {
  62. type: 'separator'
  63. },
  64. {
  65. role: 'cut'
  66. },
  67. {
  68. role: 'copy'
  69. },
  70. {
  71. role: 'paste'
  72. },
  73. {
  74. role: 'pasteandmatchstyle'
  75. },
  76. {
  77. role: 'delete'
  78. },
  79. {
  80. role: 'selectall'
  81. }
  82. ]
  83. }
  84. const showFileChooserDialog = function (callback) {
  85. const {dialog} = require('electron').remote
  86. const files = dialog.showOpenDialog({})
  87. if (files != null) {
  88. callback(pathToHtml5FileObject(files[0]))
  89. }
  90. }
  91. const pathToHtml5FileObject = function (path) {
  92. const fs = require('fs')
  93. const blob = new Blob([fs.readFileSync(path)])
  94. blob.name = path
  95. return blob
  96. }
  97. const createFileSelectorElement = function (callback) {
  98. const fileSelectorElement = document.createElement('span')
  99. fileSelectorElement.style.display = 'none'
  100. fileSelectorElement.click = showFileChooserDialog.bind(this, callback)
  101. return fileSelectorElement
  102. }