AutoPagerize_Console

Expansion Autopagerize operation. / AutoPagerizeの操作系を拡張します。

  1. // ==UserScript==
  2. // @name AutoPagerize_Console
  3. // @name:en AutoPagerize_Console
  4. // @name:ja AutoPagerize_Console
  5. // @description Expansion Autopagerize operation. / AutoPagerizeの操作系を拡張します。
  6. // @description:en Expansion Autopagerize operation.
  7. // @namespace phodra
  8. // @include *
  9. // @exclude https://www.youtube.com/*
  10. // @exclude https://docs.google.com/*
  11. // @exclude https://console.developers.google.com/*
  12. // @version 5.4.1
  13. // @noframes
  14. // @grant GM_getValue
  15. // @grant GM_setValue
  16. // @grant GM.getValue
  17. // @grant GM.setValue
  18. // ==/UserScript==
  19.  
  20. (()=>{
  21. // Greasemonkey 4.0未満バージョン対応
  22. if( this.GM == null ){
  23. this.GM = {
  24. getValue: async (name, defVal) => await GM_getValue(name, defVal),
  25. setValue: async (name, value) => await GM_setValue(name, value)
  26. }
  27. }
  28. // 拡張
  29. Array.prototype.first = function(){ return this[0]; }
  30. Array.prototype.last = function(){ return this[this.length-1]; }
  31. Array.prototype.round = function(i){ return this[i<0? 0: i>=this.length? this.length-1: i]; }
  32. Node.prototype.prependChild = function(elm){ this.insertBefore(elm,this.firstChild); }
  33. Element.prototype.css = function(arg1, arg2){
  34. if( arg2 == null){
  35. for( let key in arg1 ){
  36. this.style[key] = arg1[key]
  37. }
  38. }else{
  39. this.style[arg1] = arg2
  40. }
  41. }
  42. Element.prototype.attr = function(arg1, arg2){
  43. if( arg2 == null){
  44. for( let key in arg1 ){
  45. this.setAttribute(key, arg1[key])
  46. }
  47. }else{
  48. this.setAttribute(arg1, arg2)
  49. }
  50. }
  51. // 任意のイベントを発火
  52. const FireEvent = ename => {
  53. const e = document.createEvent('Event')
  54. e.initEvent( ename, true, false)
  55. return document.dispatchEvent(e)
  56. }
  57.  
  58.  
  59.  
  60. // 画像をひとまとめにしておく
  61. const RES = {
  62. 'config': "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAC5SURBVCiRrZI9DsIwDIVfKsQIxyjlBNwC7lFWBq4AKyMrB0C9AGzcBlDFAAh9DE2rNKQoSDzJcvxsyz+x9C8ACTBy7AxIYhILKuRWAAo/rhfIHVi9CXANjK1iJO0lDSVNJPW9uIekk6SrpKkxhrq9MW3cgDWwBV6eL/Nnyx3nwuF3Dp/XfNe27h3vNgKtnoElsAKeoVZ/Xc5F0qxZjlf9wCeOflxoxtLquRWp+obvsCeXOnYadXKxeAMXu9O375dXpAAAAABJRU5ErkJggg==",
  63. 'scrAll': "data:image/png;base64,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6LY0xzroyiAbWQ7nyDd+ePiDFuKl3SBW3f8B8fP2P2is2c4AAABielRYdFJhdyBwcm9maWxlIHR5cGUgaXB0YwAAeNo9icENwDAMAv+eoiPY4KrpOrU//eXR/VUnUgJCAk7e/oUcUw5hc/jtqV7esrRQ8KraCCqNZwUkbZIo8tS28YwIck1V+QEwdRTPIeQRVwAACWppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+Cjx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDQuNC4wLUV4aXYyIj4KIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgZGM6Rm9ybWF0PSJpbWFnZS9wbmciLz4KIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PgD/gEAAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQffDB8MHyAdGHmgAAABB0lEQVQ4y72VLUuEQRRGz6wLKot/QBDNIghazDZBMAsGs2AxWv0V/gPDVvOCxaprsoomYVGLCMKxDDIOr/N+oPvALZd7mDv3YyYgndSDKYP93CFuARetQWAOWP63VENeVXEFOGwNdi5OncQBcATS2NQZ9VK1LXhuVBvo1ERNoQN/6q0JtK1+ZKB10Jr6YoVK0KL6kMQ+1YLqgnqTxD2qJynYq2hwHxgC69H1CuwAk7rJWQVG0QBGgXAnbhbBQBgD48q57rhW+/mlmvTyuFUfI7SrfuZgcR/FDeAKGETXBHgupqouZU0ffh8klAbgNoGu1fk05rcX4AyYBe5jenuB8P4nb870v4AvLySHS1xd+RoAAAAASUVORK5CYII=",
  64. 'scrPage': "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAeCAYAAAAcni9KAAAJXHpUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAHjarZhrllspEoT/s4pZApBAwnJ4ntM7mOXPl1y5HnbZ7fZ0ydKV0BUkGZGRgd3+71/H/Ye/qCW6lLWWVornL7XUYudN9c/fcw0+3dfnb7+u4fO4C9++iAwJV3k+ltd46Izn9x9oeo2Pz+NO52ue+pro28qvCcVWjrwZryBfE0l8xsPrs2uv3/X0YTuv5/m2RX0u339OSjJWZj6JLm5pPMOzihCBZOm8Rl5Fgt3Ep/ue1yjl69w51a+T9/buu9z5/hqXz6lwvrxuKN/l6DUe8te5uxn6hNr7yp++GMk3//HvY+7OqufsZ3c9FTJV3GtT4QnhCYMbwSjJ/VnhoTwz7/U+Go/KFieILT/Bc/jpQgsxiD8hhRV6OGHf6wyTEFPcUbnGOMm4jVXR2OK8oCR7hBNVmiwnFSQmuAnD8S2WcNdtd70ZKiuvwJ0xMJkh+sPDfTX4J4+3ic4xiofg65NuaEFc0ThNGIacvXIXgITzwi2/8svDfeCN/wCsgGC+aa5ssPvxTDFyeOeWXJyF+7JPzj+lEXS9JiBFrJ0JJggI+ALVQwleY9QQyGMFn07kUVIcIBByjiu4AzYiBXBqtLX5jYZ7b8zxGUZaACJLEQWaJh2wUsrwR1OFQz1LTi7nXLLmmlvuRUoquZSixTSqq2jSrEVVqzbtVWqquZaqtdZWe4tNkLDcSlPXamutdxbtTN35deeO3kccMtLIowwddbTRJ/SZaeZZps462+wrLlmU/ypL3aqrrb7Dhko77bzL1l132/3AtSMnnXzK0VNPO/0NtfAq20+ohe+Q+zVq4YWaIZbuffqOGsNXTu4UweQkG2YgFlMAcTUEIHQ0zHwNKUVDzjDzLVIUOYJayAbOCoYYCKYdYj7hDbt35H6Jm8vpH+EWf4acM+j+DeScQfdC7kfcvkBtWd+bF7GnCi2nXg7Cxg279li79aQ/vrr/d4J/NtGeskPZtXWSXs+Osg263Vc5SEqpI7h25j4wZO3Zxiho5ZSWo68bts3QTxd0PqSmpPmcHhRu4hq22BR1Yx28zgCP+NjiWNyBzE4lX5XPexwiIdf39gyz7MOueUPxtka1cXorHqSjOYl2xABv7P3fX1Xb8W3MAEdO3WdmCNjz7k3cWrSElEs66tly373PXKXH7ffOJVR2utdueYalw+uez6Zi9od/x9xFTu04clDME52sxw92m45fpyadSUvrG8bvDTXzyn3TGJvMEVqS0ULz5LHOsOvU4ZZ2izubQXmuGJ3w3dDPrhTzIVP0LCIiNFgvGnp6oGRZAcFURjtCIRyrVE2ZDK85zgJmldXHMjSplHABcZUt7Ri4KY8zVPc6mwRKHtqojXQQ+KapLKqI79acRcLaY045RZmkxUppqmP9+MSy0Jesi+r6Aa/fgNaBacFH5lPZHIEmT1yHUNZc1VY1wZ3zoAGjbyLehFQ69ygATQVn2WNX589qjd2V0g5TPLH1RRTcC2d2kDLW9unQv6AH6pJhw8A+xIV5GL2vPut2E4swoEDamxArFmEfWEPBfLmDn27SfbhneSw3KMiO8QTQ66TfW5Cj6GroZFuHXWziGEiebr4GwtIQL9eseswUiLymwD9cJSvHdgshhAQxETUG9klj2WuQCqaBiQFOCKWNQhrt4cexuZIZpE7KyAZz/UJZsMqfhtzHe0aWtKgQstsn4SPNCH4snYD4FrxaRJrzztkvM4KJbiDCsx6nITfN56L1VpDpyLeC7Gzo0BesHnGGQ2apufNyt40CkYNR6CK6oJGSgsH2BnUwJhQP1gGgO7k0525dhZz9Skbdj7v9tNnNwquZ3qW2CyHB0Nxu3DTInN5kxX29jVP8b0j5xxDch+/GBq+aMMhCxu0DAoUIXEiNpfTbHBFJwG97dmlhjSATL56rs3Zp3nMbJfPlzVPT2qhpStrE85Z0pqRRwyyLPt7shQbMvxWBarg0zCwcHQiibY6ejdMu9HebkhVkz4hQflC1/GSFXygklbmsz7iJ3lzo6fZUsiIAKJPZy4HwFRM8xD2oFpGBKwj4yVYG3MUC6OwtbW/tywGv18CqbLyuNGYapHpI2QO8O6F3BC75fsYqMjq8bzlxaqvkZqY6mWfrmm6xg7z+tg8tNMqnYSwg+CeXeENax059J9kulDMjdUGfqqbBhV7MFlYXXT0eoBNktSHBWW65ivS6Q6ZDAJJUMkYvjcU9/VwlaWXzKxY0e54iHLMPZyM6uSm5hGJtCNJFiJlsG/Vj2Fpvy54qB0GslR66rInYE/A53hHIobHIOEx23cFpakrU2zQkUCKOiLDHLX56jN6XLccYYOnw0Dv302ocveIo8bQmtlqhKNI2JQOu7AVnwmRn2SUr6Aybp5lexqpwMrOWNMf6jRZ5UaDw3AcgLgzEYkBcwCFajfkRFlpkvDRUjMiitVwb8j6jI+so+kjMPLGW56rs5W2BUIfWbhvLlXZlZ2JS2KTAKEBFcR5dZYfBkT5B1bVOvs5nH7KH/bDpN1oMJ751O28SBulf3Q6NR8BigrnWExwnW9qw9eKwrBdXuHEVLFbL+E+uEFFIuMFDTfR5qst495VxxsgwVl3HGrGWHVOu1AwGvWiiFDw9P1FOiqdWWpBZZvNyKI5JHjwqiB8OrAyTtFaQqqk1D+xVQVrMteDOqpZLxgzjzSTBKx8RaBnSpv0/w+4Oj5TLfMeUFnEsvVvICWHbusHTyJrR9AYifWFxUQk0/jRyZq7ALU4D5exdSNYG9DArdSUXdInDHOq6MrNwuFh7yEUbpUBpXIdDicEIngGfbbVlmLS7OqcGOggtddwIzHpgiLOR6pcq7l4yrn7h34padQ0UunDKGbY36iBZ910x4uDYKgtomcAbhu1vBopOQ3PTW29mljQJLb3mSAd/RrerxSYouD8UhCg5GZpBAj+p1vLoDHp5wHFdjAgCUsYDbqN64UFXzlhgv3YqyE81IU6UDZKIMlrXXD4/JmMiQcBvwk2UqDV5qVWfgwHlah3j0XkrSkRi3+5HpozL5yjOk99yoCMDkhyTySP+n2Z7m8uycF4NI8l67oV4NgnHvDIuRDCbwHFEt3N5QTtuwZ7wrB4Wh3b4PwTm08kmHjJ2HAK2ZVTyECopjIn+5vLAsHM8ptQoDvyi+Fmwzwrk9t+gv3smdP/Cme/PJjJz4v4HLs+ZCx2tVfwAAABgelRYdFJhdyBwcm9maWxlIHR5cGUgaXB0YwAAeNo9SckNgDAM+2cKRkjsAGUd0k9/PNhfmEpgy/Jl47rLlomEsSXyyO4p/oge5eCu2Ag6g6sEkjGf0nOqx7vIN0P/qrs9MK8U05SNmcYAAAlqaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA0LjQuMC1FeGl2MiI+CiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIGRjOkZvcm1hdD0iaW1hZ2UvcG5nIi8+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBlbmQ9InciPz4A/4BAAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH3wwfDB8brBOQhAAAAPhJREFUOMvl1LEuREEUh/FvNisiSCRCIqGytQdR06oUFAqF91Do0NJrvIBaK6p9AZWEhGx8miXHdWfvzHbiJNPcO7/8586cuQmZqnrwV2C/FoibwC5I1VCvVGvRQB1NAy8cVw3aUN+/YM2ungAzcZtK0lbVV0OVJh4Dc82D6UpbUp9tVEniEbDY1gqT0ubVJ1uqK/EAWG57kXL3UZwFhsDa+NElcNa5VPUwrOxFXfkxJ4P66jDA01/zMnAvoDd1vROqPfUhwPPWz2mBOwGN1EEpvA/wOnvODbQd0Ie6VQrvAryZ1FXfDSAuAPuhB24T6THXUukf/Mk/Ac1knVlDqEQOAAAAAElFTkSuQmCC",
  65. 'disabled': "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADpSURBVCiRnZIxCsJAEEXfBo0IilhYWIgogo1W1mLnHTyFjVXOEkif1kKvYGsr2NhoaaVo8S2WsGoikiwss/NnHjvsfiMhCqxSctjvYbNxBd+HTgdmM2i1MkgJSSgMEaDBAE0mqN22ue+j1Qo9n7Yv2SlwvXbFywUtFlYPghyghB4P1O+jahVdr073/j1CuQzzOdxusNs5/S8I0O3aeD7nBI2xsVLJCR6PNg6HOcD7HbZb6PVgPHZ66TcChwMsl3A6QRyD935NlgFGI9Ro2LzZRFH0+UUSMolXvy1Xr9vxplOo1dLTmKImfwFplKHHjazaRQAAAABJRU5ErkJggg==",
  66. 'enabled': "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAACESURBVCiRzdIxDkFREIXh74lWh9BolBagYhU2o1CrWYtF2IyK/mokzPPmvRCFmWpOzp+592QqRfFF9cN0xDVxrrDOwD1uWDSA4zbQAzp3vlSv2/JjsAqpTnHBqOba4BCl9z/OsKtp86ad5aUnimVQ0v6HcLIDGOL0HGM4W/nJDdo2flB3ti8tcnms5h0AAAAASUVORK5CYII=",
  67. }
  68.  
  69.  
  70.  
  71. // スタイル
  72. const $style = document.createElement("style")
  73. $style.setAttribute("type", "text/css")
  74. $style.textContent = `
  75. #apc-panel *,
  76. #apc-config * {
  77. color: #eee;
  78. border-color: #666;
  79. }
  80. .apc-box,
  81. #apc-pageList,
  82. #apc-config,
  83. #apc-mButtons {
  84. background-color: #1c1c1c !important;
  85. }
  86. .apc-button {
  87. filter: brightness(100%) contrast(150%);
  88. }
  89. #apc-enabler {
  90. filter: grayscale(100%);
  91. }
  92. #apc-panel[ap_valid] #apc-enabler {
  93. filter: grayscale(60%);
  94. }
  95.  
  96.  
  97. /* コンソールパネル */
  98. #apc-panel {
  99. opacity: 0.6;
  100. background-color: transparent !important;
  101.  
  102. position: fixed;
  103. z-index: 9999999990;
  104. right: 0;
  105. margin: 0;
  106.  
  107. display: inline-flex;
  108. flex-direction: column;
  109. align-items: flex-end;
  110.  
  111. }
  112. #apc-panel[display_rule=valid]:not([ap_valid]) {
  113. visibility: hidden;
  114. }
  115.  
  116. #apc-panel *,
  117. #apc-config * {
  118. font-family: arial, sans-serif;
  119. font-size: 14px;
  120. font-weight: normal;
  121. letter-spacing: normal;
  122. vertical-align: baseline;
  123. line-height: normal;
  124. }
  125. .apc-box {
  126. padding: 1px;
  127. box-sizing: content-box;
  128. min-width: 18px;
  129. /*position: relative;*/
  130. pointer-events: auto;
  131. }
  132. #apc-panel[non_hover='transparent']:not(:hover):not([config]) .apc-box {
  133. background-color: transparent !important;
  134. }
  135. #apc-panel[non_hover='stealth']:not(:hover):not([config]) .apc-box {
  136. visibility: hidden;
  137. }
  138.  
  139. /* ボタンのスタイル */
  140. .apc-button {
  141. border: solid 1px;
  142. box-sizing: border-box;
  143. cursor: pointer;
  144. margin: 1px;
  145. padding: 0;
  146. position: relative;
  147. opacity: 0.5;
  148. width: 16px;
  149. }
  150. .apc-button:hover {
  151. opacity: 0.8;
  152. }
  153. .apc-button:active {
  154. opacity: 0.3;
  155. }
  156. /* ボタンの大きさ */
  157. #apc-optionBox .apc-button {
  158. height: 16px;
  159. }
  160. #apc-scrollerBox .apc-button {
  161. height: 32px;
  162. }
  163.  
  164.  
  165. /* オプションボックス */
  166. #apc-optionBox {
  167. display: flex;
  168. z-index: 9999999991;
  169. }
  170. #apc-enabler[state="enable"] {
  171. background-image: url(${RES.enabled});
  172. }
  173. #apc-enabler[state="disable"] {
  174. background-image: url(${RES.disabled});
  175. }
  176. #apc-setting {
  177. background-image: url(${RES.config});
  178. }
  179. /* optionBox配置形状: */
  180. #apc-panel[ap_valid] #apc-optionBox[option_dir_valid='Left'],
  181. #apc-panel:not([ap_valid]) #apc-optionBox[option_dir_invalid='Left'] {
  182. flex-direction: row-reverse;
  183. }
  184. #apc-panel[ap_valid] #apc-optionBox[option_dir_valid='Right'],
  185. #apc-panel:not([ap_valid]) #apc-optionBox[option_dir_invalid='Right'] {
  186. flex-direction: row;
  187. }
  188. #apc-panel[ap_valid] #apc-optionBox[option_dir_valid^='Up'],
  189. #apc-panel:not([ap_valid]) #apc-optionBox[option_dir_invalid^='Up'] {
  190. flex-direction: column-reverse;
  191. }
  192. #apc-panel[ap_valid] #apc-optionBox[option_dir_valid^='Down'],
  193. #apc-panel:not([ap_valid]) #apc-optionBox[option_dir_invalid^='Down'] {
  194. flex-direction: column;
  195. }
  196. #apc-panel[ap_valid] #apc-optionBox[option_dir_valid='Up_protrude'],
  197. #apc-panel:not([ap_valid]) #apc-optionBox[option_dir_invalid='Up_protrude'] {
  198. margin-top: -18px;
  199. }
  200. #apc-panel[ap_valid] #apc-optionBox[option_dir_valid='Down_protrude'],
  201. #apc-panel:not([ap_valid]) #apc-optionBox[option_dir_invalid='Down_protrude'] {
  202. margin-bottom: -18px;
  203. }
  204.  
  205.  
  206. /* スクローラーボックス */
  207. #apc-scrollerBox {
  208. z-index: 9999999992;
  209. }
  210. #apc-scrollTop,
  211. #apc-scrollBottom {
  212. background-image: url(${RES.scrAll});
  213. }
  214. #apc-scrollPrev,
  215. #apc-scrollNext {
  216. background-image: url(${RES.scrPage});
  217. }
  218. /* scrollerBox配置形状:スリム */
  219. #apc-scrollerBox[scroller_form='Slim'] {
  220. display: flex;
  221. flex-flow: column wrap-reverse;
  222. }
  223. #apc-scrollerBox[scroller_form='Slim'] #apc-scrollTop {
  224. order: 1;
  225. }
  226. #apc-scrollerBox[scroller_form='Slim'] #apc-scrollPrev {
  227. order: 2;
  228. }
  229. #apc-scrollerBox[scroller_form='Slim'] #apc-scrollNext {
  230. order: 3;
  231. transform: scale(1, -1);
  232. }
  233. #apc-scrollerBox[scroller_form='Slim'] #apc-scrollBottom,
  234. #apc-panel:not([ap_valid]) #apc-scrollBottom {
  235. order: 4;
  236. transform: scale(1, -1);
  237. }
  238. /* scrollerBox配置形状:スクエア */
  239. #apc-panel[ap_valid] #apc-scrollerBox[scroller_form='Square'] {
  240. display: grid;
  241. }
  242. #apc-panel[ap_valid] #apc-scrollerBox[scroller_form='Square'] #apc-scrollTop {
  243. grid-row: 1/2;
  244. grid-column: 2/3;
  245. transform: scale(-1, 1);
  246. }
  247. #apc-panel[ap_valid] #apc-scrollerBox[scroller_form='Square'] #apc-scrollBottom {
  248. grid-row: 2/3;
  249. grid-column: 2/3;
  250. transform: scale(-1, -1);
  251. }
  252. #apc-panel[ap_valid] #apc-scrollerBox[scroller_form='Square'] #apc-scrollNext {
  253. grid-row: 2/3;
  254. grid-column: 1/2;
  255. transform: scale(1, -1);
  256. }
  257. #apc-panel[ap_valid] #apc-scrollerBox[scroller_form='Square'] #apc-scrollPrev {
  258. grid-row: 1/2;
  259. grid-column: 1/2;
  260. }
  261.  
  262.  
  263. /* ページボックス */
  264. #apc-pageIndexBox {
  265. cursor: pointer;
  266. z-index: 9999999993;
  267. min-height: 17px;
  268. position: relative;
  269. }
  270. /* ページ表示 */
  271. #apc-sequencer {
  272. margin: 0px 1px;
  273. padding: 0px;
  274. text-align: center;
  275. }
  276. /* pageIndexBox配置形状:縦置き */
  277. #apc-pageIndexBox[page_index_form$='Pile'] #apc-sequencer {
  278. display: flex;
  279. flex-direction: column;
  280. }
  281. #apc-pageIndexBox[page_index_form$='Pile'] span:first-child{
  282. border-bottom: solid 1px #eee !important;
  283. }
  284. /* pageIndexBox配置形状:横置き */
  285. #apc-pageIndexBox[page_index_form='Strip'],
  286. #apc-pageIndexBox[page_index_form='Growed Pile']{
  287. box-sizing: border-box;
  288. width: 100%;
  289. }
  290.  
  291. #apc-pageIndexBox[page_index_form$='Strip'] span:first-child::after{
  292. content: " / ";
  293. }
  294.  
  295. /* ページ一覧 */
  296. #apc-pageList {
  297. position: absolute;
  298. min-width: 38px;
  299.  
  300. margin: 0;
  301. padding: 0px;
  302. list-style-type: none;
  303.  
  304. display: none;
  305. flex-flow: column wrap-reverse;
  306. max-height: 50vh;
  307. }
  308. #apc-pageIndexBox:hover #apc-pageList {
  309. display: flex;
  310. }
  311. #apc-pageIndexBox[page_list_expand^="Left"] #apc-pageList {
  312. right: 100%;
  313. }
  314. #apc-pageIndexBox[page_list_expand^="Right"] #apc-pageList {
  315. left: 100%;
  316. flex-wrap: wrap;
  317. }
  318. #apc-pageIndexBox[page_list_expand$="upper"] #apc-pageList {
  319. bottom: 0;
  320. }
  321. #apc-pageIndexBox[page_list_expand$="lower"] #apc-pageList {
  322. top: 0;
  323. }
  324. #apc-pageIndexBox[page_list_expand="Upper"] #apc-pageList {
  325. right: 0;
  326. bottom: 100%;
  327. }
  328. #apc-pageIndexBox[page_list_expand="Lower"] #apc-pageList {
  329. right: 0;
  330. top: 100%;
  331. }
  332.  
  333. .apc-pageListItem {
  334. border-style: outset;
  335. border-width: 1px;
  336. box-sizing: border-box;
  337. cursor: pointer;
  338. margin: 1px;
  339. padding: 0px;
  340. text-align: center;
  341. }
  342.  
  343. #apc-panel:not([ap_valid]) #apc-scrollPrev,
  344. #apc-panel:not([ap_valid]) #apc-scrollNext,
  345. #apc-panel:not([ap_valid]) #apc-pageIndexBox {
  346. display: none;
  347. }
  348.  
  349. #apc-panel[config]+#apc-configDialog {
  350. display: flex;
  351. }
  352. /* コンフィグメニューダイアログ */
  353. #apc-configDialog {
  354. background-color: transparent !important;
  355. position: fixed;
  356. z-index: 9999999999;
  357.  
  358. top: 0px;
  359. left: 0px;
  360. width: 100%;
  361. height: 100%;
  362.  
  363. display: none;
  364. flex-direction: column;
  365. justify-content: center;
  366. align-items: center;
  367. }
  368. #apc-config {
  369. opacity: 1.0;
  370. border: outset 3px white;
  371. display: inline-block;
  372.  
  373. text-align: left;
  374. padding: 5px 15px;
  375. padding-bottom: 0;
  376. max-height: 90vh;
  377. overflow: scroll;
  378.  
  379. user-select: none;
  380. -moz-user-select: none;
  381. -webkit-user-select: none;
  382. -ms-user-select: none;
  383. }
  384. #apc-config h4 {
  385. display: block;
  386. background-color: transparent;
  387. padding: 0;
  388. padding-bottom: 1px;
  389. margin: 5px 0 2px -5px;
  390. border: solid 0;
  391. border-bottom-width: 1px;
  392. font-weight: bold !important;
  393. }
  394. #apc-config .apc-group {
  395. border: solid 1px;
  396. margin: 0;
  397. margin-top: 10px;
  398. padding: 5px;
  399. font-size: 0;
  400. }
  401. #apc-config .apc-group h5 {
  402. display: inline-block;
  403. margin: 0;
  404. margin-top: -1em;
  405. padding: 0 3px;
  406. background-color: #1c1c1c;
  407. font-weight: bold !important;
  408. }
  409. #apc-config .apc-mItem {
  410. display: block;
  411. margin: 5px 2px 0 2px;
  412. }
  413. #apc-config label {
  414. display: block;
  415. margin: 2px;
  416. cursor: pointer;
  417. }
  418. #apc-config input,
  419. #apc-config select {
  420. background-image: none;
  421. background-color: #000;
  422. border: 2px inset #666;
  423. margin: auto 2px;
  424. cursor: pointer;
  425. border-radius: initial;
  426. padding: initial;
  427. }
  428. #apc-config option {
  429. color: black;
  430. background-color: white;
  431. }
  432. #apc-config input {
  433. width: auto;
  434. height: auto;
  435. padding: 0;
  436. cursor: pointer;
  437. }
  438. #apc-config select,
  439. #apc-config input[type='number'] {
  440. box-sizing: content-box;
  441. height: 19px;
  442. }
  443. #apc-config input[type='number'] {
  444. max-width: 60px;
  445. -webkit-appearance: ;
  446. }
  447. #apc-config select {
  448. max-width: 80px;
  449. }
  450. #apc-config input[type='checkbox'] {
  451. vertical-align: middle;
  452. }
  453. #apc-config #apc-mButtons {
  454. display: flex;
  455. justify-content: stretch;
  456. padding: 15px 0 0 0;
  457. position: sticky;
  458. bottom: 0;
  459. }
  460. #apc-config .apc-config_button {
  461. border: outset 2px;
  462. margin: 0 5px;
  463. width: 100%;
  464. }
  465. `
  466. document.head.appendChild($style)
  467.  
  468.  
  469.  
  470. // コントロール配置
  471. /// パネル(最親)
  472. const $panel = document.createElement("div")
  473. $panel.id = "apc-panel"
  474.  
  475. // ボックスを作成
  476. const $createBox = () => {
  477. const $box = document.createElement("div")
  478. $box.className = "apc-box"
  479. return $box
  480. }
  481. // ボタンを作成
  482. const $createButton = (attr) => {
  483. const $button = document.createElement("div")
  484. $button.className = "apc-button"
  485. $button.attr(attr)
  486. return $button
  487. }
  488.  
  489. ///panel/ オプションボックス
  490. const $optionBox = $createBox()
  491. $optionBox.id = "apc-optionBox"
  492. $panel.appendChild($optionBox)
  493.  
  494. ///panel/optionBox/ オンオフボタン (enable/disable)
  495. const $enabler = $createButton(
  496. { 'id': "apc-enabler" }
  497. )
  498. const apEnable = {
  499. name: "enable",
  500. state: true,
  501. }
  502. ///panel/optionBox// トグルボタン クリックでリクエストイベント発火
  503. $enabler.addEventListener(
  504. 'click', () => FireEvent('AutoPagerizeToggleRequest')
  505. )
  506. $optionBox.appendChild($enabler)
  507.  
  508. // コンフィグメニューを開いているか
  509. ///panel/optionBox/ 設定ボタン
  510. const $setting = $createButton(
  511. {
  512. 'id': "apc-setting",
  513. 'title': "Open Config",
  514. 'alt': "c",
  515. }
  516. )
  517. $optionBox.appendChild($setting)
  518. $setting.addEventListener(
  519. 'click', () => config.open()
  520. )
  521. /// ボタンが見えなくなった時のため、ショートカットで開けるようにする。
  522. /// Alt + Ctrl + p
  523. document.addEventListener(
  524. 'keydown', e => {
  525. if( e.altKey && e.ctrlKey && e.keyCode == 80 ){
  526. config.open()
  527. }
  528. }
  529. )
  530.  
  531. const $spacingBox12 = document.createElement("div")
  532. $spacingBox12.className = "apc-spacing"
  533. $spacingBox12.style.order = 2
  534. $panel.appendChild($spacingBox12)
  535.  
  536. ///panel/ スクロールボックス
  537. const $scrollerBox = $createBox()
  538. $scrollerBox.id = "apc-scrollerBox"
  539. $panel.appendChild($scrollerBox)
  540.  
  541. ///panel/scr/ 最上部へ移動
  542. const $scrollTop = $createButton(
  543. {
  544. 'id': "apc-scrollTop",
  545. 'alt': "↑",
  546. 'title': "Move to Top",
  547. }
  548. )
  549. $scrollerBox.appendChild($scrollTop)
  550. ///panel/scr/ 最下部へ移動
  551. const $scrollBottom = $createButton(
  552. {
  553. 'id': "apc-scrollBottom",
  554. 'alt': "↓",
  555. 'title': "Move to Bottom",
  556. }
  557. )
  558. $scrollerBox.appendChild($scrollBottom)
  559. ///panel/scr/ 前のページ
  560. const $scrollPrev = $createButton(
  561. {
  562. 'id': "apc-scrollPrev",
  563. 'alt': "△",
  564. 'title': "Move to Previous",
  565. }
  566. )
  567. $scrollerBox.appendChild($scrollPrev)
  568. ///panel/scr/ 次のページ
  569. const $scrollNext = $createButton(
  570. {
  571. 'id': "apc-scrollNext",
  572. 'alt': "▽",
  573. 'title': "Move to Next",
  574. }
  575. )
  576. $scrollerBox.appendChild($scrollNext)
  577.  
  578. ///panel/scr/ 最上部へ移動
  579. $scrollTop.addEventListener(
  580. 'click', () => smoothScrollTo(0)
  581. )
  582. ///panel/scr/ 最下部へ移動
  583. $scrollBottom.addEventListener(
  584. 'click', () => smoothScrollTo(getBottomPos)
  585. )
  586. ///panel/scr/ 前のページ
  587. $scrollPrev.addEventListener(
  588. 'click', () => {
  589. smoothScrollTo( pageBounds.round( getNowPage(false) ) )
  590. }
  591. )
  592. ///panel/scr/ 次のページ
  593. $scrollNext.addEventListener(
  594. 'click', () => {
  595. const targetPage = getNowPage()+1
  596. smoothScrollTo(
  597. targetPage < pageBounds.length ?
  598. pageBounds.round(targetPage) :
  599. getBottomPos
  600. )
  601. }
  602. )
  603.  
  604. const $spacingBox23 = document.createElement("div")
  605. $spacingBox23.className = "apc-spacing"
  606. $spacingBox23.style.order = 4
  607. $panel.appendChild($spacingBox23)
  608.  
  609. ///panel/ ページボックス
  610. const $pageIndexBox = $createBox()
  611. $pageIndexBox.id = "apc-pageIndexBox"
  612.  
  613. ///panel/pageIndexBox/ ページ数表示
  614. const $sequencer = document.createElement("div")
  615. $sequencer.id = "apc-sequencer"
  616. const $sequencerNow = document.createElement("span")
  617. const $sequencerMax = document.createElement("span")
  618. $sequencerNow.textContent = $sequencerMax.textContent = "1"
  619. $sequencer.appendChild($sequencerNow)
  620. $sequencer.appendChild($sequencerMax)
  621. $pageIndexBox.appendChild($sequencer)
  622. $panel.appendChild($pageIndexBox)
  623.  
  624. ///panel/pageIndexBox/ ページリスト
  625. const $pageList = document.createElement("ol")
  626. $pageList.id = "apc-pageList"
  627. $pageIndexBox.appendChild($pageList)
  628. // 新しいページリストアイテムにイベントを追加
  629. const $createPageListItem = num => {
  630. const $elm = document.createElement("li")
  631. $elm.className = "apc-pageListItem"
  632. $elm.textContent = num
  633. // クリックでそのページにスクロール
  634. $elm.addEventListener(
  635. 'click', function(){
  636. const targetNum = this.textContent-1
  637. smoothScrollTo( pageBounds.round(targetNum) )
  638. }
  639. )
  640. // // ダブルクリックでページ移動
  641. // $elm.addEventListener(
  642. // 'dblclick', function(){
  643. // const num = this.textContent-2
  644. // if( num >= 0 )
  645. // document.getElementsByClassName("autopagerize_link")[num].href
  646. // }
  647. // )
  648. return $elm
  649. }
  650. $pageList.appendChild( $createPageListItem(1) )
  651.  
  652. document.body.appendChild($panel)
  653.  
  654.  
  655.  
  656.  
  657.  
  658. /// コンフィグメニューを作成
  659. // コンフィグコントロール管理クラス
  660. // 基底クラス
  661. class ConfigControl {
  662. constructor(name, options){
  663. this.name = name
  664. this.defaultValue = options.defaultValue || 0
  665. this.onchange_ = options.onchange || null
  666. }
  667.  
  668. get state(){
  669. return this.value
  670. }
  671. set state(val){
  672. this.value = val
  673. this.onchange()
  674. }
  675. onchange(){
  676. if( typeof(this.onchange_) == "function" ) this.onchange_()
  677. }
  678. getInitial(){
  679. return this.defaultValue || 0
  680. }
  681. setDefault(){
  682. this.state = this.defaultValue
  683. }
  684. restoreState(params){
  685. const val = params[this.name]
  686. if( val == null ){
  687. this.setDefault()
  688. }else{
  689. this.state = val
  690. }
  691. }
  692. /* 仮想関数
  693. * 継承先のクラスでこれらをオーバーライドする
  694. * オーバーライドされていなければバグなのでwarn
  695. */
  696. /* virtual */get value(){
  697. console.warn("virtual get value", this.name)
  698. return null
  699. }
  700. /* virtual */set value(val){
  701. console.warn("virtual set value", this.name)
  702. }
  703. /* virtual */appendTo($to){
  704. console.warn("virtual appendTo", this.name)
  705. }
  706. }
  707. // NumericUpDown管理クラス
  708. class NumericSet extends ConfigControl {
  709. constructor(name, options, attr){
  710. super(name, options)
  711.  
  712. this.$numeric = document.createElement("input")
  713. this.$numeric.type = 'number'
  714. this.$numeric.name = name
  715. this.$numeric.value = this.getInitial()
  716. this.$numeric.attr(attr)
  717.  
  718. this.$numeric.addEventListener(
  719. 'change', () => this.onchange()
  720. )
  721. }
  722. get value(){
  723. if( isNaN(this.$numeric.value) ){
  724. this.$numeric.value = this.defaultValue
  725. }
  726. return this.$numeric.value
  727. }
  728. set value(val){
  729. this.$numeric.value = parseInt(val, 10) || this.defaultValue
  730. }
  731. appendTo($to){
  732. $to.appendChild(this.$numeric)
  733. }
  734. }
  735. // コンボボックス管理クラス
  736. class ComboSet extends ConfigControl{
  737. constructor(name, options){
  738. super(name, options)
  739.  
  740. this.$combo = document.createElement("select")
  741. this.$combo.attr("name", name)
  742. this.$combo.addEventListener(
  743. 'change', () => this.onchange()
  744. )
  745.  
  746. if( options.items != null ){
  747. this.addItems(options.items, this.getInitial())
  748. }
  749.  
  750. }
  751. get value(){
  752. return this.$combo.value
  753. }
  754. set value(val){
  755. this.selectItem(val)
  756. }
  757. addItems(itemParams, sel = null){
  758. itemParams.forEach(
  759. (elm, i) => {
  760. let value, text
  761. if( typeof(elm) == "string" ){
  762. value = text = elm
  763. }else{
  764. value = elm.value
  765. text = elm.text || value
  766. }
  767. const $item = document.createElement("option")
  768. $item.value = value || "option"+i
  769. $item.textContent = text || $item.value
  770. this.$combo.appendChild($item)
  771. }
  772. )
  773. if( sel != null ) this.selectItem(sel)
  774. }
  775. selectItem(target){
  776. if( typeof target == "number" ){
  777. this.$combo.selectedIndex = target
  778. }else if( typeof target == "string" ){
  779. this.$combo.value = target
  780. }
  781. }
  782. appendTo($to){
  783. $to.appendChild(this.$combo)
  784. }
  785. // isDefault(){
  786. // if( typeof this.defaultValue == "number" ){
  787. // return this.$combo.selectedIndex == this.defaultValue
  788. // }else if( typeof this.defaultValue == "string" ){
  789. // return this.$combo.value == this.defaultValue
  790. // }
  791. // return false
  792. // }
  793. }
  794. // ラジオボタン管理クラス
  795. class RadioSet extends ConfigControl {
  796. constructor(name, options){
  797. super(name, options)
  798. this.selected_ = null
  799. this.items = []
  800.  
  801. if( options.items != null ){
  802. this.addItems( options.items, this.getInitial() )
  803. }
  804. }
  805. get state(){
  806. return this.selected_
  807. }
  808. set state(val){
  809. if( val >= 0 && val < this.items.length ){
  810. this.selected_ = val
  811. this.items[val].$radio.checked = true
  812. this.onchange()
  813. }
  814. }
  815. selectedIndex(){
  816. return this.selected_
  817. }
  818. selectedItem(){
  819. let i = this.selectedIndex()
  820. if( i < 0 || i >= this.items.length ){
  821. i = this.defaultValue
  822. }
  823. return this.items[i]
  824. }
  825. // isDefault(){
  826. // return this.selectedIndex() == this.defaultValue
  827. // }
  828.  
  829. addItems(itemParams, sel = null){
  830. itemParams.forEach(
  831. (elm, i) => {
  832. const nameItem = `${this.name}-item-${i}`
  833. const forId = elm.id || nameItem
  834. const value = elm.value || nameItem
  835. const title = elm.title || nameItem
  836. const text = elm.text || nameItem
  837.  
  838. const $label = document.createElement("label")
  839. $label.attr(
  840. {
  841. 'for': forId,
  842. 'title': title,
  843. }
  844. )
  845. const $radio = document.createElement("input")
  846. $radio.attr(
  847. {
  848. 'type': "radio",
  849. 'name': this.name,
  850. 'id': forId,
  851. }
  852. )
  853. $radio.addEventListener(
  854. 'change', () => {
  855. this.selected_ = i
  856. this.onchange()
  857. }
  858. )
  859. $label.appendChild( $radio )
  860. $label.appendChild( document.createTextNode(text) )
  861.  
  862. this.items.push(
  863. {
  864. 'value': value,
  865. '$radio': $radio,
  866. '$label': $label
  867. }
  868. )
  869. }
  870. )
  871.  
  872. if( sel != null ) this.state = sel
  873. }
  874. appendTo($to){
  875. this.items.forEach(
  876. elm => $to.appendChild( elm.$label )
  877. )
  878. }
  879. }
  880.  
  881.  
  882.  
  883. /// コンフィグメニュー
  884. const $config = document.createElement("div")
  885. $config.id = "apc-config"
  886. // バブリングストップ
  887. $config.addEventListener(
  888. 'click', e => e.stopPropagation()
  889. )
  890.  
  891.  
  892. const $createH4 = (title, text) => {
  893. const $h4 = document.createElement("h4")
  894. $h4.title = title
  895. $h4.textContent = text
  896. return $h4
  897. }
  898. ///config/ 表示する条件
  899. $config.appendChild( $createH4(
  900. "APCが表示されるページ",
  901. "The page on which Autopagerize_Console is display")
  902. )
  903. const radioDisplayRule = new RadioSet(
  904. "display_rule",
  905. {
  906. 'onchange': function(){
  907. $panel.attr(this.name, this.selectedItem().value)
  908. },
  909. 'items': [
  910. {
  911. 'id': "apc-mdAlways",
  912. 'value': "always",
  913. 'text': "always",
  914. 'title': "常に表示",
  915. },
  916. {
  917. 'id': "apc-mdValid",
  918. 'value': "valid",
  919. 'text': "only when \"AutoPagerize\" is valid",
  920. 'title': "AutoPagerizeが有効なページであれば表示\n(Alt+Ctrl+pで設定画面を表示)",
  921. }
  922. ]
  923. }
  924. )
  925. // radioDisplayRule.isAlways = function(){
  926. // return this.selectedItem() == 0
  927. // }
  928. // radioDisplayRule.isValid = function(){
  929. // return this.selectedItem() == 1
  930. // }
  931. radioDisplayRule.appendTo($config)
  932.  
  933. ///config/position/ マウスが外れている時の表示
  934. $config.appendChild(
  935. $createH4(
  936. "マウスが外れている時の表示",
  937. "Appearance when non-hover"
  938. )
  939. )
  940. const radioNonHover = new RadioSet(
  941. "non_hover",
  942. {
  943. 'onchange': function(){
  944. $panel.attr(this.name, this.selectedItem().value)
  945. },
  946. 'items': [
  947. {
  948. 'id': "apc-no_change",
  949. 'value': "no_change",
  950. 'text': "No change",
  951. 'title': "変更しない",
  952. },
  953. {
  954. 'id': "apc-transparent",
  955. 'value': "transparent",
  956. 'text': "Transparent",
  957. 'title': "背景を透過",
  958. },
  959. {
  960. 'id': "apc-stealth",
  961. 'value': "stealth",
  962. 'text': "Stealth",
  963. 'title': "隠れる",
  964. }
  965. ]
  966. }
  967. )
  968. radioNonHover.appendTo($config)
  969.  
  970. const $createInputRow = (title, text) => {
  971. const $row = document.createElement("div")
  972. $row.className = "apc-mItem"
  973. $row.title = title
  974. $row.textContent = text
  975. return $row
  976. }
  977. const $createGroupBox = subject => {
  978. const $box = document.createElement("div")
  979. $box.className = "apc-group"
  980. const $subject = document.createElement("h5")
  981. $subject.textContent = subject
  982. $box.appendChild($subject)
  983. return $box
  984. }
  985. /// 位置設定
  986. const UpdatePanelPos = () => {
  987. $panel.style[comboPanelPosY.value] =
  988. numericPanelPosValue.value + comboPanelPosUnit.value
  989. }
  990. const UpdateBoxPos = ($elm, val) => {
  991. $elm.style.height = val+"px"
  992. }
  993. const UpdateAllPositon = () => {
  994. UpdatePanelPos()
  995. UpdateBoxPos( $spacingBox12, numericSpecing12.value)
  996. UpdateBoxPos( $spacingBox23, numericSpecing23.value)
  997. }
  998. ///config/ 位置
  999. $config.appendChild( $createH4( "位置設定", "Expression style") )
  1000.  
  1001. //config/position/ パネル位置
  1002. const $panelPos = $createInputRow(
  1003. "パネル位置",
  1004. "panel position Y:"
  1005. )
  1006. $config.appendChild($panelPos)
  1007.  
  1008. ///config/position/panelPos/ 使用単位
  1009. const comboPanelPosY = new ComboSet(
  1010. "panel_position_y", {
  1011. 'items': [ "top", "bottom"],
  1012. 'onchange': () => {
  1013. $panel.style.removeProperty("top")
  1014. $panel.style.removeProperty("bottom")
  1015. UpdatePanelPos()
  1016. }
  1017. }
  1018. )
  1019. comboPanelPosY.appendTo($panelPos)
  1020. ///config/position/panelPos/ 座標
  1021. const numericPanelPosValue = new NumericSet(
  1022. "panel_position_value", {
  1023. 'defaultValue': 48,
  1024. 'onchange': UpdatePanelPos,
  1025. }
  1026. )
  1027. numericPanelPosValue.appendTo($panelPos)
  1028. ///config/position/panelPos/ 使用単位
  1029. const comboPanelPosUnit = new ComboSet(
  1030. "panel_position_unit", {
  1031. 'items': ["px","%"],
  1032. 'onchange': UpdatePanelPos,
  1033. }
  1034. )
  1035. comboPanelPosUnit.appendTo($panelPos)
  1036.  
  1037. ///config/position/ オプションボックス
  1038. const $optionGroup = $createGroupBox("Option box")
  1039. $config.appendChild($optionGroup)
  1040. ///config/position/optionBox/ 並び順
  1041. const $optionOrder = $createInputRow( "並び順", "Order:")
  1042. $config.appendChild($optionOrder)
  1043. const numericOptionOrder = new NumericSet(
  1044. "option_order",
  1045. {
  1046. 'defaultValue': 1,
  1047. 'onchange': function(){
  1048. $optionBox.style.order = this.value*2-1
  1049. },
  1050. },
  1051. { 'min': 1, 'max': 3}
  1052. )
  1053. numericOptionOrder.appendTo($optionOrder)
  1054. $optionGroup.appendChild($optionOrder)
  1055. /// 展開方向
  1056. const optionDirOptions = {
  1057. 'items':
  1058. [ "Left", "Right", "Up", "Down",
  1059. {value: "Up_protrude", text: "Up (protrude)"},
  1060. {value: "Down_protrude", text: "Down (protrude)"} ],
  1061. 'defaultValue': "Up",
  1062. 'onchange': function(){
  1063. $optionBox.attr(this.name, this.value)
  1064. }
  1065. }
  1066. ///config/position/optionBox/ 有効ページでの展開方向
  1067. const $optionValidForm = $createInputRow(
  1068. "Autopagerizeが有効なページでの展開方向",
  1069. "Direction when AP is valid:"
  1070. )
  1071. const comboOptionDirValid = new ComboSet(
  1072. "option_dir_valid", optionDirOptions
  1073. )
  1074. comboOptionDirValid.appendTo($optionValidForm)
  1075. $optionGroup.appendChild($optionValidForm)
  1076. ///config/position/optionBox/ 対象外ページの展開方向
  1077. const $optionInvalidForm = $createInputRow(
  1078. "Autopagerizeが有効でないページでの展開方向",
  1079. "Direction when AP is invalid:"
  1080. )
  1081. const comboOptionDirInvalid = new ComboSet(
  1082. "option_dir_invalid", optionDirOptions
  1083. )
  1084. comboOptionDirInvalid.appendTo($optionInvalidForm)
  1085. $optionGroup.appendChild($optionInvalidForm)
  1086.  
  1087. ///config/position/scrollerBox/ BOX1とBOX2の間隔
  1088. const $specing12 = $createInputRow(
  1089. "BOX1とBOX2の間隔",
  1090. "Specing between to BOX1 and BOX2:"
  1091. )
  1092. const numericSpecing12 = new NumericSet(
  1093. "spacing_12",
  1094. {
  1095. 'onchange': function(){
  1096. UpdateBoxPos( $spacingBox12, this.value)
  1097. }
  1098. }
  1099. )
  1100. numericSpecing12.appendTo($specing12)
  1101. $specing12.appendChild(document.createTextNode(" px"))
  1102. $config.appendChild($specing12)
  1103.  
  1104. ///config/position/ スクローラーボックス
  1105. const $scrollerGroup = $createGroupBox("Scroller box")
  1106. $config.appendChild($scrollerGroup)
  1107. ///config/position/scrollerBox/ 並び順
  1108. const $scrollerOrder = $createInputRow( "並び順", "Order:")
  1109. $config.appendChild($scrollerOrder)
  1110. const numericScrollerOrder = new NumericSet(
  1111. "scroller_order",
  1112. {
  1113. 'defaultValue': 2,
  1114. 'onchange': function(){
  1115. $scrollerBox.style.order = this.value*2-1
  1116. }
  1117. },
  1118. { 'min': 1, 'max': 3}
  1119. )
  1120. numericScrollerOrder.appendTo($scrollerOrder)
  1121. $scrollerGroup.appendChild($scrollerOrder)
  1122. ///config/position/scrollerBox/ 配置形状
  1123. const $scrollerForm = $createInputRow(
  1124. "配置形状\n(AP対象外ページでは自動的にボタンが2つになるので無視される)",
  1125. "Form when AP is valid:"
  1126. )
  1127. const comboScrollerForm = new ComboSet(
  1128. "scroller_form", {
  1129. 'items': ["Slim","Square"],
  1130. 'onchange': function(){
  1131. $scrollerBox.attr( this.name, this.value)
  1132. }
  1133. }
  1134. )
  1135. comboScrollerForm.appendTo($scrollerForm)
  1136. $scrollerGroup.appendChild($scrollerForm)
  1137.  
  1138. ///config/position/pageIndexBox/ BOX2とBOX3の間隔
  1139. const $specing23 = $createInputRow(
  1140. " BOX2とBOX3の間隔",
  1141. "Specing between to BOX2 and BOX3:"
  1142. )
  1143. const numericSpecing23 = new NumericSet(
  1144. "spacing_23",
  1145. {
  1146. 'onchange': function(){
  1147. UpdateBoxPos( $spacingBox23, this.value)
  1148. }
  1149. }
  1150. )
  1151. numericSpecing23.appendTo($specing23)
  1152. $specing23.appendChild(document.createTextNode(" px"))
  1153. $config.appendChild($specing23)
  1154.  
  1155. ///config/position/ ページインデックスボックス
  1156. const $pageIndexGroup = $createGroupBox("PageIndex box")
  1157. $config.appendChild($pageIndexGroup)
  1158. ///config/position/pageIndexBox/ 並び順
  1159. const $pageIndexOrder = $createInputRow( "並び順", "Order:")
  1160. $config.appendChild($pageIndexOrder)
  1161. const numericPageIndexOrder = new NumericSet(
  1162. "pageindex_order",
  1163. {
  1164. 'defaultValue': 3,
  1165. 'onchange': function(){
  1166. $pageIndexBox.style.order = this.value*2-1
  1167. }
  1168. },
  1169. { 'min': 1, 'max': 3}
  1170. )
  1171. numericPageIndexOrder.appendTo($pageIndexOrder)
  1172. $pageIndexGroup.appendChild($pageIndexOrder)
  1173. ///config/position/pageIndexBox/ 配置形状
  1174. const $pageIndexForm = $createInputRow(
  1175. "配置形状\n(AP対象外ページでは自動的に非表示となるので無視される)",
  1176. "Form when AP is valid:"
  1177. )
  1178. const comboPageIndexForm = new ComboSet(
  1179. "page_index_form",
  1180. {
  1181. 'items': ["Pile", "Strip", "Growed Pile"],
  1182. 'onchange': function(){
  1183. $pageIndexBox.attr( this.name, this.value)
  1184. }
  1185. }
  1186. )
  1187. comboPageIndexForm.appendTo($pageIndexForm)
  1188. $pageIndexGroup.appendChild($pageIndexForm)
  1189. ///config/position/pageIndexBox/ 展開方向
  1190. const $pageListExpand = $createInputRow(
  1191. "展開方向",
  1192. "Page-list expand direction:"
  1193. )
  1194. const comboPageListExpand = new ComboSet(
  1195. "page_list_expand",
  1196. {
  1197. 'items': [
  1198. "Upper", "Lower",
  1199. "Left-upper", "Left-lower",
  1200. "Right-upper", "Right-lower"
  1201. ],
  1202. 'defaultValue': "Lower",
  1203. 'onchange': function(){
  1204. $pageIndexBox.attr( this.name, this.value)
  1205. }
  1206. }
  1207. )
  1208. comboPageListExpand.appendTo($pageListExpand)
  1209. $pageIndexGroup.appendChild($pageListExpand)
  1210.  
  1211.  
  1212.  
  1213. const $mButtons = document.createElement("div")
  1214. $mButtons.id = "apc-mButtons"
  1215. $config.appendChild($mButtons)
  1216.  
  1217. ///config/ 閉じるボタン
  1218. const $mCloseDecision = document.createElement("input")
  1219. $mCloseDecision.attr(
  1220. {
  1221. 'id': "apc-mCloseDecision",
  1222. 'class': "apc-config_button",
  1223. 'type': "button",
  1224. 'value': "OK",
  1225. }
  1226. )
  1227. $mCloseDecision.addEventListener(
  1228. 'click', () => config.close()
  1229. )
  1230. $mButtons.appendChild($mCloseDecision)
  1231. const $mCloseCancel = document.createElement("input")
  1232. $mCloseCancel.attr(
  1233. {
  1234. 'id': "apc-mCloseCancel",
  1235. 'class': "apc-config_button",
  1236. 'type': "button",
  1237. 'value': "Cancel",
  1238. }
  1239. )
  1240. $mCloseCancel.addEventListener(
  1241. 'click', () => config.close(false)
  1242. )
  1243. $mButtons.appendChild($mCloseCancel)
  1244.  
  1245. // コンフィグダイアログ
  1246. const $configDialog = document.createElement("div")
  1247. $configDialog.id = "apc-configDialog"
  1248. $configDialog.addEventListener(
  1249. 'click', () => config.close()
  1250. )
  1251. $configDialog.appendChild($config)
  1252. document.body.appendChild($configDialog)
  1253.  
  1254.  
  1255.  
  1256. class Config {
  1257. constructor(name, options = null){
  1258. this.name = name
  1259. this.tempParams = null
  1260. this.init(options)
  1261. }
  1262. init(options){
  1263. if( options == null ) return
  1264. if( options.items != null ) this.items = options.items
  1265. if( options.onopen != null ) this.onopen_ = options.onopen
  1266. if( options.onclose != null ) this.onclose_ = options.onclose
  1267. }
  1268. open(){
  1269. this.tempParams = this.getParams()
  1270. if( typeof this.onopen_ == "function" ){ this.onopen_(); }
  1271. }
  1272. close(decision = true){
  1273. if( decision ) this.save()
  1274. else this.restore(this.tempParams)
  1275. this.tempParams = null
  1276.  
  1277. if( typeof this.onclose_ == "function" ){ this.onclose_(); }
  1278. }
  1279. restore(params){
  1280. if( params == null ){
  1281. this.items.forEach( elm => elm.setDefault() )
  1282. }else{
  1283. this.items.forEach( elm => elm.restoreState(params) )
  1284. }
  1285. }
  1286. getParams(){
  1287. const params = {}
  1288. this.items.forEach(
  1289. elm => params[elm.name] = elm.state
  1290. )
  1291. return params
  1292. }
  1293. save(){
  1294. GM.setValue( this.name, this.getParams() )
  1295. }
  1296. load(){
  1297. GM.getValue( this.name, null).then(
  1298. result => this.restore(result)
  1299. )
  1300. }
  1301. }
  1302. const config = new Config(
  1303. "config",
  1304. {
  1305. 'onopen': () => $panel.setAttribute("config", true),
  1306. 'onclose': () => {
  1307. $panel.removeAttribute("config")
  1308. UpdateAllPositon()
  1309. },
  1310. 'items': [
  1311. radioDisplayRule, radioNonHover,
  1312. comboPanelPosY,
  1313. numericPanelPosValue, comboPanelPosUnit,
  1314. numericOptionOrder,
  1315. comboOptionDirValid, comboOptionDirInvalid,
  1316. numericSpecing12,
  1317. numericScrollerOrder,
  1318. comboScrollerForm,
  1319. numericSpecing23,
  1320. numericPageIndexOrder,
  1321. comboPageIndexForm,
  1322. comboPageListExpand
  1323. ]
  1324. }
  1325. )
  1326.  
  1327. // enableの変更を反映
  1328. const updateEnable = (toggle = null, save = true) => {
  1329. apEnable.state = toggle === null ? !apEnable.state : toggle
  1330. $enabler.attr(
  1331. apEnable.state ?
  1332. {
  1333. 'state': "enable",
  1334. 'alt': "E",
  1335. 'title': "AutePagerize OFF (Now:Enable)"
  1336. } :
  1337. {
  1338. 'state': "disable",
  1339. 'alt': "D",
  1340. 'title': "AutePagerize ON (Now:Disable)"
  1341. }
  1342. )
  1343. if( save ){
  1344. GM.setValue( apEnable.name, apEnable.state)
  1345. }
  1346. }
  1347. ///panel/optionBox// APイベントをキャプチャー
  1348. document.addEventListener(
  1349. 'AutoPagerizeToggleRequest', () => updateEnable()
  1350. )
  1351. document.addEventListener(
  1352. 'AutoPagerizeEnableRequest', () => updateEnable(true, false)
  1353. )
  1354. document.addEventListener(
  1355. 'AutoPagerizeDisableRequest', () => updateEnable(false, false)
  1356. )
  1357.  
  1358. // リクエストを発行
  1359. const RequestEnableOrDisable = enable => {
  1360. FireEvent( enable ?
  1361. 'AutoPagerizeEnableRequest' :
  1362. 'AutoPagerizeDisableRequest'
  1363. )
  1364. }
  1365.  
  1366. // すべての状態をロードする
  1367. const loadState = () => {
  1368. GM.getValue( apEnable.name, true)
  1369. .then(
  1370. result => {
  1371. apEnable.state = result
  1372. RequestEnableOrDisable(result)
  1373. }
  1374. )
  1375. config.load()
  1376. UpdateAllPositon()
  1377. }
  1378. loadState()
  1379. // タブを切り替えた時にステータスを最新に同期する
  1380. window.document.addEventListener(
  1381. 'visibilitychange',
  1382. () => {
  1383. if( window.document.visibilityState == 'visible' ){
  1384. loadState()
  1385. }
  1386. }
  1387. )
  1388. // AutoPagerize有効なページでのみ行う処理
  1389. const updateApValid = () => {
  1390. setTimeout(
  1391. () => {
  1392. RequestEnableOrDisable(apEnable.state)
  1393. },
  1394. 100
  1395. )
  1396. $panel.attr( "ap_valid", true)
  1397. }
  1398. /// APメッセージバー(アドオン版)かAPアイコン(スクリプト版)が
  1399. /// 存在する、もしくは挿入されると、APが有効なページであるとみなす。
  1400. const apObject =
  1401. document.getElementById("autopagerize_message_bar") ||
  1402. document.getElementById("autopagerize_icon")
  1403. if( apObject != null ){
  1404. updateApValid()
  1405. }else{
  1406. const mo = new MutationObserver(
  1407. mRecs => {
  1408. for( let rec of mRecs ){
  1409. for( let $added of rec.addedNodes ){
  1410. if( ["autopagerize_message_bar", "autopagerize_icon"]
  1411. .includes($added.id) )
  1412. {
  1413. updateApValid()
  1414. mo.disconnect()
  1415. }
  1416. }
  1417. }
  1418. }
  1419. )
  1420. mo.observe( document.body, {'childList': true})
  1421. document.addEventListener(
  1422. 'GM_AutoPagerizeNextPageLoaded',
  1423. () => mo.disconnect()
  1424. )
  1425. }
  1426.  
  1427. let scrTop = document.documentElement.scrollTop
  1428. let oldPage = null
  1429. // ウィンドウのスクロールが発生した時
  1430. window.addEventListener(
  1431. 'scroll',
  1432. () => {
  1433. scrTop = document.documentElement.scrollTop
  1434. // 現在のページを更新
  1435. const np = getNowPage()
  1436. if( np != oldPage ){
  1437. $sequencerNow.textContent = np+1
  1438. oldPage = np
  1439. }
  1440. }
  1441. )
  1442. // 各ページを管理する配列
  1443. let pageBounds = [0]
  1444. // 現在のページを取得(境界線上を前ページとみなす場合false)
  1445. const getNowPage = (notLess=true) => {
  1446. const breakOver = notLess ?
  1447. (st, bound) => st >= bound :
  1448. (st, bound) => st > bound
  1449. let i
  1450. for( i = pageBounds.length-1; i >= 0; i-- ){
  1451. if( breakOver( scrTop, pageBounds[i]) ) break
  1452. }
  1453. return i
  1454. }
  1455. const getBottomPos = () => {
  1456. return Math.max(
  1457. document.body.clientHeight,
  1458. document.body.scrollHeight,
  1459. document.documentElement.scrollHeight,
  1460. document.documentElement.clientHeight) -
  1461. window.innerHeight
  1462. }
  1463.  
  1464. // ページを継ぎ足した時、継ぎ目の位置を記録する
  1465. const apPageAppended = () => {
  1466. // セパレーターの絶対位置を取得
  1467. const $apSep = document.getElementsByClassName("autopagerize_page_separator")
  1468. const len = $apSep.length
  1469.  
  1470. let sepPos = $apSep.item(len-1).getBoundingClientRect().top + window.pageYOffset
  1471. sepPos = Math.round(sepPos)
  1472. if( !pageBounds.includes(sepPos) ){
  1473. pageBounds.push(sepPos)
  1474. }
  1475. $sequencerMax.textContent = len+1
  1476.  
  1477. // ページリストアイテムを追加
  1478. $pageList.appendChild( $createPageListItem(len+1) )
  1479. }
  1480.  
  1481. document.addEventListener(
  1482. 'GM_AutoPagerizeNextPageLoaded',
  1483. () => apPageAppended()
  1484. )
  1485.  
  1486. let scrTick = null
  1487. // 任意の位置にスクロール
  1488. const smoothScrollTo = targetY => {
  1489. // 続けてスクロールさせるとキャンセルして新たなスクロール
  1490. if( scrTick != null ){
  1491. clearTimeout(scrTick)
  1492. scrTick = null
  1493. }
  1494. // 再帰処理部分
  1495. const smoothScrollTick = (_targetY) => {
  1496. // 常に最新の位置をターゲットにしたい場合、引数に関数を渡す
  1497. // (最下部へのスクロール用。
  1498. //  なぜかスクロール途中にページの高さが変わる場合がある)
  1499. let targetY = (typeof(_targetY) == "function" ?
  1500. _targetY() :
  1501. _targetY)
  1502. // 移動量
  1503. let moveY = (targetY-scrTop)/10
  1504. // 終了条件
  1505. let endOver
  1506. // 下方向の移動量調整と終了条件
  1507. if( moveY>0 ){
  1508. moveY = Math.ceil(moveY); //切り上げ
  1509. endOver = scrTop+moveY>=targetY; //ターゲットを越えていれば
  1510. }
  1511. // 上方向の移動量調整と終了条件
  1512. else{
  1513. moveY = Math.floor(moveY); //切り下げ
  1514. endOver = scrTop+moveY<=targetY; //ターゲットを下回っていれば
  1515. }
  1516. // 条件を満たしていれば終了
  1517. if( endOver ){
  1518. window.scrollTo( 0, targetY)
  1519. clearTimeout(scrTick)
  1520. scrTick = null
  1521. }else{
  1522. window.scrollBy( 0, moveY)
  1523. scrTick = setTimeout(
  1524. () => smoothScrollTick(targetY),
  1525. 10
  1526. )
  1527. }
  1528. }
  1529. smoothScrollTick(targetY)
  1530. }
  1531. })()