1String.prototype.format = function (args) { 2 let formatted = this; 3 for (let i = 0; i < args.length; i++) { 4 let regexp = new RegExp("\\{" + i + "\\}", "gi"); 5 formatted = formatted.replace(regexp, t(args[i])); 6 } 7 return formatted; 8}; 9 10export function truncateString(str, num) { 11 if (str == null || str == undefined) return str; 12 // If the length of str is less than or equal to num 13 // just return str--don't truncate it. 14 if (str.length <= num) { 15 return str; 16 } 17 // Return str truncated with '...' concatenated to the end of str. 18 return str.slice(0, num) + "..."; 19} 20 21export function isPageNew() { 22 if (window.performance) { 23 var navEntries = window.performance.getEntriesByType("navigation"); 24 if (navEntries.length > 0 && navEntries[0].type === "back_forward") { 25 console.log( 26 "isPageNew: As per API lv2, this page is load from back/forward" 27 ); 28 return false; 29 } else if ( 30 window.performance.navigation && 31 window.performance.navigation.type == 32 window.performance.navigation.TYPE_BACK_FORWARD 33 ) { 34 console.log( 35 "isPageNew: As per API lv1, this page is load from back/forward" 36 ); 37 return false; 38 } else { 39 console.log("isPageNew: This is normal page load"); 40 return true; 41 } 42 } else { 43 console.log( 44 "isPageNew: Unfortunately, your browser doesn't support this API" 45 ); 46 return true; 47 } 48} 49 50export function toMomentObj(date_time) { 51 if (date_time == undefined || date_time == null) return moment(); 52 return moment(date_time); 53} 54 55export function toMoment(date_time) { 56 return moment(date_time).fromNow(); 57} 58 59export function t(str, replace = []) { 60 if (str == null || str == undefined) { 61 return str; 62 } 63 str = str.toString(); 64 if ( 65 frappe._messages[str.toLowerCase()] == undefined && 66 frappe._messages[str] == undefined 67 ) { 68 if (replace.length) return str.format(replace); 69 return str; 70 } 71 var translation_string = frappe._messages[str]; 72 if (translation_string == undefined) { 73 translation_string = frappe._messages[str.toLowerCase()]; 74 } 75 if (replace.length) return translation_string.format(replace); 76 return translation_string; 77} 78 79export function exceptionToMap(exceptionJSON) { 80 var exceptionMAP = JSON.parse(exceptionJSON); 81 for (var i = 0; i < exceptionMAP.length; i++) { 82 exceptionMAP[i] = JSON.parse(exceptionMAP[i]); 83 } 84 return exceptionMAP; 85} 86 87export function showException(e, callback = null) { 88 var exceptions = "" 89 if(typeof e === 'string' || e instanceof String){ 90 exceptions = [{"message":e}] 91 }else{ 92 exceptions = exceptionToMap(e.responseJSON._server_messages); 93 } 94 bootbox.alert({ 95 title: t("Error"), 96 message: 97 `<div class="alert alert-danger" role="alert"> 98 ` + 99 t(exceptions[0].message) + 100 ` 101 </div>`, 102 size: "large", 103 buttons: { 104 ok: { 105 label: t("Ok"), 106 className: "default-btn", 107 }, 108 }, 109 // callback: (results) => results?this.save_property():console.log("cancel"), 110 callback: callback, 111 }); 112 return exceptions; 113} 114 115export function toMomentStringTranslationFromNow(moment_string) { 116 var matches = moment_string.match(/(\d+)/); 117 if (matches) { 118 return t(moment_string.replace(/[0-9]+/g, "{0}"), [matches[0]]); 119 } 120 return t(moment_string); 121} 122 123export function toMomentString(date_time) { 124 return toMoment(date_time); 125} 126 127export function toMomentStringTranslation(date_time) { 128 moment_string = toMomentString(date_time); 129 var matches = moment_string.match(/(\d+)/); 130 if (matches) { 131 return t(moment_string.replace(/[0-9]+/g, "{0}"), [matches[0]]); 132 } 133 return t(moment_string); 134} 135 136export function showSuccess(message, callback = null) { 137 bootbox.alert({ 138 title: t("Success"), 139 message: 140 `<div class="alert alert-success" role="alert"> 141 ` + 142 t(message) + 143 ` 144 </div>`, 145 size: "large", 146 buttons: { 147 ok: { 148 label: t("Ok"), 149 className: "default-btn", 150 }, 151 }, 152 // callback: (results) => results?this.save_property():console.log("cancel"), 153 callback: callback, 154 }); 155} 156 157export function upload_file( 158 file, 159 i, 160 doctype, 161 docname, 162 fieldname = null, 163 method = null, 164 attach_doc_image = null 165) { 166 // var file = new File([filer], "test.jpg",{ type: "image/png" }); 167 return new Promise((resolve, reject) => { 168 let xhr = new XMLHttpRequest(); 169 xhr.upload.addEventListener("loadstart", (e) => { 170 file.uploading = true; 171 }); 172 xhr.upload.addEventListener("progress", (e) => { 173 if (e.lengthComputable) { 174 file.progress = e.loaded; 175 file.total = e.total; 176 } 177 }); 178 xhr.upload.addEventListener("load", (e) => { 179 file.uploading = false;
180 resolve(); 181 }); 182 xhr.addEventListener("error", (e) => { 183 file.failed = true; 184 reject(); 185 }); 186 xhr.onreadystatechange = () => { 187 if (xhr.readyState == XMLHttpRequest.DONE) { 188 if (xhr.status === 200) { 189 file.request_succeeded = true; 190 let r = null; 191 let file_doc = null; 192 try { 193 r = JSON.parse(xhr.responseText); 194 if (r.message.doctype === "File") { 195 file_doc = r.message; 196 } 197 } catch (e) { 198 r = xhr.responseText; 199 } 200 file.doc = file_doc; 201 // if (i == this.files.length - 1 && this.files.every(file => file.request_succeeded)) { 202 // this.close_dialog = true; 203 // } 204 } else if (xhr.status === 403) { 205 file.failed = true; 206 let response = JSON.parse(xhr.responseText); 207 file.error_message = `Not permitted. ${ 208 response._error_message || "" 209 }`; 210 } else if (xhr.status === 413) { 211 file.failed = true; 212 file.error_message = "Size exceeds the maximum allowed file size."; 213 } else { 214 file.failed = true; 215 file.error_message = 216 xhr.status === 0 217 ? "XMLHttpRequest Error" 218 : `${xhr.status} : ${xhr.statusText}`; 219 let error = null; 220 try { 221 error = JSON.parse(xhr.responseText); 222 } catch (e) { 223 // pass 224 } 225 frappe.request.cleanup({}, error); 226 } 227 } 228 }; 229 xhr.open("POST", "/api/method/upload_file", true); 230 xhr.setRequestHeader("Accept", "application/json"); 231 xhr.setRequestHeader("X-Frappe-CSRF-Token", frappe.csrf_token); 232 let form_data = new FormData(); 233 if (file.file_obj) { 234 form_data.append("file", file.file_obj, file.name); 235 } 236 form_data.append("is_private", +file.private); 237 form_data.append("folder", "Home"); 238 if (file.file_url) { 239 form_data.append("file_url", file.file_url); 240 } 241 file.file_name = file.name; 242 if (file.file_name) { 243 form_data.append("file_name", file.file_name); 244 } 245 form_data.append("doctype", doctype); 246 form_data.append("docname", docname); 247 if (fieldname) { 248 form_data.append("fieldname", fieldname); 249 } 250 if (method) { 251 form_data.append("method", method); 252 } 253 if (file.optimize) { 254 form_data.append("optimize", true); 255 } 256 if (attach_doc_image) { 257 form_data.append("max_width", 200); 258 form_data.append("max_height", 200); 259 } 260 xhr.send(form_data); 261 }); 262} 263 264export function nFormatter(num, digits = 1) { 265 num = parseFloat(num.toString()); 266 const lookup = [ 267 { 268 value: 1, 269 symbol: "", 270 }, 271 { 272 value: 1e3, 273 symbol: frappe.lang_dir == "ltr" ? "k" : "اÙÙ", 274 }, 275 { 276 value: 1e6, 277 symbol: frappe.lang_dir == "ltr" ? "M" : "Ù ÙÙÙÙ", 278 }, 279 { 280 value: 1e9, 281 symbol: frappe.lang_dir == "ltr" ? "B" : "بÙÙÙÙ", 282 }, 283 { 284 value: 1e12, 285 symbol: frappe.lang_dir == "ltr" ? "T" : "ترÙÙÙÙ", 286 }, 287 ]; 288 const rx = /\.0+$|(\.[0-9]*[1-9])0+$/; 289 var item = lookup 290 .slice() 291 .reverse() 292 .find(function (item) { 293 return num >= item.value; 294 }); 295 return item 296 ? (num / item.value).toFixed(digits).replace(rx, "$1") + " " + item.symbol 297 : "0"; 298} 299 300 301export function truncateSafeText(text, maxLength = 12) { 302 if (text.length <= maxLength) return text; 303 304 const words = text.split(' '); 305 let result = ''; 306 307 for (let word of words) { 308 if ((result + word).length > maxLength) break; 309 result += (result ? ' ' : '') + word; 310 } 311 312 return result.trim() + '...'; 313}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.