comparison src/admin.js @ 0:8f4df159f06b

start public repo
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 11 Jul 2025 20:57:49 -0600
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:8f4df159f06b
1 'use strict';
2
3 let currentPulldown = null;
4 let newPulldown = null;
5
6 function clickMenu(clicked,display) {
7 //console.log("clickMenu");
8 let pulldown = clicked.parentNode.querySelector('[pulldown_menu]');
9 if( pulldown !== currentPulldown ) {
10 pulldown.style.display = display || "block";
11 newPulldown = pulldown;
12 window.onclick = function() {
13 //console.log("window.onclick");
14 if( currentPulldown ) {
15 currentPulldown.style.display = "none";
16 if( !newPulldown )
17 window.onclick = null;
18 }
19 currentPulldown = newPulldown;
20 newPulldown = null;
21 };
22 pulldown.scrollIntoViewIfNeeded(false);
23 }
24 }
25
26 function stopPropagation(event) {
27 event.stopPropagation();
28 }
29
30 window.addEventListener( 'load', function() {
31 for( let pulldown of document.querySelectorAll('[pulldown_menu]') ) {
32 pulldown.onclick = stopPropagation;
33 }
34 } );
35
36 function copyLink() {
37 // avoid the paranoid security nonsense with navigator.clipboard
38 let input = document.querySelector('input[clipboard]');
39 input.select();
40 document.execCommand('copy');
41 input.blur();
42
43 let span = document.querySelector('[pulldown_menu] span[copy]');
44 span.textContent = 'Copied!';
45 span.setAttribute('copy','copied');
46 setTimeout(function(){
47 span.textContent = 'Copy';
48 span.setAttribute('copy','');
49 } ,1000);
50 }
51
52 function logout() {
53 document.cookie = 'user=; Max-Age=0; path=/;';
54 document.cookie = 'password=; Max-Age=0; path=/;';
55 location = '/';
56 }
57
58
59 function uploadcareUrl(uuid) {
60 return "https://ucarecdn.com/" + uuid + "/-/quality/smart/";
61 }
62
63 if( typeof(uploadcare) !== 'undefined' ) {
64 uploadcare.publicKey = window.uploadcarePubKey;
65 uploadcare.imagesOnly = true;
66 uploadcare.maxFileSize = 10000000;
67 uploadcare.onError = function(status,text) {
68 let err = 'upload failed: ' + status;
69 if( text ) {
70 err += '\n' + text;
71 }
72 console.log(err);
73 ajax( '/error_log.js', 'err='+encodeURIComponent(err) );
74 };
75 }
76
77
78 let dropSelector, iDragging;
79
80 function indexOf(a,el) {
81 for( let i=0; i<a.length; i++ ) {
82 if( a[i] === el )
83 return i;
84 }
85 return -1;
86 }
87
88 if( typeof(dad) !== 'undefined' ) {
89 dad.onStart = function(event) {
90 let dragging = event.original;
91 iDragging = indexOf(dragging.parentNode.querySelectorAll(dropSelector),dragging);
92 }
93
94 dad.onEnter = function(event) {
95 let dropzone = event.dropzone
96 let original = event.original
97 let items = document.querySelectorAll(dropSelector);
98 let iDropzone = indexOf(items,dropzone);
99 let iOriginal = indexOf(items,original);
100 let where = iDropzone < iOriginal ? 'beforebegin' : 'afterend';
101 dropzone.insertAdjacentElement(where,original);
102 };
103 }
104
105 function date(time) {
106 document.write(new Date(time).toLocaleDateString());
107 }
108
109 function ajaxForm(url,form) {
110 let post = '';
111 for( let i=0; i<form.length; i++ ) {
112 let input = form[i];
113 let name = input.name;
114 if( name === '' )
115 continue;
116 let type = input.type;
117 if( (type==='radio' || type==='checkbox') && !input.checked )
118 continue;
119 post += name + '=' + encodeURIComponent(input.value) + '&';
120 }
121 ajax(url,post,{form:form});
122 }
123
124 function clearErrors(form) {
125 let divs = form.querySelectorAll('div[error]');
126 for( let i=0; i<divs.length; i++ ) {
127 divs[i].textContent = '';
128 }
129 }
130
131 function showError(form,field,message) {
132 clearErrors(form);
133 let err = form.querySelector('[error="'+field+'"]');
134 err.textContent = message;
135 err.scrollIntoViewIfNeeded(false);
136 err.setAttribute('flash','');
137 setTimeout(function(){err.removeAttribute('flash')},2000);
138 }
139
140 function showPassword(div) {
141 div.querySelector('img[show]').style.display = 'none';
142 div.querySelector('img[hide]').style.display = 'block';
143 let input = div.querySelector('input');
144 input.type = 'text';
145 input.focus();
146 }
147 function hidePassword(div) {
148 div.querySelector('img[show]').style.display = 'block';
149 div.querySelector('img[hide]').style.display = 'none';
150 let input = div.querySelector('input');
151 input.type = 'password';
152 input.focus();
153 }
154
155
156 function isEmpty(obj) {
157 for( let _ in obj ) {
158 return false;
159 }
160 return true;
161 }
162
163 function barChartHeight(rows) {
164 return 200 + 20*rows;
165 }
166
167
168 // Mixpanel
169 if( window.UserEmail ) {
170 mixpanel.ours.identify(window.UserEmail);
171 mixpanel.ours.people.set({'$email':window.UserEmail,'$name':window.UserName});
172 }
173
174
175 // A/B tests
176
177 function setAbTest(name,values) {
178 let props = {};
179 props[name] = cookies[name];
180 for( let i=1; i<=4; i++ ) {
181 props[name+'-null-'+i] = values[ Math.floor( Math.random() * values.length ) ];
182 }
183 mixpanel.ours.identify();
184 mixpanel.ours.people.set(props);
185 }
186
187 function removeAbTest(name) {
188 let a = [];
189 a.push(name);
190 for( let i=1; i<=4; i++ ) {
191 a.push(name+'-null-'+i);
192 }
193 mixpanel.ours.people.unset(a);
194 }
195
196
197
198 if( !location.pathname.match(/^\/private\//) ) {
199 fbTrack( 'track', 'PageView' );
200 }