webcomp.html 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <style>
  2. .webcomp-sc {
  3. position: relative;
  4. color: var(--MAIN-TITLES-TEXT-color);
  5. }
  6. .comp-container {
  7. margin-right: 30px;
  8. transition: margin-right .5s ease-in-out;
  9. }
  10. .webcomp-sc.expanded .comp-container {
  11. margin-right: 250px;
  12. }
  13. // customizer panel
  14. .customizer-panel {
  15. position: absolute;
  16. top: 0px;
  17. right: 0px;
  18. overflow: hidden;
  19. width: 25px;
  20. height: 100%;
  21. border: 1px solid #d6d8db;
  22. border-radius: 5px;
  23. padding: 3px 5px;
  24. transition: width .5s ease-in-out;
  25. }
  26. .webcomp-sc.expanded .customizer-panel {
  27. width: 245px;
  28. }
  29. // customizer panel content
  30. .customizer-panel .panel-content {
  31. height: 100%;
  32. margin-left: 20px;
  33. transition: margin-left .5s ease-in-out;
  34. display: flex;
  35. flex-direction: column;
  36. }
  37. .webcomp-sc.expanded .customizer-panel .panel-content {
  38. margin-left: 0;
  39. }
  40. .webcomp-sc.hide-events .wc-events {
  41. display: none;
  42. }
  43. .customizer-panel .panel-content textarea {
  44. width: 232px;
  45. margin-bottom: 5px;
  46. resize: none;
  47. font-family: "Lucida Console", Courier, monospace;
  48. font-size: .7em;
  49. white-space: pre;
  50. }
  51. .customizer-panel .panel-content .attributes-txt {
  52. flex: 4;
  53. }
  54. .customizer-panel .panel-content .events-txt {
  55. flex: 1;
  56. }
  57. // Expand collapse button
  58. .customizer-panel .exp-collapse-button {
  59. position: absolute;
  60. right: 5px;
  61. top: 3px;
  62. height: 100%;
  63. display: inline-block;
  64. user-select: none;
  65. }
  66. .customizer-panel .exp-collapse-button em.fa-plus {
  67. transition: transform .5s ease-in-out;
  68. }
  69. .webcomp-sc.expanded .customizer-panel .exp-collapse-button em.fa-plus {
  70. transform: rotate(45deg);
  71. }
  72. .customizer-panel .exp-collapse-button .cust-txt {
  73. position: absolute;
  74. left: -5px;
  75. top: 50%;
  76. margin-top: -50px;
  77. writing-mode: vertical-rl;
  78. color: var(--MAIN-TITLES-TEXT-color);
  79. letter-spacing: .15em;
  80. transition: left .2s ease-in-out;
  81. }
  82. .webcomp-sc.expanded .customizer-panel .exp-collapse-button .cust-txt {
  83. left: 20px;
  84. }
  85. </style>
  86. <div class="webcomp-sc">
  87. <script type = "text/javascript" src={{ .Get "src" }}></script>
  88. <div class="comp-container"></div>
  89. <div class="customizer-panel">
  90. <div class="panel-content">
  91. <b>Attributes</b>
  92. <textarea class="attributes-txt"></textarea>
  93. <b class="wc-events">Events</b>
  94. <textarea class="wc-events events-txt" readonly></textarea>
  95. </div>
  96. <div class="exp-collapse-button">
  97. <a href="javascript:void(0);"><em class="fa fa-plus"></em></a>
  98. <span class="cust-txt">Customize</span>
  99. </div>
  100. </div>
  101. </div>
  102. <script type = "text/javascript">
  103. function initWebcomp() {
  104. const webcomps = document.querySelectorAll(".webcomp-sc");
  105. const currentWebcomp = webcomps[webcomps.length - 1];
  106. currentWebcomp.querySelector(".exp-collapse-button a")
  107. .addEventListener("click", event => {
  108. currentWebcomp.classList.toggle("expanded");
  109. });
  110. return currentWebcomp;
  111. }
  112. function createComponent(name, innerHTML) {
  113. const webcomp = initWebcomp();
  114. const container = webcomp.querySelector(".comp-container");
  115. const eventsTxtArea = webcomp.querySelector("textarea.events-txt");
  116. const attributesTextArea = webcomp.querySelector("textarea.attributes-txt");
  117. const component = document.createElement(name);
  118. component.innerHTML = innerHTML;
  119. container.appendChild(component);
  120. return {webcomp, component, eventsTxtArea, attributesTextArea};
  121. }
  122. function loadAttrs(url, callback) {
  123. fetch(url)
  124. .then(response => response.json())
  125. .then(json => callback(json));
  126. }
  127. (function ({webcomp, component, eventsTxtArea, attributesTextArea}, params){
  128. const attrsPrefix = "-";
  129. // Init attributes
  130. function initAttrs(attrs) {
  131. Object.assign(component, attrs);
  132. attributesTextArea.value = JSON.stringify(attrs, null, 2);
  133. }
  134. if(params.attrSrc) {
  135. loadAttrs(params.attrSrc, initAttrs);
  136. } else {
  137. const attrs = params.filter(param => param.startsWith(attrsPrefix));
  138. initAttrs(params);
  139. }
  140. attributesTextArea.addEventListener("input", function () {
  141. Object.assign(component, JSON.parse(attributesTextArea.value));
  142. });
  143. // Add event listeners
  144. function handleEvent(propertyName, event) {
  145. console.log("Event triggered:", event, $);
  146. let eventTxt = event.type;
  147. const eventProp = event.detail[0][propertyName];
  148. if(eventProp) {
  149. eventTxt = `${eventTxt} : ${eventProp}`;
  150. }
  151. eventsTxtArea.value += `${eventTxt}\r\n`;
  152. eventsTxtArea.scrollTop = eventsTxtArea.scrollHeight;
  153. }
  154. if(params.events) {
  155. params.events.split(",").forEach(event => {
  156. const [eventName, propertyName] = event.split(":");
  157. component.addEventListener(eventName, handleEvent.bind(this, propertyName));
  158. });
  159. } else {
  160. webcomp.classList.add("hide-events");
  161. }
  162. })(
  163. createComponent({{ .Get "name" }}, {{ .Inner }}),
  164. {{ .Params }}
  165. );
  166. </script>