2626 .copy-btn {
2727 flex-shrink : 0 ;
2828 }
29+ .linker-options {
30+ margin-bottom : 1.25em ;
31+ }
32+ .linker-options-title-row {
33+ display : grid;
34+ grid-template-columns : max-content 1fr ;
35+ gap : 0.5em 1em ;
36+ align-items : center;
37+ margin-bottom : 0.5em ;
38+ }
39+ .linker-options-title-row label {
40+ white-space : nowrap;
41+ }
42+ .linker-options-two-col {
43+ display : flex;
44+ flex-wrap : nowrap;
45+ gap : 0.5em 0.8em ;
46+ }
47+ .linker-option {
48+ display : flex;
49+ align-items : center;
50+ gap : 0.5em ;
51+ white-space : nowrap;
52+ }
2953</ style >
3054
3155< div class ="inner-content " style ="margin: 0 10%; ">
@@ -46,12 +70,38 @@ <h1>NetLogo Web Model Link Creator</h1>
4670
4771 < h2 > Your Model URL</ h2 >
4872
49- < p > Paste your model's URL below and all links will update automatically.</ p >
73+ < p > Paste your model's URL below and all links will update automatically. You can also configure the extra options
74+ for your link.</ p >
5075
5176 < input type ="url " id ="model-url-input "
5277 placeholder ="https://example.com/my-model.nlogox "
5378 style ="width: 100%; box-sizing: border-box; padding: 6px 8px; font-size: 1em; margin-bottom: 1.25em; " />
5479
80+ < div class ="linker-options ">
81+ < div class ="linker-options-title-row ">
82+ < label for ="opt-title "> Model title</ label >
83+ < input type ="text " id ="opt-title " placeholder ="(defaults to model file name) " style ="padding: 4px 6px; " />
84+ </ div >
85+ < div class ="linker-options-two-col ">
86+ < div class ="linker-option ">
87+ < label for ="opt-tabs "> Commands and code position</ label >
88+ < select id ="opt-tabs " style ="padding: 4px 6px; ">
89+ < option value ="bottom "> Bottom (default)</ option >
90+ < option value ="right "> Right</ option >
91+ </ select >
92+ </ div >
93+ < div class ="linker-option ">
94+ < label for ="opt-speed "> Speed slider (-1 to 1)</ label >
95+ < input type ="number " id ="opt-speed " min ="-1 " max ="1 " step ="0.1 " placeholder ="0 (default) "
96+ style ="padding: 4px 6px; width: 8em; " />
97+ </ div >
98+ < div class ="linker-option ">
99+ < label for ="opt-analytics "> Disable analytics</ label >
100+ < input type ="checkbox " id ="opt-analytics " />
101+ </ div >
102+ </ div >
103+ </ div >
104+
55105 < h2 > Shareable Link</ h2 >
56106
57107 < p > Opens the full NetLogo Web interface. The simplest way to share your model with others by social media, email, or messaging software.</ p >
@@ -94,32 +144,75 @@ <h2>Embeddable Links</h2>
94144
95145< script >
96146 ( function ( ) {
97- const input = document . getElementById ( 'model-url-input' ) ;
98- const allLinks = document . querySelectorAll ( '[data-link-format]' ) ;
99- const origin = window . location . origin ;
147+ const input = document . getElementById ( 'model-url-input' ) ;
148+ const allLinks = document . querySelectorAll ( '[data-link-format]' ) ;
149+ const origin = window . location . origin ;
150+ const analyticsCheck = document . getElementById ( 'opt-analytics' ) ;
151+ const titleInput = document . getElementById ( 'opt-title' ) ;
152+ const tabsSelect = document . getElementById ( 'opt-tabs' ) ;
153+ const speedInput = document . getElementById ( 'opt-speed' ) ;
154+
155+ function getExtraParams ( ) {
156+ const parts = [ ] ;
157+
158+ if ( analyticsCheck . checked ) {
159+ parts . push ( 'disableAnalytics' ) ;
160+ }
161+
162+ const title = titleInput . value . trim ( ) ;
163+ if ( title !== '' ) {
164+ parts . push ( 'title=' + encodeURIComponent ( title ) ) ;
165+ }
166+
167+ if ( tabsSelect . value === 'right' ) {
168+ parts . push ( 'tabs=right' ) ;
169+ }
170+
171+ const rawSpeed = speedInput . value ;
172+ if ( rawSpeed !== '' ) {
173+ const speed = parseFloat ( rawSpeed ) ;
174+ if ( ! isNaN ( speed ) && speed >= - 1 && speed <= 1 && speed !== 0 ) {
175+ parts . push ( 'speed=' + speed ) ;
176+ }
177+ }
178+
179+ return parts ;
180+ }
100181
101182 function updateLinks ( ) {
102- const modelUrl = input . value . trim ( ) ;
183+ const modelUrl = input . value . trim ( ) ;
184+ const extraParts = getExtraParams ( ) ;
185+ const extraQuery = extraParts . join ( '&' ) ;
186+
103187 allLinks . forEach ( function ( link ) {
104188 const base = origin + link . dataset . path ;
105189 let href ;
190+
106191 if ( link . dataset . linkFormat === 'shareable' ) {
107- href = modelUrl ? base + '#' + modelUrl : base ;
108- } else if ( modelUrl ) {
109- let params = '?url=' + encodeURIComponent ( modelUrl ) ;
110- if ( link . dataset . version ) {
111- params += '&v=' + encodeURIComponent ( link . dataset . version ) ;
112- }
113- href = base + params ;
192+ const queryStr = extraQuery ? '?' + extraQuery : '' ;
193+ const hashStr = modelUrl ? '#' + modelUrl : '' ;
194+ href = base + queryStr + hashStr ;
195+
114196 } else {
115- href = base ;
197+ // embeddable
198+ const paramParts = [ ] ;
199+ if ( extraQuery ) { paramParts . push ( extraQuery ) ; }
200+ if ( modelUrl ) { paramParts . push ( 'url=' + encodeURIComponent ( modelUrl ) ) ; }
201+ if ( link . dataset . version ) { paramParts . push ( 'v=' + encodeURIComponent ( link . dataset . version ) ) ; }
202+ href = paramParts . length > 0 ? base + '?' + paramParts . join ( '&' ) : base ;
116203 }
117- link . href = href ;
204+
205+ link . href = href ;
118206 link . textContent = href ;
119207 } ) ;
120208 }
121209
122210 input . addEventListener ( 'input' , updateLinks ) ;
211+ analyticsCheck . addEventListener ( 'change' , updateLinks ) ;
212+ titleInput . addEventListener ( 'input' , updateLinks ) ;
213+ tabsSelect . addEventListener ( 'change' , updateLinks ) ;
214+ speedInput . addEventListener ( 'input' , updateLinks ) ;
215+
123216 updateLinks ( ) ;
124217
125218 document . querySelectorAll ( '.copy-btn' ) . forEach ( function ( btn ) {
0 commit comments