Online IDE Support JS

Injects elements into a codepen IDE for demonstration purposes

当前为 2022-01-11 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/438329/1007648/Online%20IDE%20Support%20JS.js

  1. // BEGIN SUPPORTING CODE
  2. let delay = 0;
  3. let combinedSteps = `unset`;
  4. let pen = {
  5. nav: undefined,
  6. cmd: undefined,
  7. log: undefined,
  8. hide: ()=> {
  9. pen.nav && (pen.nav.classList.add(`penHidden`));
  10. pen.cmd && (pen.cmd.classList.add(`penHidden`));
  11. pen.log && (pen.log.classList.add(`penHidden`));
  12. },
  13. };
  14. const cmdInfo = {
  15. id: `instructions`,
  16. }
  17. const logInfo = {
  18. id: `logText`,
  19. class: `logContainer`
  20. }
  21. const navInfo = {
  22. id: `penNav`,
  23. class: `penNavigation`,
  24. }
  25.  
  26. const action = (msgcmd, combine) => {
  27. const penHeader = document.getElementById(cmdInfo.id);
  28. const stime = 3000;
  29. combine = combine === `combine` ? true : false;
  30.  
  31. if (combine) {
  32. combinedSteps !== true && (delay += stime);
  33. combinedSteps = true;
  34. } else if(combinedSteps == `unset`) {
  35. delay += stime;
  36. } else if(combinedSteps === true) {
  37. delay += stime/4;
  38. combinedSteps = false;
  39. }
  40. setTimeout(()=> {
  41. if (typeof msgcmd === `string`) {
  42. penHeader.classList.add(`pulse`);
  43. penHeader.innerHTML = msgcmd;
  44. setTimeout(() => {penHeader.classList.remove(`pulse`)}, 1000)
  45. } else {
  46. msgcmd();
  47. }
  48. }, delay);
  49. };
  50.  
  51. const consoleLog = (msg) => {
  52. const logEl = document.getElementById(logInfo.id);
  53. logEl.value = `${msg}\n${logEl.value}`
  54. };
  55.  
  56. const createElement = (nodeType, props) => {
  57. const domNode = document.createElement(nodeType);
  58. if (props && "object" === typeof props) {
  59. for (const prop in props) {
  60. if (prop === "html") {
  61. domNode.innerHTML = props[prop];
  62. } else if (prop === "text") {
  63. domNode.textContent = props[prop];
  64. } else {
  65. if (prop.slice(0, 5) === "aria_" || prop.slice(0, 4) === "data_") {
  66. const attr = prop.slice(0, 4) + "-" + prop.slice(5);
  67. domNode.setAttribute(attr, props[prop]);
  68. } else {
  69. domNode.setAttribute(prop, props[prop]);
  70. }
  71. }
  72. // Set attributes on the element if passed
  73. if (["role", "aria-label"].includes(prop)) domNode.setAttribute(prop, props[prop]);
  74. }
  75. }
  76. return domNode;
  77. };
  78.  
  79. const initialize = () => {
  80. // Add UI elements if not provided
  81. if (!document.getElementById(logInfo.id)) {
  82. addStyle(`
  83. body {
  84. padding: 0 4rem;
  85. }
  86.  
  87. .penNavigationLabel {
  88. background: aliceblue;
  89. color: blue;
  90. position: relative;
  91. top: 0px;
  92. left: -35px;
  93. float: left;
  94. max-width: 6rem;
  95. text-align: right;
  96. padding: 0.1rem 0.265rem;
  97. transform: rotate(-90deg);
  98. }
  99.  
  100. .pulse {
  101. animation: pulse 1s 1;
  102. }
  103.  
  104. @keyframes pulse {
  105. 0% {
  106. background-color: #001F3F;
  107. }
  108. 100% {
  109. background-color: #FFFFFF;
  110. }
  111. }
  112.  
  113. .logClosed {
  114. left: -90%;
  115. }
  116. .logContainer {
  117. position: absolute;
  118. z-index: 9999;
  119. width: 80%;
  120. top: 50%;
  121. margin-left: 10%;
  122. }
  123. .logContainerLabel {
  124. background: black;
  125. color: white;
  126. position: relative;
  127. float: right;
  128. top: 44px;
  129. left: 47px;
  130. max-width: 6rem;
  131. text-align: right;
  132. padding: 0.1rem 0.265rem;
  133. transform: rotate(-90deg);
  134. cursor: pointer;
  135. }
  136. #logText {
  137. width:100%;
  138. height:20rem;
  139. color:white;
  140. background:black;
  141. font-size: 0.7rem;
  142. font-family: monospace;
  143. line-height: 0.9rem;
  144. }
  145.  
  146. .penNavigation {
  147. background: aliceblue;
  148. min-height: 3rem;
  149. margin-bottom: 0.625rem;
  150. padding: 0.625rem;
  151. z-index: 9999;
  152. position: relative;
  153.  
  154. .dds__button--sm {
  155. margin-right: 0.25rem;
  156. }
  157. }
  158.  
  159. .penHidden {
  160. display: none;
  161. }
  162. `)
  163. const logEl = createElement(`div`, {
  164. class: `${logInfo.class} logClosed`,
  165. });
  166. const logLabel = createElement(`div`, {
  167. id: `${logInfo.id}Label`,
  168. class: `${logInfo.class}Label`,
  169. text: `console`
  170. });
  171. logEl.appendChild(logLabel);
  172. const textEl = createElement(`textarea`, {
  173. id: logInfo.id,
  174. });
  175. logEl.appendChild(textEl);
  176. document.querySelector(`body`).prepend(logEl);
  177. logLabel.addEventListener(`click`, (e) => {
  178. logEl.classList.toggle('logClosed');
  179. })
  180. }
  181.  
  182. if (!document.getElementById(cmdInfo.id)) {
  183. const instrEl = createElement(`h5`, {
  184. id: cmdInfo.id,
  185. text: ``,
  186. });
  187. document.querySelector(`body`).prepend(instrEl);
  188. }
  189.  
  190. if (!document.getElementById(navInfo.id)) {
  191. const navEl = createElement(`div`, {
  192. class: navInfo.class,
  193. id: navInfo.id,
  194. });
  195. const navLabel = createElement(`div`, {
  196. id: `${navInfo.id}Label`,
  197. class: `${navInfo.class}Label`,
  198. text: `api`
  199. });
  200. navEl.appendChild(navLabel);
  201. document.querySelector(`body`).prepend(navEl);
  202. }
  203.  
  204. pen.nav = document.getElementById(navInfo.id);
  205. pen.cmd = document.getElementById(cmdInfo.id);
  206. pen.log = document.getElementById(logInfo.id);
  207. };
  208.  
  209. const addPenButton = (lText, lAction) => {
  210. if (typeof lText === `string`) {
  211. const newButton = createElement(`button`, {
  212. class: `dds__button dds__button--sm`,
  213. text: lText
  214. });
  215. newButton.addEventListener(`click`, (e) => {
  216. lAction();
  217. });
  218. pen.nav.appendChild(newButton);
  219. } else { // presume we are moving an existing element to the pen nav
  220. pen.nav.appendChild(lText);
  221. }
  222. };
  223.  
  224. const addStyle = (styles) => {
  225. /* Create style document */
  226. var css = document.createElement('style');
  227. css.type = 'text/css';
  228.  
  229. if (css.styleSheet)
  230. css.styleSheet.cssText = styles;
  231. else
  232. css.appendChild(document.createTextNode(styles));
  233.  
  234. /* Append style to the tag name */
  235. document.getElementsByTagName("head")[0].appendChild(css);
  236. }
  237.  
  238.  
  239. const runDemo = (demo) => {
  240. consoleLog(`\n${demo.selector} has the following events: ${demo.events}`);
  241.  
  242. demo.events.forEach((ev)=>{
  243. document.addEventListener(ev, (e)=> {
  244. consoleLog(ev + "\n" + JSON.stringify(e));
  245. })
  246. })
  247.  
  248. let hasDispose = false;
  249. Object.keys(demo.component).forEach(key=>{
  250. if (typeof demo.component[key] === `function`) {
  251. if (key !== `dispose`) {
  252. addPenButton(key, demo.component[key]);
  253. } else {
  254. hasDispose = true;
  255. }
  256. } else {
  257. consoleLog(`
  258. ${demo.selector} has the property:
  259. .${key} = ${demo.component[key]}
  260. (open console to see more details)`);
  261. console.log(demo.component[key]);
  262. }
  263. })
  264.  
  265. hasDispose && (addPenButton(`dispose`, ()=>{
  266. demo.component[`dispose`]();
  267. pen.nav.querySelectorAll(`button`).forEach(b=>b.disabled = `true`);
  268. }));
  269. };
  270.  
  271. initialize();
  272.  
  273. // END SUPPORTING CODE
  274.  
  275. /*
  276. pen.hide();
  277. */
  278. /*
  279. runDemo({
  280. selector: `more-less`,
  281. events: [`ddsMoreLessExpandEvent`, `ddsMoreLessCollapseEvent`],
  282. component: {
  283. property1: `soidjsoaidjo`,
  284. method1: ()=>{}
  285. },
  286. });
  287. */