11<!DOCTYPE html>
22< html >
3+
34< head >
45 < title > JavaScript Injector</ title >
56</ head >
7+
68< body >
79 < div id ="JavaScriptInjectorConfigPage " data-role ="page " class ="page type-interior pluginConfigurationPage ">
810 < div data-role ="content ">
911 < div class ="content-primary ">
1012 < form id ="JavaScriptInjectorConfigForm ">
1113 < div class ="verticalSection verticalSection-extrabottompadding ">
1214 < div class ="sectionTitleContainer flex align-items-center ">
13- < h2 class ="sectionTitle "> JavaScript Injector Settings</ h2 >
15+ < h2 class ="sectionTitle "> JavaScript Injector</ h2 >
16+ < a is ="emby-linkbutton " class ="raised raised-mini emby-button " style ="margin-left: 2em; "
17+ target ="_blank " href ="https://github.com/n00bcodr/Jellyfin-JavaScript-Injector ">
18+ < i class ="md-icon button-icon button-icon-left secondaryText "> </ i >
19+ < span > Help</ span >
20+ </ a >
1421 </ div >
15-
22+ < hr > < br >
1623 < div id ="scriptsContainer " class ="verticalSection-extrabottompadding ">
17- </ div >
24+ <!-- Script entries will be dynamically inserted here -->
25+ </ div >
1826
1927 < div class ="verticalSection ">
2028 < button is ="emby-button " type ="button " id ="addScriptBtn " class ="raised button-submit block ">
2129 < span > Add Script</ span >
2230 </ button >
2331 </ div >
24-
2532 < br />
26- < div class ="infoBox ">
27- < p class ="infoBoxText ">
28- < strong > ℹ️</ strong > Changes require a browser refresh to take effect. Scripts marked with 'Requires Authentication' will only be loaded for authenticated users.
29- </ p >
33+ < div
34+ style ="background-color: rgba(255, 255, 255, 0.05); border-left: 4px solid #00a4dc; border-radius: 4px; padding: 1em 1.5em; margin: 1.5em 0; display: flex; align-items: center; gap: 1em; ">
35+ < i class ="material-icons " style ="color: #00a4dc; font-size: 24px; "> info</ i >
36+ < div >
37+ Changes require a browser refresh to take effect. < br />
38+ Scripts marked with 'Requires Authentication' will only be loaded for authenticated
39+ users.
40+ </ div >
3041 </ div >
31-
3242 < div >
3343 < button is ="emby-button " type ="submit " class ="raised button-submit block ">
3444 < span > Save</ span >
@@ -40,18 +50,21 @@ <h2 class="sectionTitle">JavaScript Injector Settings</h2>
4050 </ div >
4151
4252 < template id ="script-entry-template ">
43- < details class ="verticalSection " style ="border-radius: 8px; margin-bottom: 1em; box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.1), 0 2px 4px rgba(0, 0, 0, 0.5); transition: box-shadow 0.3s ease; ">
44- < summary style ="cursor: pointer; list-style: none; display: flex; align-items: center; padding: 0.75em 1em; ">
45- < i class ="material-icons arrow-closed " style ="display: inline-block; "> arrow_right</ i >
46- < i class ="material-icons arrow-open " style ="display: none; "> arrow_drop_down</ i >
47- < h3 class ="sectionTitle script-name-header " style ="margin: 0px 0px 0px 0.5em; "> </ h3 >
53+ < details class ="verticalSection "
54+ style ="background-color: rgba(255, 255, 255, 0.05); border-radius: 8px; margin-bottom: 1em; transition: box-shadow 0.3s ease; ">
55+ < summary
56+ style ="cursor: pointer; list-style: none; display: flex; align-items: center; padding: 0.75em 1em; ">
57+ < i class ="material-icons arrow-icon " style ="transition: transform 0.2s ease-in-out; "> arrow_right</ i >
58+ < h3 class ="sectionTitle script-name-header " style ="margin: 0 0 0 0.5em; "> </ h3 >
4859 </ summary >
49- < div class ="script-container " style ="padding: 0 1.5em 1.5em 1.5em ; ">
60+ < div class ="script-container " style ="padding: 1.5em; border-top: 1px solid rgba(255, 255, 255, 0.1) ; ">
5061 < div class ="inputContainer ">
5162 < input is ="emby-input " type ="text " class ="script-name-input " label ="Script Name: " />
5263 </ div >
5364 < div class ="inputContainer ">
54- < textarea is ="emby-textarea " class ="script-code-textarea " label ="JavaScript Code: " style ="height: 300px; width: 100%; " placeholder ="// Insert javascript code here "> </ textarea >
65+ < textarea class ="script-code-textarea emby-textarea emby-input "
66+ style ="height: 300px; width: 100%; "
67+ placeholder ="// Insert your custom JavaScript code here... "> </ textarea >
5568 </ div >
5669 < div style ="display: flex; align-items: center; gap: 2em; margin-top: 1em; ">
5770 < label class ="emby-checkbox-label ">
@@ -74,7 +87,7 @@ <h3 class="sectionTitle script-name-header" style="margin: 0px 0px 0px 0.5em;"><
7487 var JavaScriptInjectorConfig = {
7588 pluginId : 'f5a34f7b-2e8a-4e6a-a722-3a216a81b374' ,
7689
77- loadConfiguration : function ( ) {
90+ loadConfiguration : function ( ) {
7891 Dashboard . showLoadingMsg ( ) ;
7992 ApiClient . getPluginConfiguration ( JavaScriptInjectorConfig . pluginId ) . then ( function ( config ) {
8093 const scriptsContainer = document . querySelector ( '#scriptsContainer' ) ;
@@ -85,12 +98,12 @@ <h3 class="sectionTitle script-name-header" style="margin: 0px 0px 0px 0.5em;"><
8598 } ) ;
8699 }
87100 Dashboard . hideLoadingMsg ( ) ;
88- } ) . catch ( function ( ) {
101+ } ) . catch ( function ( ) {
89102 Dashboard . hideLoadingMsg ( ) ;
90103 } ) ;
91104 } ,
92105
93- createScriptEntry : function ( script ) {
106+ createScriptEntry : function ( script ) {
94107 const template = document . querySelector ( '#script-entry-template' ) ;
95108 const clone = template . content . cloneNode ( true ) ;
96109
@@ -101,8 +114,7 @@ <h3 class="sectionTitle script-name-header" style="margin: 0px 0px 0px 0.5em;"><
101114 const enabledCheckbox = clone . querySelector ( '.script-enabled-checkbox' ) ;
102115 const authCheckbox = clone . querySelector ( '.script-auth-checkbox' ) ;
103116 const removeBtn = clone . querySelector ( '.script-remove-btn' ) ;
104- const arrowOpen = clone . querySelector ( '.arrow-open' ) ;
105- const arrowClosed = clone . querySelector ( '.arrow-closed' ) ;
117+ const arrowIcon = clone . querySelector ( '.arrow-icon' ) ;
106118
107119 // Populate the cloned template with script data
108120 nameHeader . textContent = script . Name ;
@@ -120,32 +132,22 @@ <h3 class="sectionTitle script-name-header" style="margin: 0px 0px 0px 0.5em;"><
120132 detailsElement . remove ( ) ;
121133 } ) ;
122134
123- // Handle hover effect for box-shadow
124- const defaultShadow = 'inset 0 1px 1px rgba(255, 255, 255, 0.1), 0 2px 4px rgba(0, 0, 0, 0.5)' ;
125- const hoverShadow = 'inset 0 1px 1px rgba(255, 255, 255, 0.1), 0 4px 8px rgba(0, 0, 0, 0.6)' ;
126135 detailsElement . addEventListener ( 'mouseover' , ( ) => {
127- detailsElement . style . boxShadow = hoverShadow ;
136+ detailsElement . style . boxShadow = '0 4px 12px rgba(0, 0, 0, 0.4)' ;
128137 } ) ;
129138 detailsElement . addEventListener ( 'mouseout' , ( ) => {
130- detailsElement . style . boxShadow = defaultShadow ;
139+ detailsElement . style . boxShadow = 'none' ;
131140 } ) ;
132141
133142 // Handle arrow icon switching on toggle
134143 detailsElement . addEventListener ( 'toggle' , ( ) => {
135- if ( detailsElement . open ) {
136- arrowOpen . style . display = 'inline-block' ;
137- arrowClosed . style . display = 'none' ;
138- } else {
139- arrowOpen . style . display = 'none' ;
140- arrowClosed . style . display = 'inline-block' ;
141- }
144+ arrowIcon . style . transform = detailsElement . open ? 'rotate(90deg)' : 'rotate(0deg)' ;
142145 } ) ;
143146
144-
145147 return clone ;
146148 } ,
147149
148- saveConfiguration : function ( ) {
150+ saveConfiguration : function ( ) {
149151 Dashboard . showLoadingMsg ( ) ;
150152 const scripts = [ ] ;
151153 document . querySelectorAll ( '#scriptsContainer .script-container' ) . forEach ( container => {
@@ -164,27 +166,28 @@ <h3 class="sectionTitle script-name-header" style="margin: 0px 0px 0px 0.5em;"><
164166 } ) ;
165167 } ,
166168
167- registerEvents : function ( ) {
168- document . querySelector ( '#JavaScriptInjectorConfigForm' ) . addEventListener ( 'submit' , function ( e ) {
169+ registerEvents : function ( ) {
170+ document . querySelector ( '#JavaScriptInjectorConfigForm' ) . addEventListener ( 'submit' , function ( e ) {
169171 e . preventDefault ( ) ;
170172 JavaScriptInjectorConfig . saveConfiguration ( ) ;
171173 return false ;
172174 } ) ;
173175
174- document . querySelector ( '#addScriptBtn' ) . addEventListener ( 'click' , function ( ) {
176+ document . querySelector ( '#addScriptBtn' ) . addEventListener ( 'click' , function ( ) {
175177 const scriptsContainer = document . querySelector ( '#scriptsContainer' ) ;
176178 scriptsContainer . appendChild ( JavaScriptInjectorConfig . createScriptEntry ( { Name : 'New Script' , Script : '' , Enabled : true , RequiresAuthentication : false } ) ) ;
177179 } ) ;
178180 }
179181 } ;
180182
181- document . addEventListener ( 'pageshow' , function ( e ) {
183+ document . addEventListener ( 'pageshow' , function ( e ) {
182184 if ( e . target . id === 'JavaScriptInjectorConfigPage' ) {
183- JavaScriptInjectorConfig . loadConfiguration ( ) ;
184- JavaScriptInjectorConfig . registerEvents ( ) ;
185+ JavaScriptInjectorConfig . loadConfiguration ( ) ;
186+ JavaScriptInjectorConfig . registerEvents ( ) ;
185187 }
186188 } ) ;
187189 </ script >
188190 </ div >
189191</ body >
192+
190193</ html >
0 commit comments