1 2/** 3 * Cloudinary's JavaScript library - Version 2.5.0 4 * Copyright Cloudinary 5 * see https://github.com/cloudinary/cloudinary_js 6 * 7 */ 8var slice = [].slice, 9 extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, 10 hasProp = {}.hasOwnProperty; 11 12(function(root, factory) { 13 var name, ref, results, value; 14 if ((typeof define === 'function') && define.amd) { 15 return define(['jquery'], factory); 16 } else if (typeof exports === 'object') { 17 return module.exports = factory(require('jquery')); 18 } else { 19 root.cloudinary || (root.cloudinary = {}); 20 ref = factory(jQuery); 21 results = []; 22 for (name in ref) { 23 value = ref[name]; 24 results.push(root.cloudinary[name] = value); 25 } 26 return results; 27 } 28})(this, function(jQuery) { 29 30 /* 31 * Includes common utility methods and shims 32 */ 33 34 /** 35 * Return true if all items in list are strings 36 * @function Util.allString 37 * @param {Array} list - an array of items 38 */ 39 var ArrayParam, BaseUtil, ClientHintsMetaTag, Cloudinary, CloudinaryJQuery, Condition, Configuration, Expression, ExpressionParam, FetchLayer, HtmlTag, ImageTag, Layer, LayerParam, Param, RangeParam, RawParam, SubtitlesLayer, TextLayer, Transformation, TransformationBase, TransformationParam, Util, VideoTag, addClass, allStrings, base64Encode, base64EncodeURL, camelCase, cloneDeep, cloudinary, compact, contains, convertKeys, crc32, defaults, difference, funcTag, functions, getAttribute, getData, hasClass, identity, isEmpty, isFunction, isNumberLike, isObject, isString, m, merge, objToString, objectProto, parameters, reWords, removeAttribute, setAttribute, setAttributes, setData, smartEscape, snakeCase, utf8_encode, webp, width, withCamelCaseKeys, withSnakeCaseKeys, without; 40 allStrings = function(list) { 41 var item, j, len; 42 for (j = 0, len = list.length; j < len; j++) { 43 item = list[j]; 44 if (!Util.isString(item)) { 45 return false; 46 } 47 } 48 return true; 49 }; 50 51 /** 52 * Creates a new array without the given item. 53 * @function Util.without 54 * @param {Array} array - original array 55 * @param {*} item - the item to exclude from the new array 56 * @return {Array} a new array made of the original array's items except for `item` 57 */ 58 without = function(array, item) { 59 var i, length, newArray; 60 newArray = []; 61 i = -1; 62 length = array.length; 63 while (++i < length) { 64 if (array[i] !== item) { 65 newArray.push(array[i]); 66 } 67 } 68 return newArray; 69 }; 70 71 /** 72 * Return true is value is a number or a string representation of a number. 73 * @function Util.isNumberLike 74 * @param {*} value 75 * @returns {boolean} true if value is a number 76 * @example 77 * Util.isNumber(0) // true 78 * Util.isNumber("1.3") // true 79 * Util.isNumber("") // false 80 * Util.isNumber(undefined) // false 81 */ 82 isNumberLike = function(value) { 83 return (value != null) && !isNaN(parseFloat(value)); 84 }; 85 86 /** 87 * Escape all characters matching unsafe in the given string 88 * @function Util.smartEscape 89 * @param {string} string - source string to escape 90 * @param {RegExp} unsafe - characters that must be escaped 91 * @return {string} escaped string 92 */ 93 smartEscape = function(string, unsafe) { 94 if (unsafe == null) { 95 unsafe = /([^a-zA-Z0-9_.\-\/:]+)/g; 96 } 97 return string.replace(unsafe, function(match) { 98 return match.split("").map(function(c) { 99 return "%" + c.charCodeAt(0).toString(16).toUpperCase(); 100 }).join(""); 101 }); 102 }; 103 104 /** 105 * Assign values from sources if they are not defined in the destination. 106 * Once a value is set it does not change 107 * @function Util.defaults 108 * @param {Object} destination - the object to assign defaults to 109 * @param {...Object} source - the source object(s) to assign defaults from 110 * @return {Object} destination after it was modified 111 */ 112 defaults = function() { 113 var destination, sources; 114 destination = arguments[0], sources = 2 <= arguments.length ? slice.call(arguments, 1) : []; 115 return sources.reduce(function(dest, source) { 116 var key, value; 117 for (key in source) { 118 value = source[key]; 119 if (dest[key] === void 0) { 120 dest[key] = value; 121 } 122 } 123 return dest; 124 }, destination); 125 }; 126 127 /*********** lodash functions */ 128 objectProto = Object.prototype; 129 130 /** 131 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) 132 * of values. 133 */ 134 objToString = objectProto.toString; 135 136 /** 137 * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. 138 * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) 139 * 140 * @param {*} value The value to check. 141 * @returns {boolean} Returns `true` if `value` is an object, else `false`. 142 * @example 143 * 144 #isObject({}); 145 * // => true 146 * 147 #isObject([1, 2, 3]); 148 * // => true 149 * 150 #isObject(1); 151 * // => false 152 */ 153 isObject = function(value) { 154 var type; 155 type = typeof value; 156 return !!value && (type === 'object' || type === 'function'); 157 }; 158 funcTag = '[object Function]'; 159 160 /** 161 * Checks if `value` is classified as a `Function` object. 162 * @function Util.isFunction 163 * @param {*} value The value to check. 164 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. 165 * @example 166 * 167 * function Foo(){}; 168 * isFunction(Foo); 169 * // => true 170 * 171 * isFunction(/abc/); 172 * // => false 173 */ 174 isFunction = function(value) { 175 return isObject(value) && objToString.call(value) === funcTag; 176 }; 177 178 /*********** lodash functions */ 179 180 /** Used to match words to create compound words. */ 181 reWords = (function() { 182 var lower, upper; 183 upper = '[A-Z]'; 184 lower = '[a-z]+'; 185 return RegExp(upper + '+(?=' + upper + lower + ')|' + upper + '?' + lower + '|' + upper + '+|[0-9]+', 'g'); 186 })();
187 188 /** 189 * Convert string to camelCase 190 * @function Util.camelCase 191 * @param {string} string - the string to convert 192 * @return {string} in camelCase format 193 */ 194 camelCase = function(source) { 195 var i, word, words; 196 words = source.match(reWords); 197 words = (function() { 198 var j, len, results; 199 results = []; 200 for (i = j = 0, len = words.length; j < len; i = ++j) { 201 word = words[i]; 202 word = word.toLocaleLowerCase(); 203 if (i) { 204 results.push(word.charAt(0).toLocaleUpperCase() + word.slice(1)); 205 } else { 206 results.push(word); 207 } 208 } 209 return results; 210 })(); 211 return words.join(''); 212 }; 213 214 /** 215 * Convert string to snake_case 216 * @function Util.snakeCase 217 * @param {string} string - the string to convert 218 * @return {string} in snake_case format 219 */ 220 snakeCase = function(source) { 221 var i, word, words; 222 words = source.match(reWords); 223 words = (function() { 224 var j, len, results; 225 results = []; 226 for (i = j = 0, len = words.length; j < len; i = ++j) { 227 word = words[i]; 228 results.push(word.toLocaleLowerCase()); 229 } 230 return results; 231 })(); 232 return words.join('_'); 233 }; 234 convertKeys = function(source, converter) { 235 var key, result, value; 236 if (converter == null) { 237 converter = Util.identity; 238 } 239 result = {}; 240 for (key in source) { 241 value = source[key]; 242 key = converter(key); 243 if (!Util.isEmpty(key)) { 244 result[key] = value; 245 } 246 } 247 return result; 248 }; 249 250 /** 251 * Create a copy of the source object with all keys in camelCase 252 * @function Util.withCamelCaseKeys 253 * @param {Object} value - the object to copy 254 * @return {Object} a new object 255 */ 256 withCamelCaseKeys = function(source) { 257 return convertKeys(source, Util.camelCase); 258 }; 259 260 /** 261 * Create a copy of the source object with all keys in snake_case 262 * @function Util.withSnakeCaseKeys 263 * @param {Object} value - the object to copy 264 * @return {Object} a new object 265 */ 266 withSnakeCaseKeys = function(source) { 267 return convertKeys(source, Util.snakeCase); 268 }; 269 base64Encode = typeof btoa !== 'undefined' && isFunction(btoa) ? btoa : typeof Buffer !== 'undefined' && isFunction(Buffer) ? function(input) { 270 if (!(input instanceof Buffer)) { 271 input = new Buffer.from(String(input), 'binary'); 272 } 273 return input.toString('base64'); 274 } : function(input) { 275 throw new Error("No base64 encoding function found"); 276 }; 277 278 /** 279 * Returns the Base64-decoded version of url.<br> 280 * This method delegates to `btoa` if present. Otherwise it tries `Buffer`. 281 * @function Util.base64EncodeURL 282 * @param {string} url - the url to encode. the value is URIdecoded and then re-encoded before converting to base64 representation 283 * @return {string} the base64 representation of the URL 284 */ 285 base64EncodeURL = function(input) { 286 var error1, ignore; 287 try { 288 input = decodeURI(input); 289 } catch (error1) { 290 ignore = error1; 291 } 292 input = encodeURI(input); 293 return base64Encode(input); 294 }; 295 BaseUtil = { 296 allStrings: allStrings, 297 camelCase: camelCase, 298 convertKeys: convertKeys, 299 defaults: defaults, 300 snakeCase: snakeCase, 301 without: without, 302 isFunction: isFunction, 303 isNumberLike: isNumberLike, 304 smartEscape: smartEscape, 305 withCamelCaseKeys: withCamelCaseKeys, 306 withSnakeCaseKeys: withSnakeCaseKeys, 307 base64EncodeURL: base64EncodeURL 308 }; 309 310 /** 311 * Includes utility methods and lodash / jQuery shims 312 */ 313 314 /** 315 * Get data from the DOM element. 316 * 317 * This method will use jQuery's `data()` method if it is available, otherwise it will get the `data-` attribute 318 * @param {Element} element - the element to get the data from 319 * @param {string} name - the name of the data item 320 * @returns the value associated with the `name` 321 * @function Util.getData 322 */ 323 getData = function(element, name) { 324 return jQuery(element).data(name); 325 }; 326 327 /** 328 * Set data in the DOM element. 329 * 330 * This method will use jQuery's `data()` method if it is available, otherwise it will set the `data-` attribute 331 * @function Util.setData 332 * @param {Element} element - the element to set the data in 333 * @param {string} name - the name of the data item 334 * @param {*} value - the value to be set 335 * 336 */ 337 setData = function(element, name, value) { 338 return jQuery(element).data(name, value); 339 }; 340 341 /** 342 * Get attribute from the DOM element. 343 * 344 * This method will use jQuery's `attr()` method if it is available, otherwise it will get the attribute directly 345 * @function Util.getAttribute 346 * @param {Element} element - the element to set the attribute for 347 * @param {string} name - the name of the attribute 348 * @returns {*} the value of the attribute 349 * 350 */ 351 getAttribute = function(element, name) { 352 return jQuery(element).attr(name); 353 }; 354 355 /** 356 * Set attribute in the DOM element. 357 * 358 * This method will use jQuery's `attr()` method if it is available, otherwise it will set the attribute directly 359 * @function Util.setAttribute 360 * @param {Element} element - the element to set the attribute for 361 * @param {string} name - the name of the attribute 362 * @param {*} value - the value to be set 363 */ 364 setAttribute = function(element, name, value) { 365 return jQuery(element).attr(name, value); 366 }; 367 368 /** 369 * Remove an attribute in the DOM element. 370 * 371 * @function Util.removeAttribute 372 * @param {Element} element - the element to set the attribute for 373 * @param {string} name - the name of the attribute 374 */ 375 removeAttribute = function(element, name) { 376 return jQuery(element).removeAttr(name); 377 }; 378 379 /** 380 * Set a group of attributes to the element 381 * @function Util.setAttributes 382 * @param {Element} element - the element to set the attributes for 383 * @param {Object} attributes - a hash of attribute names and values 384 */ 385 setAttributes = function(element, attributes) { 386 return jQuery(element).attr(attributes); 387 }; 388 389 /** 390 * Checks if element has a css class 391 * @function Util.hasClass 392 * @param {Element} element - the element to check 393 * @param {string} name - the class name 394 @returns {boolean} true if the element has the class 395 */ 396 hasClass = function(element, name) { 397 return jQuery(element).hasClass(name); 398 }; 399 400 /** 401 * Add class to the element 402 * @function Util.addClass 403 * @param {Element} element - the element 404 * @param {string} name - the class name to add 405 */ 406 addClass = function(element, name) { 407 return jQuery(element).addClass(name); 408 }; 409 width = function(element) { 410 return jQuery(element).width(); 411 }; 412 413 /** 414 * Returns true if item is empty: 415 * <ul> 416 * <li>item is null or undefined</li> 417 * <li>item is an array or string of length 0</li> 418 * <li>item is an object with no keys</li> 419 * </ul> 420 * @function Util.isEmpty 421 * @param item 422 * @returns {boolean} true if item is empty 423 */ 424 isEmpty = function(item) { 425 return (item == null) || (jQuery.isArray(item) || Util.isString(item)) && item.length === 0 || (jQuery.isPlainObject(item) && jQuery.isEmptyObject(item)); 426 }; 427 428 /** 429 * Returns true if item is a string 430 * @param item 431 * @returns {boolean} true if item is a string 432 */ 433 isString = function(item) { 434 return typeof item === 'string' || (item != null ? item.toString() : void 0) === '[object String]'; 435 }; 436 437 /**
438 * Recursively assign source properties to destination 439 * @function Util.merge 440 * @param {Object} destination - the object to assign to 441 * @param {...Object} [sources] The source objects. 442 */ 443 merge = function() { 444 var args, i; 445 args = (function() { 446 var j, len, results; 447 results = []; 448 for (j = 0, len = arguments.length; j < len; j++) { 449 i = arguments[j]; 450 results.push(i); 451 } 452 return results; 453 }).apply(this, arguments); 454 args.unshift(true); 455 return jQuery.extend.apply(this, args); 456 }; 457 458 /** 459 * Creates a new array from the parameter with "falsey" values removed 460 * @function Util.compact 461 * @param {Array} array - the array to remove values from 462 * @return {Array} a new array without falsey values 463 */ 464 compact = function(arr) { 465 var item, j, len, results; 466 results = []; 467 for (j = 0, len = arr.length; j < len; j++) { 468 item = arr[j]; 469 if (item) { 470 results.push(item); 471 } 472 } 473 return results; 474 }; 475 476 /** 477 * Create a new copy of the given object, including all internal objects. 478 * @function Util.cloneDeep 479 * @param {Object} value - the object to clone 480 * @return {Object} a new deep copy of the object 481 */ 482 cloneDeep = function() { 483 var args; 484 args = jQuery.makeArray(arguments); 485 args.unshift({}); 486 args.unshift(true); 487 return jQuery.extend.apply(this, args); 488 }; 489 490 /** 491 * Check if a given item is included in the given array 492 * @function Util.contains 493 * @param {Array} array - the array to search in 494 * @param {*} item - the item to search for 495 * @return {boolean} true if the item is included in the array 496 */ 497 contains = function(arr, item) { 498 var i, j, len; 499 for (j = 0, len = arr.length; j < len; j++) { 500 i = arr[j]; 501 if (i === item) { 502 return true; 503 } 504 } 505 return false; 506 }; 507 508 /** 509 * Returns values in the given array that are not included in the other array 510 * @function Util.difference 511 * @param {Array} arr - the array to select from 512 * @param {Array} values - values to filter from arr 513 * @return {Array} the filtered values 514 */ 515 difference = function(arr, values) { 516 var item, j, len, results; 517 results = []; 518 for (j = 0, len = arr.length; j < len; j++) { 519 item = arr[j]; 520 if (!contains(values, item)) { 521 results.push(item); 522 } 523 } 524 return results; 525 }; 526 527 /** 528 * Returns a list of all the function names in obj 529 * @function Util.functions 530 * @param {Object} object - the object to inspect 531 * @return {Array} a list of functions of object 532 */ 533 functions = function(object) { 534 var i, results; 535 results = []; 536 for (i in object) { 537 if (jQuery.isFunction(object[i])) { 538 results.push(i); 539 } 540 } 541 return results; 542 }; 543 544 /** 545 * Returns the provided value. This functions is used as a default predicate function. 546 * @function Util.identity 547 * @param {*} value 548 * @return {*} the provided value 549 */ 550 identity = function(value) { 551 return value; 552 }; 553 554 /** 555 * @class Util 556 */ 557 Util = jQuery.extend(BaseUtil, { 558 hasClass: hasClass, 559 addClass: addClass, 560 getAttribute: getAttribute, 561 setAttribute: setAttribute, 562 removeAttribute: removeAttribute, 563 setAttributes: setAttributes, 564 getData: getData, 565 setData: setData, 566 width: width, 567 isString: isString, 568 isArray: jQuery.isArray, 569 isEmpty: isEmpty, 570 571 /** 572 * Assign source properties to destination. 573 * If the property is an object it is assigned as a whole, overriding the destination object. 574 * @function Util.assign 575 * @param {Object} destination - the object to assign to 576 */ 577 assign: jQuery.extend, 578 merge: merge, 579 cloneDeep: cloneDeep, 580 compact: compact, 581 contains: contains, 582 difference: difference, 583 functions: functions, 584 identity: identity, 585 isPlainObject: jQuery.isPlainObject, 586 587 /**
588 * Remove leading or trailing spaces from text 589 * @function Util.trim 590 * @param {string} text 591 * @return {string} the `text` without leading or trailing spaces 592 */ 593 trim: jQuery.trim 594 }); 595 596 /** 597 * UTF8 encoder 598 * 599 */ 600 utf8_encode = function(argString) { 601 var c1, enc, end, n, start, string, stringl, utftext; 602 if (argString === null || typeof argString === 'undefined') { 603 return ''; 604 } 605 string = argString + ''; 606 utftext = ''; 607 start = void 0; 608 end = void 0; 609 stringl = 0; 610 start = end = 0; 611 stringl = string.length; 612 n = 0; 613 while (n < stringl) { 614 c1 = string.charCodeAt(n); 615 enc = null; 616 if (c1 < 128) { 617 end++; 618 } else if (c1 > 127 && c1 < 2048) { 619 enc = String.fromCharCode(c1 >> 6 | 192, c1 & 63 | 128); 620 } else { 621 enc = String.fromCharCode(c1 >> 12 | 224, c1 >> 6 & 63 | 128, c1 & 63 | 128); 622 } 623 if (enc !== null) { 624 if (end > start) { 625 utftext += string.slice(start, end); 626 } 627 utftext += enc; 628 start = end = n + 1; 629 } 630 n++; 631 } 632 if (end > start) { 633 utftext += string.slice(start, stringl); 634 } 635 return utftext; 636 }; 637 638 /** 639 * CRC32 calculator 640 * Depends on 'utf8_encode' 641 */ 642 crc32 = function(str) { 643 var crc, i, iTop, table, x, y; 644 str = utf8_encode(str); 645 table = '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F 63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC 51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E 7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D 806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA 11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F 30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D'; 646 crc = 0; 647 x = 0; 648 y = 0; 649 crc = crc ^ -1; 650 i = 0; 651 iTop = str.length; 652 while (i < iTop) { 653 y = (crc ^ str.charCodeAt(i)) & 0xFF; 654 x = '0x' + table.substr(y * 9, 8); 655 crc = crc >>> 8 ^ x; 656 i++; 657 } 658 crc = crc ^ -1; 659 if (crc < 0) { 660 crc += 4294967296; 661 } 662 return crc; 663 }; 664 Layer = (function() { 665 666 /** 667 * Layer 668 * @constructor Layer 669 * @param {Object} options - layer parameters 670 */ 671 function Layer(options) { 672 this.options = {}; 673 if (options != null) { 674 ["resourceType", "type", "publicId", "format"].forEach((function(_this) { 675 return function(key) { 676 var ref; 677 return _this.options[key] = (ref = options[key]) != null ? ref : options[Util.snakeCase(key)]; 678 }; 679 })(this)); 680 } 681 } 682 683 Layer.prototype.resourceType = function(value) { 684 this.options.resourceType = value; 685 return this; 686 }; 687 688 Layer.prototype.type = function(value) { 689 this.options.type = value; 690 return this; 691 }; 692 693 Layer.prototype.publicId = function(value) { 694 this.options.publicId = value; 695 return this; 696 }; 697 698 699 /** 700 * Get the public ID, formatted for layer parameter 701 * @function Layer#getPublicId 702 * @return {String} public ID 703 */ 704 705 Layer.prototype.getPublicId = function() { 706 var ref; 707 return (ref = this.options.publicId) != null ? ref.replace(/\//g, ":") : void 0; 708 }; 709 710 711 /** 712 * Get the public ID, with format if present 713 * @function Layer#getFullPublicId 714 * @return {String} public ID 715 */ 716 717 Layer.prototype.getFullPublicId = function() { 718 if (this.options.format != null) { 719 return this.getPublicId() + "." + this.options.format; 720 } else { 721 return this.getPublicId(); 722 } 723 }; 724 725 Layer.prototype.format = function(value) { 726 this.options.format = value; 727 return this; 728 }; 729 730 731 /** 732 * generate the string representation of the layer 733 * @function Layer#toString 734 */ 735 736 Layer.prototype.toString = function() { 737 var components; 738 components = []; 739 if (this.options.publicId == null) { 740 throw "Must supply publicId"; 741 } 742 if (!(this.options.resourceType === "image")) { 743 components.push(this.options.resourceType); 744 } 745 if (!(this.options.type === "upload")) { 746 components.push(this.options.type); 747 } 748 components.push(this.getFullPublicId()); 749 return Util.compact(components).join(":"); 750 }; 751 752 return Layer; 753 754 })();
755 FetchLayer = (function(superClass) { 756 extend(FetchLayer, superClass); 757 758 759 /** 760 * @constructor FetchLayer 761 * @param {Object|string} options - layer parameters or a url 762 * @param {string} options.url the url of the image to fetch 763 */ 764 765 function FetchLayer(options) { 766 FetchLayer.__super__.constructor.call(this, options); 767 if (Util.isString(options)) { 768 this.options.url = options; 769 } else if (options != null ? options.url : void 0) { 770 this.options.url = options.url; 771 } 772 } 773 774 FetchLayer.prototype.url = function(url) { 775 this.options.url = url; 776 return this; 777 }; 778 779 780 /** 781 * generate the string representation of the layer 782 * @function FetchLayer#toString 783 * @return {String} 784 */ 785 786 FetchLayer.prototype.toString = function() { 787 return "fetch:" + (cloudinary.Util.base64EncodeURL(this.options.url)); 788 }; 789 790 return FetchLayer; 791 792 })(Layer); 793 TextLayer = (function(superClass) { 794 extend(TextLayer, superClass); 795 796 797 /** 798 * @constructor TextLayer 799 * @param {Object} options - layer parameters 800 */ 801 802 function TextLayer(options) { 803 var keys; 804 TextLayer.__super__.constructor.call(this, options); 805 keys = ["resourceType", "resourceType", "fontFamily", "fontSize", "fontWeight", "fontStyle", "textDecoration", "textAlign", "stroke", "letterSpacing", "lineSpacing", "text"]; 806 if (options != null) { 807 keys.forEach((function(_this) { 808 return function(key) { 809 var ref; 810 return _this.options[key] = (ref = options[key]) != null ? ref : options[Util.snakeCase(key)]; 811 }; 812 })(this)); 813 } 814 this.options.resourceType = "text"; 815 } 816 817 TextLayer.prototype.resourceType = function(resourceType) { 818 throw "Cannot modify resourceType for text layers"; 819 }; 820 821 TextLayer.prototype.type = function(type) { 822 throw "Cannot modify type for text layers"; 823 }; 824 825 TextLayer.prototype.format = function(format) { 826 throw "Cannot modify format for text layers"; 827 }; 828 829 TextLayer.prototype.fontFamily = function(fontFamily) { 830 this.options.fontFamily = fontFamily; 831 return this; 832 }; 833 834 TextLayer.prototype.fontSize = function(fontSize) { 835 this.options.fontSize = fontSize; 836 return this; 837 }; 838 839 TextLayer.prototype.fontWeight = function(fontWeight) { 840 this.options.fontWeight = fontWeight; 841 return this; 842 }; 843 844 TextLayer.prototype.fontStyle = function(fontStyle) { 845 this.options.fontStyle = fontStyle; 846 return this; 847 }; 848 849 TextLayer.prototype.textDecoration = function(textDecoration) { 850 this.options.textDecoration = textDecoration; 851 return this; 852 }; 853 854 TextLayer.prototype.textAlign = function(textAlign) { 855 this.options.textAlign = textAlign; 856 return this; 857 }; 858 859 TextLayer.prototype.stroke = function(stroke) { 860 this.options.stroke = stroke; 861 return this; 862 }; 863 864 TextLayer.prototype.letterSpacing = function(letterSpacing) { 865 this.options.letterSpacing = letterSpacing; 866 return this; 867 }; 868 869 TextLayer.prototype.lineSpacing = function(lineSpacing) { 870 this.options.lineSpacing = lineSpacing; 871 return this; 872 }; 873 874 TextLayer.prototype.text = function(text) { 875 this.options.text = text; 876 return this; 877 }; 878 879 880 /** 881 * generate the string representation of the layer 882 * @function TextLayer#toString 883 * @return {String} 884 */ 885 886 TextLayer.prototype.toString = function() { 887 var components, hasPublicId, hasStyle, publicId, re, res, start, style, text, textSource; 888 style = this.textStyleIdentifier(); 889 if (this.options.publicId != null) { 890 publicId = this.getFullPublicId(); 891 } 892 if (this.options.text != null) { 893 hasPublicId = !Util.isEmpty(publicId); 894 hasStyle = !Util.isEmpty(style); 895 if (hasPublicId && hasStyle || !hasPublicId && !hasStyle) { 896 throw "Must supply either style parameters or a public_id when providing text parameter in a text overlay/underlay, but not both!"; 897 } 898 re = /\$\([a-zA-Z]\w*\)/g; 899 start = 0; 900 textSource = Util.smartEscape(this.options.text, /[,\/]/g); 901 text = ""; 902 while (res = re.exec(textSource)) { 903 text += Util.smartEscape(textSource.slice(start, res.index)); 904 text += res[0]; 905 start = res.index + res[0].length; 906 } 907 text += Util.smartEscape(textSource.slice(start)); 908 } 909 components = [this.options.resourceType, style, publicId, text]; 910 return Util.compact(components).join(":"); 911 }; 912 913 TextLayer.prototype.textStyleIdentifier = function() { 914 var components; 915 components = [];
916 if (this.options.fontWeight !== "normal") { 917 components.push(this.options.fontWeight); 918 } 919 if (this.options.fontStyle !== "normal") { 920 components.push(this.options.fontStyle); 921 } 922 if (this.options.textDecoration !== "none") { 923 components.push(this.options.textDecoration); 924 } 925 components.push(this.options.textAlign); 926 if (this.options.stroke !== "none") { 927 components.push(this.options.stroke); 928 } 929 if (!(Util.isEmpty(this.options.letterSpacing) && !Util.isNumberLike(this.options.letterSpacing))) { 930 components.push("letter_spacing_" + this.options.letterSpacing); 931 } 932 if (!(Util.isEmpty(this.options.lineSpacing) && !Util.isNumberLike(this.options.lineSpacing))) { 933 components.push("line_spacing_" + this.options.lineSpacing); 934 } 935 if (!Util.isEmpty(Util.compact(components))) { 936 if (Util.isEmpty(this.options.fontFamily)) { 937 throw "Must supply fontFamily. " + components; 938 } 939 if (Util.isEmpty(this.options.fontSize) && !Util.isNumberLike(this.options.fontSize)) { 940 throw "Must supply fontSize."; 941 } 942 } 943 components.unshift(this.options.fontFamily, this.options.fontSize); 944 components = Util.compact(components).join("_"); 945 return components; 946 }; 947 948 return TextLayer; 949 950 })(Layer); 951 SubtitlesLayer = (function(superClass) { 952 extend(SubtitlesLayer, superClass); 953 954 955 /** 956 * Represent a subtitles layer 957 * @constructor SubtitlesLayer 958 * @param {Object} options - layer parameters 959 */ 960 961 function SubtitlesLayer(options) { 962 SubtitlesLayer.__super__.constructor.call(this, options); 963 this.options.resourceType = "subtitles"; 964 } 965 966 return SubtitlesLayer; 967 968 })(TextLayer); 969 970 /** 971 * Transformation parameters 972 * Depends on 'util', 'transformation' 973 */ 974 Param = (function() { 975 976 /** 977 * Represents a single parameter 978 * @class Param 979 * @param {string} name - The name of the parameter in snake_case 980 * @param {string} shortName - The name of the serialized form of the parameter. 981 * If a value is not provided, the parameter will not be serialized. 982 * @param {function} [process=cloudinary.Util.identity ] - Manipulate origValue when value is called 983 * @ignore 984 */ 985 function Param(name, shortName, process) { 986 if (process == null) { 987 process = cloudinary.Util.identity; 988 } 989 990 /** 991 * The name of the parameter in snake_case 992 * @member {string} Param#name 993 */ 994 this.name = name; 995 996 /** 997 * The name of the serialized form of the parameter 998 * @member {string} Param#shortName 999 */ 1000 this.shortName = shortName; 1001 1002 /** 1003 * Manipulate origValue when value is called 1004 * @member {function} Param#process 1005 */ 1006 this.process = process; 1007 } 1008 1009 1010 /** 1011 * Set a (unprocessed) value for this parameter 1012 * @function Param#set 1013 * @param {*} origValue - the value of the parameter 1014 * @return {Param} self for chaining 1015 */ 1016 1017 Param.prototype.set = function(origValue) { 1018 this.origValue = origValue; 1019 return this; 1020 }; 1021 1022 1023 /** 1024 * Generate the serialized form of the parameter 1025 * @function Param#serialize 1026 * @return {string} the serialized form of the parameter 1027 */ 1028 1029 Param.prototype.serialize = function() { 1030 var val, valid; 1031 val = this.value(); 1032 valid = cloudinary.Util.isArray(val) || cloudinary.Util.isPlainObject(val) || cloudinary.Util.isString(val) ? !cloudinary.Util.isEmpty(val) : val != null; 1033 if ((this.shortName != null) && valid) { 1034 return this.shortName + "_" + val; 1035 } else { 1036 return ''; 1037 } 1038 }; 1039 1040 1041 /** 1042 * Return the processed value of the parameter 1043 * @function Param#value 1044 */ 1045 1046 Param.prototype.value = function() { 1047 return this.process(this.origValue); 1048 }; 1049 1050 Param.norm_color = function(value) { 1051 return value != null ? value.replace(/^#/, 'rgb:') : void 0; 1052 }; 1053 1054 Param.prototype.build_array = function(arg) { 1055 if (arg == null) { 1056 arg = []; 1057 } 1058 if (cloudinary.Util.isArray(arg)) { 1059 return arg; 1060 } else { 1061 return [arg]; 1062 } 1063 }; 1064 1065 1066 /** 1067 * Covert value to video codec string. 1068 * 1069 * If the parameter is an object, 1070 * @param {(string|Object)} param - the video codec as either a String or a Hash 1071 * @return {string} the video codec string in the format codec:profile:level 1072 * @example 1073 * vc_[ :profile : [level]] 1074 * or 1075 { codec: 'h264', profile: 'basic', level: '3.1' } 1076 * @ignore 1077 */ 1078 1079 Param.process_video_params = function(param) { 1080 var video; 1081 switch (param.constructor) { 1082 case Object: 1083 video = "";
1084 if ('codec' in param) { 1085 video = param['codec']; 1086 if ('profile' in param) { 1087 video += ":" + param['profile']; 1088 if ('level' in param) { 1089 video += ":" + param['level']; 1090 } 1091 } 1092 } 1093 return video; 1094 case String: 1095 return param; 1096 default: 1097 return null; 1098 } 1099 }; 1100 1101 return Param; 1102 1103 })(); 1104 ArrayParam = (function(superClass) { 1105 extend(ArrayParam, superClass); 1106 1107 1108 /** 1109 * A parameter that represents an array 1110 * @param {string} name - The name of the parameter in snake_case 1111 * @param {string} shortName - The name of the serialized form of the parameter 1112 * If a value is not provided, the parameter will not be serialized. 1113 * @param {string} [sep='.'] - The separator to use when joining the array elements together 1114 * @param {function} [process=cloudinary.Util.identity ] - Manipulate origValue when value is called 1115 * @class ArrayParam 1116 * @extends Param 1117 * @ignore 1118 */ 1119 1120 function ArrayParam(name, shortName, sep, process) { 1121 if (sep == null) { 1122 sep = '.'; 1123 } 1124 this.sep = sep; 1125 ArrayParam.__super__.constructor.call(this, name, shortName, process); 1126 } 1127 1128 ArrayParam.prototype.serialize = function() { 1129 var arrayValue, flat, t; 1130 if (this.shortName != null) { 1131 arrayValue = this.value(); 1132 if (cloudinary.Util.isEmpty(arrayValue)) { 1133 return ''; 1134 } else if (cloudinary.Util.isString(arrayValue)) { 1135 return this.shortName + "_" + arrayValue; 1136 } else { 1137 flat = (function() { 1138 var j, len, results; 1139 results = []; 1140 for (j = 0, len = arrayValue.length; j < len; j++) { 1141 t = arrayValue[j]; 1142 if (cloudinary.Util.isFunction(t.serialize)) { 1143 results.push(t.serialize()); 1144 } else { 1145 results.push(t); 1146 } 1147 } 1148 return results; 1149 })(); 1150 return this.shortName + "_" + (flat.join(this.sep)); 1151 } 1152 } else { 1153 return ''; 1154 } 1155 }; 1156 1157 ArrayParam.prototype.value = function() { 1158 var j, len, ref, results, v; 1159 if (cloudinary.Util.isArray(this.origValue)) { 1160 ref = this.origValue; 1161 results = []; 1162 for (j = 0, len = ref.length; j < len; j++) { 1163 v = ref[j]; 1164 results.push(this.process(v)); 1165 } 1166 return results; 1167 } else { 1168 return this.process(this.origValue); 1169 } 1170 }; 1171 1172 ArrayParam.prototype.set = function(origValue) { 1173 if ((origValue == null) || cloudinary.Util.isArray(origValue)) { 1174 return ArrayParam.__super__.set.call(this, origValue); 1175 } else { 1176 return ArrayParam.__super__.set.call(this, [origValue]); 1177 } 1178 }; 1179 1180 return ArrayParam; 1181 1182 })(Param); 1183 TransformationParam = (function(superClass) { 1184 extend(TransformationParam, superClass); 1185 1186 1187 /** 1188 * A parameter that represents a transformation 1189 * @param {string} name - The name of the parameter in snake_case 1190 * @param {string} [shortName='t'] - The name of the serialized form of the parameter 1191 * @param {string} [sep='.'] - The separator to use when joining the array elements together 1192 * @param {function} [process=cloudinary.Util.identity ] - Manipulate origValue when value is called 1193 * @class TransformationParam 1194 * @extends Param 1195 * @ignore 1196 */ 1197 1198 function TransformationParam(name, shortName, sep, process) { 1199 if (shortName == null) { 1200 shortName = "t"; 1201 } 1202 if (sep == null) { 1203 sep = '.'; 1204 } 1205 this.sep = sep; 1206 TransformationParam.__super__.constructor.call(this, name, shortName, process); 1207 } 1208 1209 TransformationParam.prototype.serialize = function() { 1210 var joined, result, t; 1211 if (cloudinary.Util.isEmpty(this.value())) { 1212 return ''; 1213 } else if (cloudinary.Util.allStrings(this.value())) { 1214 joined = this.value().join(this.sep); 1215 if (!cloudinary.Util.isEmpty(joined)) { 1216 return this.shortName + "_" + joined; 1217 } else { 1218 return ''; 1219 } 1220 } else { 1221 result = (function() { 1222 var j, len, ref, results; 1223 ref = this.value(); 1224 results = []; 1225 for (j = 0, len = ref.length; j < len; j++) { 1226 t = ref[j]; 1227 if (t != null) { 1228 if (cloudinary.Util.isString(t) && !cloudinary.Util.isEmpty(t)) { 1229 results.push(this.shortName + "_" + t); 1230 } else if (cloudinary.Util.isFunction(t.serialize)) { 1231 results.push(t.serialize()); 1232 } else if (cloudinary.Util.isPlainObject(t) && !cloudinary.Util.isEmpty(t)) { 1233 results.push(new Transformation(t).serialize()); 1234 } else { 1235 results.push(void 0); 1236 } 1237 } 1238 } 1239 return results; 1240 }).call(this); 1241 return cloudinary.Util.compact(result); 1242 } 1243 }; 1244 1245 TransformationParam.prototype.set = function(origValue1) { 1246 this.origValue = origValue1; 1247 if (cloudinary.Util.isArray(this.origValue)) { 1248 return TransformationParam.__super__.set.call(this, this.origValue); 1249 } else { 1250 return TransformationParam.__super__.set.call(this, [this.origValue]); 1251 } 1252 }; 1253 1254 return TransformationParam; 1255 1256 })(Param); 1257 RangeParam = (function(superClass) { 1258 extend(RangeParam, superClass); 1259 1260 1261 /** 1262 * A parameter that represents a range 1263 * @param {string} name - The name of the parameter in snake_case 1264 * @param {string} shortName - The name of the serialized form of the parameter 1265 * If a value is not provided, the parameter will not be serialized. 1266 * @param {function} [process=norm_range_value ] - Manipulate origValue when value is called 1267 * @class RangeParam 1268 * @extends Param 1269 * @ignore 1270 */ 1271
1272 function RangeParam(name, shortName, process) { 1273 if (process == null) { 1274 process = this.norm_range_value; 1275 } 1276 RangeParam.__super__.constructor.call(this, name, shortName, process); 1277 } 1278 1279 RangeParam.norm_range_value = function(value) { 1280 var modifier, offset; 1281 offset = String(value).match(new RegExp('^' + offset_any_pattern + '$')); 1282 if (offset) { 1283 modifier = offset[5] != null ? 'p' : ''; 1284 value = (offset[1] || offset[4]) + modifier; 1285 } 1286 return value; 1287 }; 1288 1289 return RangeParam; 1290 1291 })(Param); 1292 RawParam = (function(superClass) { 1293 extend(RawParam, superClass); 1294 1295 function RawParam(name, shortName, process) { 1296 if (process == null) { 1297 process = cloudinary.Util.identity; 1298 } 1299 RawParam.__super__.constructor.call(this, name, shortName, process); 1300 } 1301 1302 RawParam.prototype.serialize = function() { 1303 return this.value(); 1304 }; 1305 1306 return RawParam; 1307 1308 })(Param); 1309 LayerParam = (function(superClass) { 1310 var LAYER_KEYWORD_PARAMS; 1311 1312 extend(LayerParam, superClass); 1313 1314 function LayerParam() { 1315 return LayerParam.__super__.constructor.apply(this, arguments); 1316 } 1317 1318 LayerParam.prototype.value = function() { 1319 var layerOptions, result; 1320 layerOptions = this.origValue; 1321 if (cloudinary.Util.isPlainObject(layerOptions)) { 1322 layerOptions = Util.withCamelCaseKeys(layerOptions); 1323 if (layerOptions.resourceType === "text" || (layerOptions.text != null)) { 1324 result = new cloudinary.TextLayer(layerOptions).toString(); 1325 } else if (layerOptions.resourceType === "subtitles") { 1326 result = new cloudinary.SubtitlesLayer(layerOptions).toString(); 1327 } else if (layerOptions.resourceType === "fetch" || (layerOptions.url != null)) { 1328 result = new cloudinary.FetchLayer(layerOptions).toString(); 1329 } else { 1330 result = new cloudinary.Layer(layerOptions).toString(); 1331 } 1332 } else if (/^fetch:.+/.test(layerOptions)) { 1333 result = new FetchLayer(layerOptions.substr(6)).toString(); 1334 } else { 1335 result = layerOptions; 1336 } 1337 return result; 1338 }; 1339 1340 LAYER_KEYWORD_PARAMS = [["font_weight", "normal"], ["font_style", "normal"], ["text_decoration", "none"], ["text_align", null], ["stroke", "none"], ["letter_spacing", null], ["line_spacing", null]]; 1341 1342 LayerParam.prototype.textStyle = function(layer) { 1343 return (new cloudinary.TextLayer(layer)).textStyleIdentifier(); 1344 }; 1345 1346 return LayerParam; 1347 1348 })(Param); 1349 ExpressionParam = (function(superClass) { 1350 extend(ExpressionParam, superClass); 1351 1352 function ExpressionParam() { 1353 return ExpressionParam.__super__.constructor.apply(this, arguments); 1354 } 1355 1356 ExpressionParam.prototype.serialize = function() { 1357 return Expression.normalize(ExpressionParam.__super__.serialize.call(this)); 1358 }; 1359 1360 return ExpressionParam; 1361 1362 })(Param); 1363 parameters = {}; 1364 parameters.Param = Param; 1365 parameters.ArrayParam = ArrayParam; 1366 parameters.RangeParam = RangeParam; 1367 parameters.RawParam = RawParam; 1368 parameters.TransformationParam = TransformationParam; 1369 parameters.LayerParam = LayerParam; 1370 parameters.ExpressionParam = ExpressionParam; 1371 Expression = (function() { 1372 1373 /** 1374 * @internal 1375 */ 1376 var faceCount; 1377 1378 Expression.OPERATORS = { 1379 "=": 'eq', 1380 "!=": 'ne', 1381 "<": 'lt', 1382 ">": 'gt', 1383 "<=": 'lte', 1384 ">=": 'gte', 1385 "&&": 'and', 1386 "||": 'or', 1387 "*": "mul", 1388 "/": "div", 1389 "+": "add", 1390 "-": "sub" 1391 }; 1392 1393 1394 /** 1395 * @internal 1396 */ 1397 1398 Expression.PREDEFINED_VARS = { 1399 "aspect_ratio": "ar", 1400 "aspectRatio": "ar", 1401 "current_page": "cp", 1402 "currentPage": "cp", 1403 "face_count": "fc", 1404 "faceCount": "fc", 1405 "height": "h", 1406 "initial_aspect_ratio": "iar", 1407 "initial_height": "ih", 1408 "initial_width": "iw", 1409 "initialAspectRatio": "iar", 1410 "initialHeight": "ih", 1411 "initialWidth": "iw", 1412 "page_count": "pc", 1413 "page_x": "px", 1414 "page_y": "py", 1415 "pageCount": "pc", 1416 "pageX": "px", 1417 "pageY": "py", 1418 "tags": "tags", 1419 "width": "w" 1420 }; 1421 1422 1423 /** 1424 * @internal 1425 */ 1426 1427 Expression.BOUNDRY = "[ _]+"; 1428 1429 1430 /** 1431 * Represents a transformation expression 1432 * @param {string} expressionStr - a expression in string format 1433 * @class Expression 1434 * 1435 */ 1436 1437 function Expression(expressionStr) { 1438 1439 /** 1440 * @protected 1441 * @inner Expression-expressions 1442 */ 1443 this.expressions = []; 1444 if (expressionStr != null) { 1445 this.expressions.push(Expression.normalize(expressionStr)); 1446 } 1447 } 1448 1449 1450 /** 1451 * Convenience constructor method 1452 * @function Expression.new 1453 */ 1454 1455 Expression["new"] = function(expressionStr) { 1456 return new this(expressionStr); 1457 }; 1458 1459 1460 /** 1461 * Normalize a string expression 1462 * @function Cloudinary#normalize 1463 * @param {string} expression a expression, e.g. "w gt 100", "width_gt_100", "width > 100" 1464 * @return {string} the normalized form of the value expression, e.g. "w_gt_100" 1465 */ 1466 1467 Expression.normalize = function(expression) { 1468 var operators, pattern, replaceRE; 1469 if (expression == null) { 1470 return expression; 1471 } 1472 expression = String(expression); 1473 operators = "\\|\\||>=|<=|&&|!=|>|=|<|/|-|\\+|\\*"; 1474 pattern = "((" + operators + ")(?=[ _])|" + Object.keys(Expression.PREDEFINED_VARS).join("|") + ")"; 1475 replaceRE = new RegExp(pattern, "g"); 1476 expression = expression.replace(replaceRE, function(match) { 1477 return Expression.OPERATORS[match] || Expression.PREDEFINED_VARS[match]; 1478 }); 1479 return expression.replace(/[ _]+/g, '_'); 1480 }; 1481 1482 1483 /** 1484 * Serialize the expression 1485 * @return {string} the expression as a string 1486 */ 1487 1488 Expression.prototype.serialize = function() { 1489 return Expression.normalize(this.expressions.join("_")); 1490 }; 1491 1492 Expression.prototype.toString = function() { 1493 return this.serialize(); 1494 }; 1495 1496 1497 /** 1498 * Get the parent transformation of this expression 1499 * @return Transformation 1500 */ 1501 1502 Expression.prototype.getParent = function() { 1503 return this.parent; 1504 }; 1505 1506 1507 /** 1508 * Set the parent transformation of this expression 1509 * @param {Transformation} the parent transformation 1510 * @return {Expression} this expression 1511 */ 1512 1513 Expression.prototype.setParent = function(parent) { 1514 this.parent = parent; 1515 return this; 1516 }; 1517 1518 1519 /** 1520 * Add a expression 1521 * @function Expression#predicate 1522 * @internal 1523 */ 1524 1525 Expression.prototype.predicate = function(name, operator, value) { 1526 if (Expression.OPERATORS[operator] != null) { 1527 operator = Expression.OPERATORS[operator]; 1528 } 1529 this.expressions.push(name + "_" + operator + "_" + value); 1530 return this; 1531 }; 1532 1533 1534 /** 1535 * @function Expression#and 1536 */ 1537 1538 Expression.prototype.and = function() { 1539 this.expressions.push("and"); 1540 return this; 1541 }; 1542 1543 1544 /** 1545 * @function Expression#or 1546 */ 1547 1548 Expression.prototype.or = function() { 1549 this.expressions.push("or"); 1550 return this; 1551 }; 1552 1553 1554 /** 1555 * Conclude expression 1556 * @function Expression#then 1557 * @return {Transformation} the transformation this expression is defined for 1558 */ 1559 1560 Expression.prototype.then = function() { 1561 return this.getParent()["if"](this.toString()); 1562 }; 1563 1564 1565 /** 1566 * @function Expression#height 1567 * @param {string} operator the comparison operator (e.g. "<", "lt") 1568 * @param {string|number} value the right hand side value 1569 * @return {Expression} this expression 1570 */ 1571 1572 Expression.prototype.height = function(operator, value) { 1573 return this.predicate("h", operator, value); 1574 }; 1575 1576 1577 /** 1578 * @function Expression#width 1579 * @param {string} operator the comparison operator (e.g. "<", "lt") 1580 * @param {string|number} value the right hand side value 1581 * @return {Expression} this expression 1582 */ 1583 1584 Expression.prototype.width = function(operator, value) { 1585 return this.predicate("w", operator, value); 1586 }; 1587 1588 1589 /** 1590 * @function Expression#aspectRatio 1591 * @param {string} operator the comparison operator (e.g. "<", "lt") 1592 * @param {string|number} value the right hand side value 1593 * @return {Expression} this expression 1594 */ 1595 1596 Expression.prototype.aspectRatio = function(operator, value) { 1597 return this.predicate("ar", operator, value); 1598 }; 1599 1600 1601 /** 1602 * @function Expression#pages 1603 * @param {string} operator the comparison operator (e.g. "<", "lt") 1604 * @param {string|number} value the right hand side value 1605 * @return {Expression} this expression 1606 */ 1607
1608 Expression.prototype.pageCount = function(operator, value) { 1609 return this.predicate("pc", operator, value); 1610 }; 1611 1612 1613 /** 1614 * @function Expression#faces 1615 * @param {string} operator the comparison operator (e.g. "<", "lt") 1616 * @param {string|number} value the right hand side value 1617 * @return {Expression} this expression 1618 */ 1619 1620 Expression.prototype.faceCount = function(operator, value) { 1621 return this.predicate("fc", operator, value); 1622 }; 1623 1624 Expression.prototype.value = function(value) { 1625 this.expressions.push(value); 1626 return this; 1627 }; 1628 1629 1630 /** 1631 */ 1632 1633 Expression.variable = function(name, value) { 1634 return new this(name).value(value); 1635 }; 1636 1637 1638 /** 1639 * @returns a new expression with the predefined variable "width" 1640 * @function Expression.width 1641 */ 1642 1643 Expression.width = function() { 1644 return new this("width"); 1645 }; 1646 1647 1648 /** 1649 * @returns a new expression with the predefined variable "height" 1650 * @function Expression.height 1651 */ 1652 1653 Expression.height = function() { 1654 return new this("height"); 1655 }; 1656 1657 1658 /** 1659 * @returns a new expression with the predefined variable "initialWidth" 1660 * @function Expression.initialWidth 1661 */ 1662 1663 Expression.initialWidth = function() { 1664 return new this("initialWidth"); 1665 }; 1666 1667 1668 /** 1669 * @returns a new expression with the predefined variable "initialHeight" 1670 * @function Expression.initialHeight 1671 */ 1672 1673 Expression.initialHeight = function() { 1674 return new this("initialHeight"); 1675 }; 1676 1677 1678 /** 1679 * @returns a new expression with the predefined variable "aspectRatio" 1680 * @function Expression.aspectRatio 1681 */ 1682 1683 Expression.aspectRatio = function() { 1684 return new this("aspectRatio"); 1685 }; 1686 1687 1688 /** 1689 * @returns a new expression with the predefined variable "initialAspectRatio" 1690 * @function Expression.initialAspectRatio 1691 */ 1692 1693 Expression.initialAspectRatio = function() { 1694 return new this("initialAspectRatio"); 1695 }; 1696 1697 1698 /** 1699 * @returns a new expression with the predefined variable "pageCount" 1700 * @function Expression.pageCount 1701 */ 1702 1703 Expression.pageCount = function() { 1704 return new this("pageCount"); 1705 }; 1706 1707 1708 /** 1709 * @returns a new expression with the predefined variable "faceCount" 1710 * @function Expression.faceCount 1711 */ 1712 1713 faceCount = function() { 1714 return new this("faceCount"); 1715 }; 1716 1717 1718 /** 1719 * @returns a new expression with the predefined variable "currentPage" 1720 * @function Expression.currentPage 1721 */ 1722 1723 Expression.currentPage = function() { 1724 return new this("currentPage"); 1725 }; 1726 1727 1728 /** 1729 * @returns a new expression with the predefined variable "tags" 1730 * @function Expression.tags 1731 */ 1732 1733 Expression.tags = function() { 1734 return new this("tags"); 1735 }; 1736 1737 1738 /** 1739 * @returns a new expression with the predefined variable "pageX" 1740 * @function Expression.pageX 1741 */ 1742 1743 Expression.pageX = function() { 1744 return new this("pageX"); 1745 }; 1746 1747 1748 /** 1749 * @returns a new expression with the predefined variable "pageY" 1750 * @function Expression.pageY 1751 */ 1752 1753 Expression.pageY = function() { 1754 return new this("pageY"); 1755 }; 1756 1757 return Expression; 1758 1759 })(); 1760 Condition = (function(superClass) { 1761 extend(Condition, superClass); 1762 1763 1764 /** 1765 * Represents a transformation condition 1766 * @param {string} conditionStr - a condition in string format 1767 * @class Condition 1768 * @example 1769 * // normally this class is not instantiated directly 1770 * var tr = cloudinary.Transformation.new() 1771 * .if().width( ">", 1000).and().aspectRatio("<", "3:4").then() 1772 * .width(1000) 1773 * .crop("scale") 1774 * .else() 1775 * .width(500) 1776 * .crop("scale") 1777 * 1778 * var tr = cloudinary.Transformation.new() 1779 * .if("w > 1000 and aspectRatio < 3:4") 1780 * .width(1000) 1781 * .crop("scale") 1782 * .else() 1783 * .width(500) 1784 * .crop("scale") 1785 * 1786 */ 1787 1788 function Condition(conditionStr) { 1789 Condition.__super__.constructor.call(this, conditionStr); 1790 } 1791 1792 1793 /** 1794 * @function Condition#height 1795 * @param {string} operator the comparison operator (e.g. "<", "lt") 1796 * @param {string|number} value the right hand side value 1797 * @return {Condition} this condition 1798 */ 1799 1800 Condition.prototype.height = function(operator, value) { 1801 return this.predicate("h", operator, value); 1802 }; 1803 1804 1805 /** 1806 * @function Condition#width 1807 * @param {string} operator the comparison operator (e.g. "<", "lt") 1808 * @param {string|number} value the right hand side value 1809 * @return {Condition} this condition 1810 */ 1811 1812 Condition.prototype.width = function(operator, value) { 1813 return this.predicate("w", operator, value); 1814 }; 1815 1816 1817 /** 1818 * @function Condition#aspectRatio 1819 * @param {string} operator the comparison operator (e.g. "<", "lt") 1820 * @param {string|number} value the right hand side value 1821 * @return {Condition} this condition 1822 */ 1823 1824 Condition.prototype.aspectRatio = function(operator, value) { 1825 return this.predicate("ar", operator, value); 1826 }; 1827 1828 1829 /** 1830 * @function Condition#pages 1831 * @param {string} operator the comparison operator (e.g. "<", "lt") 1832 * @param {string|number} value the right hand side value 1833 * @return {Condition} this condition 1834 */ 1835
1836 Condition.prototype.pageCount = function(operator, value) { 1837 return this.predicate("pc", operator, value); 1838 }; 1839 1840 1841 /** 1842 * @function Condition#faces 1843 * @param {string} operator the comparison operator (e.g. "<", "lt") 1844 * @param {string|number} value the right hand side value 1845 * @return {Condition} this condition 1846 */ 1847 1848 Condition.prototype.faceCount = function(operator, value) { 1849 return this.predicate("fc", operator, value); 1850 }; 1851 1852 return Condition; 1853 1854 })(Expression); 1855 1856 /** 1857 * Cloudinary configuration class 1858 * Depends on 'utils' 1859 */ 1860 Configuration = (function() { 1861 1862 /** 1863 * Defaults configuration. 1864 */ 1865 var DEFAULT_CONFIGURATION_PARAMS, ref; 1866 1867 DEFAULT_CONFIGURATION_PARAMS = { 1868 responsive_class: 'cld-responsive', 1869 responsive_use_breakpoints: true, 1870 round_dpr: true, 1871 secure: (typeof window !== "undefined" && window !== null ? (ref = window.location) != null ? ref.protocol : void 0 : void 0) === 'https:' 1872 }; 1873 1874 Configuration.CONFIG_PARAMS = ["api_key", "api_secret", "callback", "cdn_subdomain", "cloud_name", "cname", "private_cdn", "protocol", "resource_type", "responsive", "responsive_class", "responsive_use_breakpoints", "responsive_width", "round_dpr", "secure", "secure_cdn_subdomain", "secure_distribution", "shorten", "type", "upload_preset", "url_suffix", "use_root_path", "version"]; 1875 1876 1877 /** 1878 * Cloudinary configuration class 1879 * @constructor Configuration 1880 * @param {Object} options - configuration parameters 1881 */ 1882 1883 function Configuration(options) { 1884 if (options == null) { 1885 options = {}; 1886 } 1887 this.configuration = Util.cloneDeep(options); 1888 Util.defaults(this.configuration, DEFAULT_CONFIGURATION_PARAMS); 1889 } 1890 1891 1892 /** 1893 * Initialize the configuration. 1894 * The function first tries to retrieve the configuration form the environment and then from the document. 1895 * @function Configuration#init 1896 * @return {Configuration} returns this for chaining 1897 * @see fromDocument 1898 * @see fromEnvironment 1899 */ 1900 1901 Configuration.prototype.init = function() { 1902 this.fromEnvironment(); 1903 this.fromDocument(); 1904 return this; 1905 }; 1906 1907 1908 /** 1909 * Set a new configuration item 1910 * @function Configuration#set 1911 * @param {string} name - the name of the item to set 1912 * @param {*} value - the value to be set 1913 * @return {Configuration} 1914 * 1915 */ 1916 1917 Configuration.prototype.set = function(name, value) { 1918 this.configuration[name] = value; 1919 return this; 1920 }; 1921 1922 1923 /** 1924 * Get the value of a configuration item 1925 * @function Configuration#get 1926 * @param {string} name - the name of the item to set 1927 * @return {*} the configuration item 1928 */ 1929 1930 Configuration.prototype.get = function(name) { 1931 return this.configuration[name]; 1932 }; 1933 1934 Configuration.prototype.merge = function(config) { 1935 if (config == null) { 1936 config = {}; 1937 } 1938 Util.assign(this.configuration, Util.cloneDeep(config)); 1939 return this; 1940 }; 1941 1942 1943 /** 1944 * Initialize Cloudinary from HTML meta tags. 1945 * @function Configuration#fromDocument 1946 * @return {Configuration} 1947 * @example <meta name="cloudinary_cloud_name" content="mycloud"> 1948 * 1949 */ 1950 1951 Configuration.prototype.fromDocument = function() { 1952 var el, j, len, meta_elements; 1953 meta_elements = typeof document !== "undefined" && document !== null ? document.querySelectorAll('meta[name^="cloudinary_"]') : void 0; 1954 if (meta_elements) { 1955 for (j = 0, len = meta_elements.length; j < len; j++) { 1956 el = meta_elements[j]; 1957 this.configuration[el.getAttribute('name').replace('cloudinary_', '')] = el.getAttribute('content'); 1958 } 1959 } 1960 return this; 1961 }; 1962 1963 1964 /** 1965 * Initialize Cloudinary from the `CLOUDINARY_URL` environment variable. 1966 * 1967 * This function will only run under Node.js environment. 1968 * @function Configuration#fromEnvironment 1969 * @requires Node.js 1970 */ 1971 1972 Configuration.prototype.fromEnvironment = function() { 1973 var cloudinary_url, j, k, len, query, ref1, ref2, ref3, uri, uri
1973Regex, v, value; 1974 cloudinary_url = typeof process !== "undefined" && process !== null ? (ref1 = process.env) != null ? ref1.CLOUDINARY_URL : void 0 : void 0; 1975 if (cloudinary_url != null) { 1976 uriRegex = /cloudinary:\/\/(?:(\w+)(?:\:([\w-]+))?@)?([\w\.-]+)(?:\/([^?]*))?(?:\?(.+))?/; 1977 uri = uriRegex.exec(cloudinary_url); 1978 if (uri) { 1979 if (uri[3] != null) { 1980 this.configuration['cloud_name'] = uri[3]; 1981 } 1982 if (uri[1] != null) { 1983 this.configuration['api_key'] = uri[1]; 1984 } 1985 if (uri[2] != null) { 1986 this.configuration['api_secret'] = uri[2]; 1987 } 1988 if (uri[4] != null) { 1989 this.configuration['private_cdn'] = uri[4] != null; 1990 } 1991 if (uri[4] != null) { 1992 this.configuration['secure_distribution'] = uri[4]; 1993 } 1994 query = uri[5]; 1995 if (query != null) { 1996 ref2 = query.split('&'); 1997 for (j = 0, len = ref2.length; j < len; j++) { 1998 value = ref2[j]; 1999 ref3 = value.split('='), k = ref3[0], v = ref3[1]; 2000 if (v == null) { 2001 v = true; 2002 } 2003 this.configuration[k] = v; 2004 } 2005 } 2006 } 2007 } 2008 return this; 2009 }; 2010 2011 2012 /** 2013 * Create or modify the Cloudinary client configuration 2014 * 2015 * Warning: `config()` returns the actual internal configuration object. modifying it will change the configuration. 2016 * 2017 * This is a backward compatibility method. For new code, use get(), merge() etc. 2018 * @function Configuration#config 2019 * @param {hash|string|boolean} new_config 2020 * @param {string} new_value 2021 * @returns {*} configuration, or value 2022 * 2023 * @see {@link fromEnvironment} for initialization using environment variables 2024 * @see {@link fromDocument} for initialization using HTML meta tags 2025 */ 2026 2027 Configuration.prototype.config = function(new_config, new_value) { 2028 switch (false) { 2029 case new_value === void 0: 2030 this.set(new_config, new_value); 2031 return this.configuration; 2032 case !Util.isString(new_config): 2033 return this.get(new_config); 2034 case !Util.isPlainObject(new_config): 2035 this.merge(new_config); 2036 return this.configuration; 2037 default: 2038 return this.configuration; 2039 } 2040 }; 2041 2042 2043 /** 2044 * Returns a copy of the configuration parameters 2045 * @function Configuration#toOptions 2046 * @returns {Object} a key:value collection of the configuration parameters 2047 */ 2048 2049 Configuration.prototype.toOptions = function() { 2050 return Util.cloneDeep(this.configuration); 2051 }; 2052 2053 return Configuration; 2054 2055 })(); 2056 2057 /** 2058 * TransformationBase 2059 * Depends on 'configuration', 'parameters','util' 2060 * @internal 2061 */ 2062 TransformationBase = (function() { 2063 var VAR_NAME_RE, lastArgCallback, processVar; 2064 2065 VAR_NAME_RE = /^\$[a-zA-Z0-9]+$/; 2066 2067 TransformationBase.prototype.trans_separator = '/'; 2068 2069 TransformationBase.prototype.param_separator = ','; 2070 2071 lastArgCallback = function(args) { 2072 var callback; 2073 callback = args != null ? args[args.length - 1] : void 0; 2074 if (Util.isFunction(callback)) { 2075 return callback; 2076 } else { 2077 return void 0; 2078 } 2079 }; 2080 2081 2082 /** 2083 * The base class for transformations. 2084 * Members of this class are documented as belonging to the {@link Transformation} class for convenience. 2085 * @class TransformationBase 2086 */ 2087 2088 function TransformationBase(options) { 2089 var parent, trans; 2090 if (options == null) { 2091 options = {}; 2092 } 2093 2094 /** @private */ 2095 parent = void 0; 2096 2097 /** @private */ 2098 trans = {}; 2099 2100 /** 2101 * Return an options object that can be used to create an identical Transformation 2102 * @function Transformation#toOptions 2103 * @return {Object} Returns a plain object representing this transformation 2104 */ 2105 this.toOptions || (this.toOptions = function(withChain) { 2106 var key, list, opt, ref, ref1, tr, value; 2107 if (withChain == null) { 2108 withChain = true; 2109 } 2110 opt = {}; 2111 for (key in trans) { 2112 value = trans[key]; 2113 opt[key] = value.origValue; 2114 } 2115 ref = this.otherOptions; 2116 for (key in ref) { 2117 value = ref[key]; 2118 if (value !== void 0) { 2119 opt[key] = value; 2120 } 2121 } 2122 if (withChain && !Util.isEmpty(this.chained)) { 2123 list = (function() { 2124 var j, len, ref1, results; 2125 ref1 = this.chained; 2126 results = []; 2127 for (j = 0, len = ref1.length; j < len; j++) { 2128 tr = ref1[j]; 2129 results.push(tr.toOptions()); 2130 } 2131 return results; 2132 }).call(this); 2133 list.push(opt); 2134 opt = {}; 2135 ref1 = this.otherOptions; 2136 for (key in ref1) { 2137 value = ref1[key]; 2138 if (value !== void 0) { 2139 opt[key] = value; 2140 } 2141 } 2142 opt.transformation = list; 2143 } 2144 return opt; 2145 }); 2146 2147 /** 2148 * Set a parent for this object for chaining purposes. 2149 * 2150 * @function Transformation#setParent 2151 * @param {Object} object - the parent to be assigned to 2152 * @returns {Transformation} Returns this instance for chaining purposes. 2153 */ 2154 this.setParent || (this.setParent = function(object) { 2155 parent = object; 2156 if (object != null) { 2157 this.fromOptions(typeof object.toOptions === "function" ? object.toOptions() : void 0); 2158 } 2159 return this; 2160 }); 2161 2162 /** 2163 * Returns the parent of this object in the chain 2164 * @function Transformation#getParent 2165 * @protected 2166 * @return {Object} Returns the parent of this object if there is any 2167 */ 2168 this.getParent || (this.getParent = function() { 2169 return parent; 2170 }); 2171 2172 /** @protected */ 2173 this.param || (this.param = function(value, name, abbr, defaultValue, process) { 2174 if (process == null) { 2175 if (Util.isFunction(defaultValue)) { 2176 process = defaultValue; 2177 } else { 2178 process = Util.identity; 2179 } 2180 } 2181 trans[name] = new Param(name, abbr, process).set(value); 2182 return this; 2183 }); 2184 2185 /** @protected */ 2186 this.rawParam || (this.rawParam = function(value, name, abbr, defaultValue, process) { 2187 if (process == null) { 2188 process = Util.identity; 2189 } 2190 process = lastArgCallback(arguments); 2191 trans[name] = new RawParam(name, abbr, process).set(value); 2192 return this; 2193 }); 2194 2195 /** @protected */ 2196 this.rangeParam || (this.rangeParam = function(value, name, abbr, defaultValue, process) { 2197 if (process == null) { 2198 process = Util.identity; 2199 } 2200 process = lastArgCallback(arguments); 2201 trans[name] = new RangeParam(name, abbr, process).set(value); 2202 return this; 2203 }); 2204 2205 /** @protected */ 2206 this.arrayParam || (this.arrayParam = function(value, name, abbr, sep, defaultValue, process) { 2207 if (sep == null) { 2208 sep = ":"; 2209 } 2210 if (defaultValue == null) { 2211 defaultValue = []; 2212 } 2213 if (process == null) { 2214 process = Util.identity; 2215 } 2216 process = lastArgCallback(arguments); 2217 trans[name] = new ArrayParam(name, abbr, sep, process).set(value); 2218 return this; 2219 }); 2220 2221 /** @protected */ 2222 this.transformationParam || (this.transformationParam = function(value, name, abbr, sep, defaultValue, process) { 2223 if (sep == null) { 2224 sep = "."; 2225 } 2226 if (process == null) { 2227 process = Util.identity; 2228 } 2229 process = lastArgCallback(arguments); 2230 trans[name] = new TransformationParam(name, abbr, sep, process).set(value); 2231 return this; 2232 }); 2233 this.layerParam || (this.layerParam = function(value, name, abbr) {
2234 trans[name] = new LayerParam(name, abbr).set(value); 2235 return this; 2236 }); 2237 2238 /** 2239 * Get the value associated with the given name. 2240 * @function Transformation#getValue 2241 * @param {string} name - the name of the parameter 2242 * @return {*} the processed value associated with the given name 2243 * @description Use {@link get}.origValue for the value originally provided for the parameter 2244 */ 2245 this.getValue || (this.getValue = function(name) { 2246 var ref, ref1; 2247 return (ref = (ref1 = trans[name]) != null ? ref1.value() : void 0) != null ? ref : this.otherOptions[name]; 2248 }); 2249 2250 /** 2251 * Get the parameter object for the given parameter name 2252 * @function Transformation#get 2253 * @param {string} name the name of the transformation parameter 2254 * @returns {Param} the param object for the given name, or undefined 2255 */ 2256 this.get || (this.get = function(name) { 2257 return trans[name]; 2258 }); 2259 2260 /** 2261 * Remove a transformation option from the transformation. 2262 * @function Transformation#remove 2263 * @param {string} name - the name of the option to remove 2264 * @return {*} Returns the option that was removed or null if no option by that name was found. The type of the 2265 * returned value depends on the value. 2266 */ 2267 this.remove || (this.remove = function(name) { 2268 var temp; 2269 switch (false) { 2270 case trans[name] == null: 2271 temp = trans[name]; 2272 delete trans[name]; 2273 return temp.origValue; 2274 case this.otherOptions[name] == null: 2275 temp = this.otherOptions[name]; 2276 delete this.otherOptions[name]; 2277 return temp; 2278 default: 2279 return null; 2280 } 2281 }); 2282 2283 /** 2284 * Return an array of all the keys (option names) in the transformation. 2285 * @return {Array<string>} the keys in snakeCase format 2286 */ 2287 this.keys || (this.keys = function() { 2288 var key; 2289 return ((function() { 2290 var results; 2291 results = []; 2292 for (key in trans) { 2293 if (key != null) { 2294 results.push(key.match(VAR_NAME_RE) ? key : Util.snakeCase(key)); 2295 } 2296 } 2297 return results; 2298 })()).sort(); 2299 }); 2300 2301 /** 2302 * Returns a plain object representation of the transformation. Values are processed. 2303 * @function Transformation#toPlainObject 2304 * @return {Object} the transformation options as plain object 2305 */ 2306 this.toPlainObject || (this.toPlainObject = function() { 2307 var hash, key, list, tr; 2308 hash = {}; 2309 for (key in trans) { 2310 hash[key] = trans[key].value(); 2311 if (Util.isPlainObject(hash[key])) { 2312 hash[key] = Util.cloneDeep(hash[key]); 2313 } 2314 } 2315 if (!Util.isEmpty(this.chained)) { 2316 list = (function() { 2317 var j, len, ref, results; 2318 ref = this.chained; 2319 results = []; 2320 for (j = 0, len = ref.length; j < len; j++) { 2321 tr = ref[j]; 2322 results.push(tr.toPlainObject()); 2323 } 2324 return results; 2325 }).call(this); 2326 list.push(hash); 2327 hash = { 2328 transformation: list 2329 }; 2330 } 2331 return hash; 2332 }); 2333 2334 /** 2335 * Complete the current transformation and chain to a new one. 2336 * In the URL, transformations are chained together by slashes. 2337 * @function Transformation#chain 2338 * @return {Transformation} Returns this transformation for chaining 2339 * @example 2340 * var tr = cloudinary.Transformation.new(); 2341 * tr.width(10).crop('fit').chain().angle(15).serialize() 2342 * // produces "c_fit,w_10/a_15" 2343 */ 2344 this.chain || (this.chain = function() { 2345 var names, tr; 2346 names = Object.getOwnPropertyNames(trans); 2347 if (names.length !== 0) { 2348 tr = new this.constructor(this.toOptions(false)); 2349 this.resetTransformations(); 2350 this.chained.push(tr); 2351 } 2352 return this; 2353 }); 2354 this.resetTransformations || (this.resetTransformations = function() { 2355 trans = {}; 2356 return this; 2357 }); 2358 this.otherOptions || (this.otherOptions = {}); 2359 this.chained = []; 2360 if (!Util.isEmpty(options)) { 2361 this.fromOptions(options); 2362 } 2363 } 2364 2365 2366 /** 2367 * Merge the provided options with own's options 2368 * @param {Object} [options={}] key-value list of options 2369 * @returns {Transformation} Returns this instance for chaining 2370 */ 2371 2372 TransformationBase.prototype.fromOptions = function(options) { 2373 var key, opt; 2374 if (options instanceof TransformationBase) { 2375 this.fromTransformation(options); 2376 } else {
2377 options || (options = {}); 2378 if (Util.isString(options) || Util.isArray(options)) { 2379 options = { 2380 transformation: options 2381 }; 2382 } 2383 options = Util.cloneDeep(options, function(value) { 2384 if (value instanceof TransformationBase) { 2385 return new value.constructor(value.toOptions()); 2386 } 2387 }); 2388 if (options["if"]) { 2389 this.set("if", options["if"]); 2390 delete options["if"]; 2391 } 2392 for (key in options) { 2393 opt = options[key]; 2394 if (key.match(VAR_NAME_RE)) { 2395 if (key !== '$attr') { 2396 this.set('variable', key, opt); 2397 } 2398 } else { 2399 this.set(key, opt); 2400 } 2401 } 2402 } 2403 return this; 2404 }; 2405 2406 TransformationBase.prototype.fromTransformation = function(other) { 2407 var j, key, len, ref; 2408 if (other instanceof TransformationBase) { 2409 ref = other.keys(); 2410 for (j = 0, len = ref.length; j < len; j++) { 2411 key = ref[j]; 2412 this.set(key, other.get(key).origValue); 2413 } 2414 } 2415 return this; 2416 }; 2417 2418 2419 /** 2420 * Set a parameter. 2421 * The parameter name `key` is converted to 2422 * @param {string} key - the name of the parameter 2423 * @param {*} value - the value of the parameter 2424 * @returns {Transformation} Returns this instance for chaining 2425 */ 2426 2427 TransformationBase.prototype.set = function() { 2428 var camelKey, key, values; 2429 key = arguments[0], values = 2 <= arguments.length ? slice.call(arguments, 1) : []; 2430 camelKey = Util.camelCase(key); 2431 if (Util.contains(Transformation.methods, camelKey)) { 2432 this[camelKey].apply(this, values); 2433 } else { 2434 this.otherOptions[key] = values[0]; 2435 } 2436 return this; 2437 }; 2438 2439 TransformationBase.prototype.hasLayer = function() { 2440 return this.getValue("overlay") || this.getValue("underlay"); 2441 }; 2442 2443 2444 /** 2445 * Generate a string representation of the transformation. 2446 * @function Transformation#serialize 2447 * @return {string} Returns the transformation as a string 2448 */ 2449 2450 TransformationBase.prototype.serialize = function() { 2451 var ifParam, j, len, paramList, ref, ref1, ref2, ref3, ref4, resultArray, t, tr, transformationList, transformationString, transformations, value, variables, vars; 2452 resultArray = (function() { 2453 var j, len, ref, results; 2454 ref = this.chained; 2455 results = []; 2456 for (j = 0, len = ref.length; j < len; j++) { 2457 tr = ref[j]; 2458 results.push(tr.serialize()); 2459 } 2460 return results; 2461 }).call(this); 2462 paramList = this.keys(); 2463 transformations = (ref = this.get("transformation")) != null ? ref.serialize() : void 0; 2464 ifParam = (ref1 = this.get("if")) != null ? ref1.serialize() : void 0; 2465 variables = processVar((ref2 = this.get("variables")) != null ? ref2.value() : void 0); 2466 paramList = Util.difference(paramList, ["transformation", "if", "variables"]); 2467 vars = []; 2468 transformationList = []; 2469 for (j = 0, len = paramList.length; j < len; j++) { 2470 t = paramList[j]; 2471 if (t.match(VAR_NAME_RE)) { 2472 vars.push(t + "_" + Expression.normalize((ref3 = this.get(t)) != null ? ref3.value() : void 0)); 2473 } else { 2474 transformationList.push((ref4 = this.get(t)) != null ? ref4.serialize() : void 0); 2475 } 2476 } 2477 switch (false) { 2478 case !Util.isString(transformations): 2479 transformationList.push(transformations); 2480 break; 2481 case !Util.isArray(transformations): 2482 resultArray = resultArray.concat(transformations); 2483 } 2484 transformationList = (function() { 2485 var l, len1, results; 2486 results = []; 2487 for (l = 0, len1 = transformationList.length; l < len1; l++) { 2488 value = transformationList[l]; 2489 if (Util.isArray(value) && !Util.isEmpty(value) || !Util.isArray(value) && value) { 2490 results.push(value); 2491 } 2492 } 2493 return results; 2494 })(); 2495 transformationList = vars.sort().concat(variables).concat(transformationList.sort()); 2496 if (ifParam === "if_end") { 2497 transformationList.push(ifParam); 2498 } else if (!Util.isEmpty(ifParam)) { 2499 transformationList.unshift(ifParam); 2500 } 2501 transformationString = Util.compact(transformationList).join(this.param_separator); 2502 if (!Util.isEmpty(transformationString)) { 2503 resultArray.push(transformationString); 2504 }
2505 return Util.compact(resultArray).join(this.trans_separator); 2506 }; 2507 2508 2509 /** 2510 * Provide a list of all the valid transformation option names 2511 * @function Transformation#listNames 2512 * @private 2513 * @return {Array<string>} a array of all the valid option names 2514 */ 2515 2516 TransformationBase.prototype.listNames = function() { 2517 return Transformation.methods; 2518 }; 2519 2520 2521 /** 2522 * Returns attributes for an HTML tag. 2523 * @function Cloudinary.toHtmlAttributes 2524 * @return PlainObject 2525 */ 2526 2527 TransformationBase.prototype.toHtmlAttributes = function() { 2528 var attrName, height, j, key, len, options, ref, ref1, ref2, ref3, value; 2529 options = {}; 2530 ref = this.otherOptions; 2531 for (key in ref) { 2532 value = ref[key]; 2533 if (!(!Util.contains(Transformation.PARAM_NAMES, Util.snakeCase(key)))) { 2534 continue; 2535 } 2536 attrName = /^html_/.test(key) ? key.slice(5) : key; 2537 options[attrName] = value; 2538 } 2539 ref1 = this.keys(); 2540 for (j = 0, len = ref1.length; j < len; j++) { 2541 key = ref1[j]; 2542 if (/^html_/.test(key)) { 2543 options[Util.camelCase(key.slice(5))] = this.getValue(key); 2544 } 2545 } 2546 if (!(this.hasLayer() || this.getValue("angle") || Util.contains(["fit", "limit", "lfill"], this.getValue("crop")))) { 2547 width = (ref2 = this.get("width")) != null ? ref2.origValue : void 0; 2548 height = (ref3 = this.get("height")) != null ? ref3.origValue : void 0; 2549 if (parseFloat(width) >= 1.0) { 2550 if (options['width'] == null) { 2551 options['width'] = width; 2552 } 2553 } 2554 if (parseFloat(height) >= 1.0) { 2555 if (options['height'] == null) { 2556 options['height'] = height; 2557 } 2558 } 2559 } 2560 return options; 2561 }; 2562 2563 TransformationBase.prototype.isValidParamName = function(name) { 2564 return Transformation.methods.indexOf(Util.camelCase(name)) >= 0; 2565 }; 2566 2567 2568 /** 2569 * Delegate to the parent (up the call chain) to produce HTML 2570 * @function Transformation#toHtml 2571 * @return {string} HTML representation of the parent if possible. 2572 * @example
2573 * tag = cloudinary.ImageTag.new("sample", {cloud_name: "demo"}) 2574 * // ImageTag {name: "img", publicId: "sample"} 2575 * tag.toHtml() 2576 * // <img src="http://res.cloudinary.com/demo/image/upload/sample"> 2577 * tag.transformation().crop("fit").width(300).toHtml() 2578 * // <img src="http://res.cloudinary.com/demo/image/upload/c_fit,w_300/sample"> 2579 */ 2580 2581 TransformationBase.prototype.toHtml = function() { 2582 var ref; 2583 return (ref = this.getParent()) != null ? typeof ref.toHtml === "function" ? ref.toHtml() : void 0 : void 0; 2584 }; 2585 2586 TransformationBase.prototype.toString = function() { 2587 return this.serialize(); 2588 }; 2589 2590 processVar = function(varArray) { 2591 var j, len, name, ref, results, v; 2592 if (Util.isArray(varArray)) { 2593 results = []; 2594 for (j = 0, len = varArray.length; j < len; j++) { 2595 ref = varArray[j], name = ref[0], v = ref[1]; 2596 results.push(name + "_" + (Expression.normalize(v))); 2597 } 2598 return results; 2599 } else { 2600 return varArray; 2601 } 2602 2603 /** 2604 * Transformation Class methods. 2605 * This is a list of the parameters defined in Transformation. 2606 * Values are camelCased. 2607 * @const Transformation.methods 2608 * @private 2609 * @ignore 2610 * @type {Array<string>} 2611 */ 2612 2613 /** 2614 * Parameters that are filtered out before passing the options to an HTML tag. 2615 * 2616 * The list of parameters is a combination of `Transformation::methods` and `Configuration::CONFIG_PARAMS` 2617 * @const {Array<string>} Transformation.PARAM_NAMES 2618 * @private 2619 * @ignore 2620 * @see toHtmlAttributes 2621 */ 2622 }; 2623 2624 return TransformationBase; 2625 2626 })(); 2627 Transformation = (function(superClass) { 2628 extend(Transformation, superClass); 2629 2630 2631 /** 2632 * Represents a single transformation. 2633 * @class Transformation 2634 * @example 2635 * t = new cloudinary.Transformation(); 2636 * t.angle(20).crop("scale").width("auto"); 2637 * 2638 * // or 2639 * 2640 * t = new cloudinary.Transformation( {angle: 20, crop: "scale", width: "auto"}); 2641 */ 2642 2643 function Transformation(options) { 2644 if (options == null) { 2645 options = {}; 2646 } 2647 Transformation.__super__.constructor.call(this, options); 2648 this; 2649 } 2650 2651 2652 /** 2653 * Convenience constructor 2654 * @param {Object} options 2655 * @return {Transformation} 2656 * @example cl = cloudinary.Transformation.new( {angle: 20, crop: "scale", width: "auto"}) 2657 */ 2658 2659 Transformation["new"] = function(args) { 2660 return new Transformation(args); 2661 }; 2662 2663 2664 /* 2665 Transformation Parameters 2666 */ 2667 2668 Transformation.prototype.angle = function(value) { 2669 return this.arrayParam(value, "angle", "a", ".", Expression.normalize); 2670 }; 2671 2672 Transformation.prototype.audioCodec = function(value) { 2673 return this.param(value, "audio_codec", "ac"); 2674 }; 2675 2676 Transformation.prototype.audioFrequency = function(value) { 2677 return this.param(value, "audio_frequency", "af"); 2678 }; 2679 2680 Transformation.prototype.aspectRatio = function(value) { 2681 return this.param(value, "aspect_ratio", "ar", Expression.normalize); 2682 }; 2683 2684 Transformation.prototype.background = function(value) { 2685 return this.param(value, "background", "b", Param.norm_color); 2686 }; 2687 2688 Transformation.prototype.bitRate = function(value) { 2689 return this.param(value, "bit_rate", "br"); 2690 }; 2691 2692 Transformation.prototype.border = function(value) { 2693 return this.param(value, "border", "bo", function(border) { 2694 if (Util.isPlainObject(border)) { 2695 border = Util.assign({}, { 2696 color: "black", 2697 width: 2 2698 }, border); 2699 return border.width + "px_solid_" + (Param.norm_color(border.color)); 2700 } else { 2701 return border; 2702 } 2703 }); 2704 }; 2705 2706 Transformation.prototype.color = function(value) { 2707 return this.param(value, "color", "co", Param.norm_color); 2708 }; 2709 2710 Transformation.prototype.colorSpace = function(value) { 2711 return this.param(value, "color_space", "cs"); 2712 }; 2713 2714 Transformation.prototype.crop = function(value) { 2715 return this.param(value, "crop", "c"); 2716 }; 2717 2718 Transformation.prototype.defaultImage = function(value) { 2719 return this.param(value, "default_image", "d"); 2720 }; 2721 2722 Transformation.prototype.delay = function(value) { 2723 return this.param(value, "delay", "dl"); 2724 }; 2725 2726 Transformation.prototype.density = function(value) { 2727 return this.param(value, "density", "dn"); 2728 }; 2729 2730 Transformation.prototype.duration = function(value) { 2731 return this.rangeParam(value, "duration", "du"); 2732 }; 2733 2734 Transformation.prototype.dpr = function(value) { 2735 return this.param(value, "dpr", "dpr", (function(_this) { 2736 return function(dpr) { 2737 dpr = dpr.toString(); 2738 if (dpr != null ? dpr.match(/^\d+$/) : void 0) { 2739 return dpr + ".0"; 2740 } else { 2741 return Expression.normalize(dpr); 2742 } 2743 }; 2744 })(this)); 2745 }; 2746 2747 Transformation.prototype.effect = function(value) { 2748 return this.arrayParam(value, "effect", "e", ":", Expression.normalize); 2749 }; 2750 2751 Transformation.prototype["else"] = function() { 2752 return this["if"]('else'); 2753 }; 2754 2755 Transformation.prototype.endIf = function() { 2756 return this["if"]('end'); 2757 }; 2758 2759 Transformation.prototype.endOffset = function(value) { 2760 return this.rangeParam(value, "end_offset", "eo"); 2761 }; 2762 2763 Transformation.prototype.fallbackContent = function(value) { 2764 return this.param(value, "fallback_content"); 2765 }; 2766 2767 Transformation.prototype.fetchFormat = function(value) { 2768 return this.param(value, "fetch_format", "f"); 2769 }; 2770 2771 Transformation.prototype.format = function(value) { 2772 return this.param(value, "format"); 2773 }; 2774 2775 Transformation.prototype.flags = function(value) { 2776 return this.arrayParam(value, "flags", "fl", "."); 2777 }; 2778 2779 Transformation.prototype.gravity = function(value) { 2780 return this.param(value, "gravity", "g"); 2781 }; 2782 2783 Transformation.prototype.fps = function(value) { 2784 return this.param(value, "fps", "fps", (function(_this) { 2785 return function(fps) { 2786 if (Util.isString(fps)) { 2787 return fps; 2788 } else if (Util.isArray(fps)) { 2789 return fps.join("-"); 2790 } else { 2791 return fps; 2792 } 2793 }; 2794 })(this)); 2795 }; 2796 2797 Transformation.prototype.height = function(value) { 2798 return this.param(value, "height", "h", (function(_this) { 2799 return function() { 2800 if (_this.getValue("crop") || _this.getValue("overlay") || _this.getValue("underlay")) { 2801 return Expression.normalize(value); 2802 } else { 2803 return null; 2804 } 2805 }; 2806 })(this)); 2807 }; 2808 2809 Transformation.prototype.htmlHeight = function(value) { 2810 return this.param(value, "html_height"); 2811 }; 2812 2813 Transformation.prototype.htmlWidth = function(value) { 2814 return this.param(value, "html_width"); 2815 }; 2816 2817 Transformation.prototype["if"] = function(value) { 2818 var i, ifVal, j, ref, trIf, trRest; 2819 if (value == null) { 2820 value = ""; 2821 } 2822 switch (value) { 2823 case "else": 2824 this.chain(); 2825 return this.param(value, "if", "if"); 2826 case "end": 2827 this.chain(); 2828 for (i = j = ref = this.chained.length - 1; j >= 0; i = j += -1) { 2829 ifVal = this.chained[i].getValue("if"); 2830 if (ifVal === "end") { 2831 break; 2832 } else if (ifVal != null) { 2833 trIf = Transformation["new"]()["if"](ifVal); 2834 this.chained[i].remove("if"); 2835 trRest = this.chained[i]; 2836 this.chained[i] = Transformation["new"]().transformation([trIf, trRest]); 2837 if (ifVal !== "else") { 2838 break; 2839 } 2840 } 2841 } 2842 return this.param(value, "if", "if"); 2843 case "": 2844 return Condition["new"]().setParent(this); 2845 default: 2846 return this.param(value, "if", "if", function(value) { 2847 return Condition["new"](value).toString(); 2848 }); 2849 } 2850 }; 2851 2852 Transformation.prototype.keyframeInterval = function(value) { 2853 return this.param(value, "keyframe_interval", "ki"); 2854 }; 2855 2856 Transformation.prototype.offset = function(value) { 2857 var end_o, ref, start_o; 2858 ref = Util.isFunction(value != null ? value.split : void 0) ? value.split('..')
2858: Util.isArray(value) ? value : [null, null], start_o = ref[0], end_o = ref[1]; 2859 if (start_o != null) { 2860 this.startOffset(start_o); 2861 } 2862 if (end_o != null) { 2863 return this.endOffset(end_o); 2864 } 2865 }; 2866 2867 Transformation.prototype.opacity = function(value) { 2868 return this.param(value, "opacity", "o", Expression.normalize); 2869 }; 2870 2871 Transformation.prototype.overlay = function(value) { 2872 return this.layerParam(value, "overlay", "l"); 2873 }; 2874 2875 Transformation.prototype.page = function(value) { 2876 return this.param(value, "page", "pg"); 2877 }; 2878 2879 Transformation.prototype.poster = function(value) { 2880 return this.param(value, "poster"); 2881 }; 2882 2883 Transformation.prototype.prefix = function(value) { 2884 return this.param(value, "prefix", "p"); 2885 }; 2886 2887 Transformation.prototype.quality = function(value) { 2888 return this.param(value, "quality", "q", Expression.normalize); 2889 }; 2890 2891 Transformation.prototype.radius = function(value) {
2892 return this.param(value, "radius", "r", Expression.normalize); 2893 }; 2894 2895 Transformation.prototype.rawTransformation = function(value) { 2896 return this.rawParam(value, "raw_transformation"); 2897 }; 2898 2899 Transformation.prototype.size = function(value) { 2900 var height, ref; 2901 if (Util.isFunction(value != null ? value.split : void 0)) { 2902 ref = value.split('x'), width = ref[0], height = ref[1]; 2903 this.width(width); 2904 return this.height(height); 2905 } 2906 }; 2907 2908 Transformation.prototype.sourceTypes = function(value) { 2909 return this.param(value, "source_types"); 2910 }; 2911 2912 Transformation.prototype.sourceTransformation = function(value) { 2913 return this.param(value, "source_transformation"); 2914 }; 2915 2916 Transformation.prototype.startOffset = function(value) { 2917 return this.rangeParam(value, "start_offset", "so"); 2918 }; 2919 2920 Transformation.prototype.streamingProfile = function(value) { 2921 return this.param(value, "streaming_profile", "sp"); 2922 }; 2923 2924 Transformation.prototype.transformation = function(value) { 2925 return this.transformationParam(value, "transformation", "t"); 2926 }; 2927 2928 Transformation.prototype.underlay = function(value) { 2929 return this.layerParam(value, "underlay", "u"); 2930 }; 2931 2932 Transformation.prototype.variable = function(name, value) { 2933 return this.param(value, name, name); 2934 }; 2935 2936 Transformation.prototype.variables = function(values) { 2937 return this.arrayParam(values, "variables"); 2938 }; 2939 2940 Transformation.prototype.videoCodec = function(value) { 2941 return this.param(value, "video_codec", "vc", Param.process_video_params); 2942 }; 2943 2944 Transformation.prototype.videoSampling = function(value) { 2945 return this.param(value, "video_sampling", "vs"); 2946 }; 2947 2948 Transformation.prototype.width = function(value) { 2949 return this.param(value, "width", "w", (function(_this) { 2950 return function() { 2951 if (_this.getValue("crop") || _this.getValue("overlay") || _this.getValue("underlay")) { 2952 return Expression.normalize(value); 2953 } else { 2954 return null; 2955 } 2956 }; 2957 })(this)); 2958 }; 2959 2960 Transformation.prototype.x = function(value) { 2961 return this.param(value, "x", "x", Expression.normalize); 2962 }; 2963 2964 Transformation.prototype.y = function(value) { 2965 return this.param(value, "y", "y", Expression.normalize); 2966 }; 2967 2968 Transformation.prototype.zoom = function(value) { 2969 return this.param(value, "zoom", "z", Expression.normalize); 2970 }; 2971 2972 return Transformation; 2973 2974 })(TransformationBase); 2975 2976 /** 2977 * Transformation Class methods. 2978 * This is a list of the parameters defined in Transformation. 2979 * Values are camelCased. 2980 */ 2981 Transformation.methods || (Transformation.methods = Util.difference(Util.functions(Transformation.prototype), Util.functions(TransformationBase.prototype))); 2982 2983 /** 2984 * Parameters that are filtered out before passing the options to an HTML tag. 2985 * 2986 * The list of parameters is a combination of `Transformation::methods` and `Configuration::CONFIG_PARAMS` 2987 */ 2988 Transformation.PARAM_NAMES || (Transformation.PARAM_NAMES = ((function() { 2989 var j, len, ref, results; 2990 ref = Transformation.methods; 2991 results = []; 2992 for (j = 0, len = ref.length; j < len; j++) { 2993 m = ref[j]; 2994 results.push(Util.snakeCase(m)); 2995 } 2996 return results; 2997 })()).concat(Configuration.CONFIG_PARAMS)); 2998 2999 /** 3000 * Generic HTML tag 3001 * Depends on 'transformation', 'util' 3002 */ 3003 HtmlTag = (function() { 3004 3005 /** 3006 * Represents an HTML (DOM) tag 3007 * @constructor HtmlTag 3008 * @param {string} name - the name of the tag 3009 * @param {string} [publicId] 3010 * @param {Object} options 3011 * @example tag = new HtmlTag( 'div', { 'width': 10}) 3012 */ 3013 var toAttribute; 3014 3015 function HtmlTag(name, publicId, options) { 3016 var transformation; 3017 this.name = name; 3018 this.publicId = publicId; 3019 if (options == null) { 3020 if (Util.isPlainObject(publicId)) { 3021 options = publicId; 3022 this.publicId = void 0; 3023 } else { 3024 options = {}; 3025 } 3026 } 3027 transformation = new Transformation(options); 3028 transformation.setParent(this); 3029 this.transformation = function() { 3030 return transformation; 3031 }; 3032 } 3033 3034 3035 /** 3036 * Convenience constructor 3037 * Creates a new instance of an HTML (DOM) tag 3038 * @function HtmlTag.new 3039 * @param {string} name - the name of the tag 3040 * @param {string} [publicId] 3041 * @param {Object} options 3042 * @return {HtmlTag} 3043 * @example tag = HtmlTag.new( 'div', { 'width': 10}) 3044 */ 3045 3046 HtmlTag["new"] = function(name, publicId, options) { 3047 return new this(name, publicId, options); 3048 }; 3049 3050 3051 /** 3052 * Represent the given key and value as an HTML attribute. 3053 * @function HtmlTag#toAttribute 3054 * @protected 3055 * @param {string} key - attribute name 3056 * @param {*|boolean} value - the value of the attribute. If the value is boolean `true`, return the key only. 3057 * @returns {string} the attribute 3058 * 3059 */ 3060 3061 toAttribute = function(key, value) { 3062 if (!value) { 3063 return void 0; 3064 } else if (value === true) { 3065 return key; 3066 } else { 3067 return key + "=\"" + value + "\""; 3068 } 3069 }; 3070 3071 3072 /** 3073 * combine key and value from the `attr` to generate an HTML tag attributes string. 3074 * `Transformation::toHtmlTagOptions` is used to filter out transformation and configuration keys. 3075 * @protected 3076 * @param {Object} attrs 3077 * @return {string} the attributes in the format `'key1="value1" key2="value2"'` 3078 * @ignore 3079 */ 3080 3081 HtmlTag.prototype.htmlAttrs = function(attrs) { 3082 var key, pairs, value; 3083 return pairs = ((function() { 3084 var results; 3085 results = []; 3086 for (key in attrs) { 3087 value = attrs[key]; 3088 if (value) { 3089 results.push(toAttribute(key, value)); 3090 } 3091 } 3092 return results; 3093 })()).sort().join(' '); 3094 }; 3095 3096 3097 /** 3098 * Get all options related to this tag. 3099 * @function HtmlTag#getOptions 3100 * @returns {Object} the options 3101 * 3102 */ 3103 3104 HtmlTag.prototype.getOptions = function() { 3105 return this.transformation().toOptions(); 3106 }; 3107 3108 3109 /** 3110 * Get the value of option `name` 3111 * @function HtmlTag#getOption 3112 * @param {string} name - the name of the option 3113 * @returns {*} Returns the value of the option 3114 * 3115 */ 3116 3117 HtmlTag.prototype.getOption = function(name) { 3118 return this.transformation().getValue(name); 3119 }; 3120 3121 3122 /** 3123 * Get the attributes of the tag. 3124 * @function HtmlTag#attributes 3125 * @returns {Object} attributes 3126 */ 3127 3128 HtmlTag.prototype.attributes = function() { 3129 return this.transformation().toHtmlAttributes(); 3130 }; 3131 3132 3133 /** 3134 * Set a tag attribute named `name` to `value` 3135 * @function HtmlTag#setAttr 3136 * @param {string} name - the name of the attribute 3137 * @param {string} value - the value of the attribute 3138 */ 3139 3140 HtmlTag.prototype.setAttr = function(name, value) { 3141 this.transformation().set("html_" + name, value); 3142 return this; 3143 }; 3144 3145 3146 /** 3147 * Get the value of the tag attribute `name` 3148 * @function HtmlTag#getAttr 3149 * @param {string} name - the name of the attribute 3150 * @returns {*} 3151 */ 3152 3153 HtmlTag.prototype.getAttr = function(name) { 3154 return this.attributes()["html_" + name] || this.attributes()[name]; 3155 }; 3156 3157 3158 /** 3159 * Remove the tag attributed named `name` 3160 * @function HtmlTag#removeAttr 3161 * @param {string} name - the name of the attribute 3162 * @returns {*} 3163 */ 3164 3165 HtmlTag.prototype.removeAttr = function(name) { 3166 var ref; 3167 return (ref = this.transformation().remove("html_" + name)) != null ? ref : this.transformation().remove(name); 3168 }; 3169 3170 3171 /** 3172 * @function HtmlTag#content 3173 * @protected 3174 * @ignore 3175 */ 3176 3177 HtmlTag.prototype.content = function() { 3178 return ""; 3179 }; 3180 3181 3182 /** 3183 * @function HtmlTag#openTag 3184 * @protected 3185 * @ignore 3186 */ 3187 3188 HtmlTag.prototype.openTag = function() { 3189 return "<" + this.name + " " + (this.htmlAttrs(this.attributes())) + ">"; 3190 }; 3191 3192 3193 /** 3194 * @function HtmlTag#closeTag 3195 * @protected 3196 * @ignore 3197 */ 3198 3199 HtmlTag.prototype.closeTag = function() { 3200 return "</" + this.name + ">"; 3201 }; 3202 3203 3204 /** 3205 * Generates an HTML representation of the tag. 3206 * @function HtmlTag#toHtml 3207 * @returns {string} Returns HTML in string format 3208 */ 3209 3210 HtmlTag.prototype.toHtml = function() { 3211 return this.openTag() + this.content() + this.closeTag(); 3212 }; 3213 3214 3215 /** 3216 * Creates a DOM object representing the tag. 3217 * @function HtmlTag#toDOM 3218 * @returns {Element} 3219 */ 3220 3221 HtmlTag.prototype.toDOM = function() { 3222 var element, name, ref, value; 3223 if (!Util.isFunction(typeof document !== "undefined" && document !== null ? document.createElement : void 0)) { 3224 throw "Can't create DOM if document is not present!"; 3225 } 3226 element = document.createElement(this.name); 3227 ref = this.attributes(); 3228 for (name in ref) {
3229 value = ref[name]; 3230 element[name] = value; 3231 } 3232 return element; 3233 }; 3234 3235 HtmlTag.isResponsive = function(tag, responsiveClass) { 3236 var dataSrc; 3237 dataSrc = Util.getData(tag, 'src-cache') || Util.getData(tag, 'src'); 3238 return Util.hasClass(tag, responsiveClass) && /\bw_auto\b/.exec(dataSrc); 3239 }; 3240 3241 return HtmlTag; 3242 3243 })(); 3244 3245 /** 3246 * Image Tag 3247 * Depends on 'tags/htmltag', 'cloudinary' 3248 */ 3249 ImageTag = (function(superClass) { 3250 extend(ImageTag, superClass); 3251 3252 3253 /** 3254 * Creates an HTML (DOM) Image tag using Cloudinary as the source. 3255 * @constructor ImageTag 3256 * @extends HtmlTag 3257 * @param {string} [publicId] 3258 * @param {Object} [options] 3259 */ 3260 3261 function ImageTag(publicId, options) { 3262 if (options == null) { 3263 options = {}; 3264 } 3265 ImageTag.__super__.constructor.call(this, "img", publicId, options); 3266 } 3267 3268 3269 /** @override */ 3270 3271 ImageTag.prototype.closeTag = function() { 3272 return ""; 3273 }; 3274 3275 3276 /** @override */ 3277 3278 ImageTag.prototype.attributes = function() { 3279 var attr, options, srcAttribute; 3280 attr = ImageTag.__super__.attributes.call(this) || []; 3281 options = this.getOptions(); 3282 srcAttribute = options.responsive && !options.client_hints ? 'data-src' : 'src'; 3283 if (attr[srcAttribute] == null) { 3284 attr[srcAttribute] = new Cloudinary(this.getOptions()).url(this.publicId); 3285 } 3286 return attr; 3287 }; 3288 3289 return ImageTag; 3290 3291 })(HtmlTag); 3292 3293 /** 3294 * Video Tag 3295 * Depends on 'tags/htmltag', 'util', 'cloudinary' 3296 */ 3297 VideoTag = (function(superClass) { 3298 var DEFAULT_POSTER_OPTIONS, DEFAULT_VIDEO_SOURCE_TYPES, VIDEO_TAG_PARAMS; 3299 3300 extend(VideoTag, superClass); 3301 3302 VIDEO_TAG_PARAMS = ['source_types', 'source_transformation', 'fallback_content', 'poster']; 3303 3304 DEFAULT_VIDEO_SOURCE_TYPES = ['webm', 'mp4', 'ogv']; 3305 3306 DEFAULT_POSTER_OPTIONS = { 3307 format: 'jpg', 3308 resource_type: 'video' 3309 }; 3310 3311 3312 /** 3313 * Creates an HTML (DOM) Video tag using Cloudinary as the source. 3314 * @constructor VideoTag 3315 * @extends HtmlTag 3316 * @param {string} [publicId] 3317 * @param {Object} [options] 3318 */ 3319 3320 function VideoTag(publicId, options) { 3321 if (options == null) { 3322 options = {}; 3323 } 3324 options = Util.defaults({}, options, Cloudinary.DEFAULT_VIDEO_PARAMS); 3325 VideoTag.__super__.constructor.call(this, "video", publicId.replace(/\.(mp4|ogv|webm)$/, ''), options); 3326 } 3327 3328 3329 /** 3330 * Set the transformation to apply on each source 3331 * @function VideoTag#setSourceTransformation 3332 * @param {Object} an object with pairs of source type and source transformation 3333 * @returns {VideoTag} Returns this instance for chaining purposes. 3334 */ 3335 3336 VideoTag.prototype.setSourceTransformation = function(value) { 3337 this.transformation().sourceTransformation(value); 3338 return this; 3339 }; 3340 3341 3342 /** 3343 * Set the source types to include in the video tag 3344 * @function VideoTag#setSourceTypes 3345 * @param {Array<string>} an array of source types 3346 * @returns {VideoTag} Returns this instance for chaining purposes. 3347 */ 3348 3349 VideoTag.prototype.setSourceTypes = function(value) { 3350 this.transformation().sourceTypes(value); 3351 return this; 3352 }; 3353 3354 3355 /** 3356 * Set the poster to be used in the video tag 3357 * @function VideoTag#setPoster 3358 * @param {string|Object} value 3359 * - string: a URL to use for the poster 3360 * - Object: transformation parameters to apply to the poster. May optionally include a public_id to use instead of the video public_id. 3361 * @returns {VideoTag} Returns this instance for chaining purposes. 3362 */ 3363 3364 VideoTag.prototype.setPoster = function(value) { 3365 this.transformation().poster(value); 3366 return this; 3367 }; 3368 3369 3370 /** 3371 * Set the content to use as fallback in the video tag 3372 * @function VideoTag#setFallbackContent 3373 * @param {string} value - the content to use, in HTML format 3374 * @returns {VideoTag} Returns this instance for chaining purposes. 3375 */ 3376 3377 VideoTag.prototype.setFallbackContent = function(value) { 3378 this.transformation().fallbackContent(value); 3379 return this; 3380 }; 3381 3382 VideoTag.prototype.content = function() { 3383 var cld, fallback, innerTags, mimeType, sourceTransformation, sourceTypes, src, srcType, transformation, videoType; 3384 sourceTypes = this.transformation().getValue('source_types'); 3385 sourceTransformation = this.transformation().getValue('source_transformation'); 3386 fallback = this.transformation().getValue('fallback_content'); 3387 if (Util.isArray(sourceTypes)) { 3388 cld = new Cloudinary(this.getOptions()); 3389 innerTags = (function() { 3390 var j, len, results; 3391 results = []; 3392 for (j = 0, len = sourceTypes.length; j < len; j++) { 3393 srcType = sourceTypes[j]; 3394 transformation = sourceTransformation[srcType] || {}; 3395 src = cld.url("" + this.publicId, Util.defaults({}, transformation, { 3396 resource_type: 'video', 3397 format: srcType 3398 })); 3399 videoType = srcType === 'ogv' ? 'ogg' : srcType; 3400 mimeType = 'video/' + videoType; 3401 results.push("<source " + (this.htmlAttrs({ 3402 src: src, 3403 type: mimeType 3404 })) + ">"); 3405 } 3406 return results; 3407 }).call(this); 3408 } else { 3409 innerTags = []; 3410 } 3411 return innerTags.join('') + fallback; 3412 }; 3413 3414 VideoTag.prototype.attributes = function() { 3415 var a, attr, j, len, poster, ref, ref1, sourceTypes; 3416 sourceTypes = this.getOption('source_types'); 3417 poster = (ref = this.getOption('poster')) != null ? ref : {}; 3418 if (Util.isPlainObject(poster)) { 3419 defaults = poster.public_id != null ? Cloudinary.DEFAULT_IMAGE_PARAMS : DEFAULT_POSTER_OPTIONS; 3420 poster = new Cloudinary(this.getOptions()).url((ref1 = poster.public_id) != null ? ref1 : this.publicId, Util.defaults({}, poster, defaults)); 3421 } 3422 attr = VideoTag.__super__.attributes.call(this) || []; 3423 for (j = 0, len = attr.length; j < len; j++) { 3424 a = attr[j]; 3425 if (!Util.contains(VIDEO_TAG_PARAMS)) { 3426 attr = a; 3427 } 3428 } 3429 if (!Util.isArray(sourceTypes)) { 3430 attr["src"] = new Cloudinary(this.getOptions()).url(this.publicId, { 3431 resource_type: 'video', 3432 format: sourceTypes 3433 }); 3434 } 3435 if (poster != null) { 3436 attr["poster"] = poster; 3437 } 3438 return attr; 3439 }; 3440 3441 return VideoTag; 3442 3443 })(HtmlTag); 3444 3445 /** 3446 * Image Tag
3447 * Depends on 'tags/htmltag', 'cloudinary' 3448 */ 3449 ClientHintsMetaTag = (function(superClass) { 3450 extend(ClientHintsMetaTag, superClass); 3451 3452 3453 /** 3454 * Creates an HTML (DOM) Meta tag that enables client-hints. 3455 * @constructor ClientHintsMetaTag 3456 * @extends HtmlTag 3457 */ 3458 3459 function ClientHintsMetaTag(options) { 3460 ClientHintsMetaTag.__super__.constructor.call(this, 'meta', void 0, Util.assign({ 3461 "http-equiv": "Accept-CH", 3462 content: "DPR, Viewport-Width, Width" 3463 }, options)); 3464 } 3465 3466 3467 /** @override */ 3468 3469 ClientHintsMetaTag.prototype.closeTag = function() { 3470 return ""; 3471 }; 3472 3473 return ClientHintsMetaTag; 3474 3475 })(HtmlTag); 3476 Cloudinary = (function() { 3477 var AKAMAI_SHARED_CDN, CF_SHARED_CDN, DEFAULT_POSTER_OPTIONS, DEFAULT_VIDEO_SOURCE_TYPES, OLD_AKAMAI_SHARED_CDN, SEO_TYPES, SHARED_CDN, VERSION, absolutize, applyBreakpoints, cdnSubdomainNumber, closestAbove, cloudinaryUrlPrefix, defaultBreakpoints, finalizeResourceType, findContainerWidth, maxWidth, updateDpr; 3478 3479 VERSION = "2.5.0"; 3480 3481 CF_SHARED_CDN = "d3jpl91pxevbkh.cloudfront.net"; 3482 3483 OLD_AKAMAI_SHARED_CDN = "cloudinary-a.akamaihd.net"; 3484 3485 AKAMAI_SHARED_CDN = "res.cloudinary.com"; 3486 3487 SHARED_CDN = AKAMAI_SHARED_CDN; 3488 3489 DEFAULT_POSTER_OPTIONS = { 3490 format: 'jpg', 3491 resource_type: 'video' 3492 }; 3493 3494 DEFAULT_VIDEO_SOURCE_TYPES = ['webm', 'mp4', 'ogv']; 3495 3496 SEO_TYPES = { 3497 "image/upload": "images", 3498 "image/private": "private_images", 3499 "image/authenticated": "authenticated_images", 3500 "raw/upload": "files", 3501 "video/upload": "videos" 3502 }; 3503 3504 3505 /** 3506 * @const {Object} Cloudinary.DEFAULT_IMAGE_PARAMS 3507 * Defaults values for image parameters. 3508 * 3509 * (Previously defined using option_consume() ) 3510 */ 3511 3512 Cloudinary.DEFAULT_IMAGE_PARAMS = { 3513 resource_type: "image", 3514 transformation: [], 3515 type: 'upload' 3516 }; 3517 3518 3519 /** 3520 * Defaults values for video parameters. 3521 * @const {Object} Cloudinary.DEFAULT_VIDEO_PARAMS 3522 * (Previously defined using option_consume() ) 3523 */ 3524 3525 Cloudinary.DEFAULT_VIDEO_PARAMS = { 3526 fallback_content: '', 3527 resource_type: "video", 3528 source_transformation: {}, 3529 source_types: DEFAULT_VIDEO_SOURCE_TYPES, 3530 transformation: [], 3531 type: 'upload' 3532 }; 3533 3534 3535 /** 3536 * Main Cloudinary class 3537 * @class Cloudinary 3538 * @param {Object} options - options to configure Cloudinary 3539 * @see Configuration for more details 3540 * @example 3541 * var cl = new cloudinary.Cloudinary( { cloud_name: "mycloud"}); 3542 * var imgTag = cl.image("myPicID"); 3543 */ 3544 3545 function Cloudinary(options) { 3546 var configuration; 3547 this.devicePixelRatioCache = {}; 3548 this.responsiveConfig = {}; 3549 this.responsiveResizeInitialized = false; 3550 configuration = new Configuration(options); 3551 this.config = function(newConfig, newValue) { 3552 return configuration.config(newConfig, newValue); 3553 }; 3554 3555 /** 3556 * Use \<meta\> tags in the document to configure this Cloudinary instance. 3557 * @return {Cloudinary} this for chaining 3558 */ 3559 this.fromDocument = function() { 3560 configuration.fromDocument(); 3561 return this; 3562 }; 3563 3564 /** 3565 * Use environment variables to configure this Cloudinary instance. 3566 * @return {Cloudinary} this for chaining 3567 */ 3568 this.fromEnvironment = function() { 3569 configuration.fromEnvironment(); 3570 return this; 3571 }; 3572 3573 /** 3574 * Initialize configuration. 3575 * @function Cloudinary#init 3576 * @see Configuration#init 3577 * @return {Cloudinary} this for chaining 3578 */ 3579 this.init = function() { 3580 configuration.init(); 3581 return this; 3582 }; 3583 } 3584 3585 3586 /** 3587 * Convenience constructor 3588 * @param {Object} options 3589 * @return {Cloudinary} 3590 * @example cl = cloudinary.Cloudinary.new( { cloud_name: "mycloud"}) 3591 */ 3592 3593 Cloudinary["new"] = function(options) { 3594 return new this(options); 3595 }; 3596 3597 3598 /** 3599 * Return the resource type and action type based on the given configuration 3600 * @function Cloudinary#finalizeResourceType 3601 * @param {Object|string} resourceType 3602 * @param {string} [type='upload'] 3603 * @param {string} [urlSuffix] 3604 * @param {boolean} [useRootPath] 3605 * @param {boolean} [shorten] 3606 * @returns {string} resource_type/type
3607 * @ignore 3608 */ 3609 3610 finalizeResourceType = function(resourceType, type, urlSuffix, useRootPath, shorten) { 3611 var key, options; 3612 if (resourceType == null) { 3613 resourceType = "image"; 3614 } 3615 if (type == null) { 3616 type = "upload"; 3617 } 3618 if (Util.isPlainObject(resourceType)) { 3619 options = resourceType; 3620 resourceType = options.resource_type; 3621 type = options.type; 3622 urlSuffix = options.url_suffix; 3623 useRootPath = options.use_root_path; 3624 shorten = options.shorten; 3625 } 3626 if (type == null) { 3627 type = 'upload'; 3628 } 3629 if (urlSuffix != null) { 3630 resourceType = SEO_TYPES[resourceType + "/" + type]; 3631 type = null; 3632 if (resourceType == null) { 3633 throw new Error("URL Suffix only supported for " + (((function() { 3634 var results; 3635 results = []; 3636 for (key in SEO_TYPES) { 3637 results.push(key); 3638 } 3639 return results; 3640 })()).join(', '))); 3641 } 3642 } 3643 if (useRootPath) { 3644 if (resourceType === 'image' && type === 'upload' || resourceType === "images") { 3645 resourceType = null; 3646 type = null; 3647 } else { 3648 throw new Error("Root path only supported for image/upload"); 3649 } 3650 } 3651 if (shorten && resourceType === 'image' && type === 'upload') { 3652 resourceType = 'iu'; 3653 type = null; 3654 } 3655 return [resourceType, type].join("/"); 3656 }; 3657 3658 absolutize = function(url) { 3659 var prefix; 3660 if (!url.match(/^https?:\//)) { 3661 prefix = document.location.protocol + '//' + document.location.host; 3662 if (url[0] === '?') { 3663 prefix += document.location.pathname; 3664 } else if (url[0] !== '/') { 3665 prefix += document.location.pathname.replace(/\/[^\/]*$/, '/'); 3666 } 3667 url = prefix + url; 3668 } 3669 return url; 3670 }; 3671 3672 3673 /** 3674 * Generate an resource URL. 3675 * @function Cloudinary#url 3676 * @param {string} publicId - the public ID of the resource 3677 * @param {Object} [options] - options for the tag and transformations, possible values include all {@link Transformation} parameters 3678 * and {@link Configuration} parameters 3679 * @param {string} [options.type='upload'] - the classification of the resource 3680 * @param {Object} [options.resource_type='image'] - the type of the resource 3681 * @return {string} The resource URL 3682 */ 3683 3684 Cloudinary.prototype.url = function(publicId, options) { 3685 var error, error1, prefix, ref, resourceTypeAndType, transformation, transformationString, url, version; 3686 if (options == null) { 3687 options = {}; 3688 } 3689 if (!publicId) { 3690 return publicId; 3691 } 3692 if (options instanceof Transformation) { 3693 options = options.toOptions(); 3694 } 3695 options = Util.defaults({}, options, this.config(), Cloudinary.DEFAULT_IMAGE_PARAMS); 3696 if (options.type === 'fetch') { 3697 options.fetch_format = options.fetch_format || options.format; 3698 publicId = absolutize(publicId); 3699 } 3700 transformation = new Transformation(options); 3701 transformationString = transformation.serialize(); 3702 if (!options.cloud_name) { 3703 throw 'Unknown cloud_name'; 3704 } 3705 if (publicId.search('/') >= 0 && !publicId.match(/^v[0-9]+/) && !publicId.match(/^https?:\//) && !((ref = options.version) != null ? ref.toString() : void 0)) { 3706 options.version = 1; 3707 } 3708 if (publicId.match(/^https?:/)) { 3709 if (options.type === 'upload' || options.type === 'asset') { 3710 url = publicId; 3711 } else { 3712 publicId = encodeURIComponent(publicId).replace(/%3A/g, ':').replace(/%2F/g, '/'); 3713 } 3714 } else { 3715 try { 3716 publicId = decodeURIComponent(publicId); 3717 } catch (error1) { 3718 error = error1; 3719 } 3720 publicId = encodeURIComponent(publicId).replace(/%3A/g, ':').replace(/%2F/g, '/'); 3721 if (options.url_suffix) { 3722 if (options.url_suffix.match(/[\.\/]/)) { 3723 throw 'url_suffix should not include . or /'; 3724 } 3725 publicId = publicId + '/' + options.url_suffix; 3726 } 3727 if (options.format) { 3728 if (!options.trust_public_id) { 3729 publicId = publicId.replace(/\.(jpg|png|gif|webp)$/, ''); 3730 } 3731 publicId = publicId + '.' + options.format; 3732 } 3733 } 3734 prefix = cloudinaryUrlPrefix(publicId, options); 3735 resourceTypeAndType = finalizeResourceType(options.resource_type, options.type, options.url_suffix, options.use_root_path, options.shorten); 3736 version = options.version ? 'v' + options.version : ''; 3737 return url || Util.compact([prefix, resourceTypeAndType, transformationString, version, publicId]).join('/').replace(/([^:])\/+/g, '$1/'); 3738 }; 3739 3740 3741 /** 3742 * Generate an video resource URL. 3743 * @function Cloudinary#video_url 3744 * @param {string} publicId - the public ID of the resource 3745 * @param {Object} [options] - options for the tag and transformations, possible values include all {@link Transformation} parameters 3746 * and {@link Configuration} parameters 3747 * @param {string} [options.type='upload'] - the classification of the resource 3748 * @return {string} The video URL 3749 */ 3750 3751 Cloudinary.prototype.video_url = function(publicId, options) {
3752 options = Util.assign({ 3753 resource_type: 'video' 3754 }, options); 3755 return this.url(publicId, options); 3756 }; 3757 3758 3759 /** 3760 * Generate an video thumbnail URL. 3761 * @function Cloudinary#video_thumbnail_url 3762 * @param {string} publicId - the public ID of the resource 3763 * @param {Object} [options] - options for the tag and transformations, possible values include all {@link Transformation} parameters 3764 * and {@link Configuration} parameters 3765 * @param {string} [options.type='upload'] - the classification of the resource 3766 * @return {string} The video thumbnail URL 3767 */ 3768 3769 Cloudinary.prototype.video_thumbnail_url = function(publicId, options) { 3770 options = Util.assign({}, DEFAULT_POSTER_OPTIONS, options); 3771 return this.url(publicId, options); 3772 }; 3773 3774 3775 /** 3776 * Generate a string representation of the provided transformation options. 3777 * @function Cloudinary#transformation_string 3778 * @param {Object} options - the transformation options 3779 * @returns {string} The transformation string 3780 */ 3781 3782 Cloudinary.prototype.transformation_string = function(options) { 3783 return new Transformation(options).serialize(); 3784 }; 3785 3786 3787 /** 3788 * Generate an image tag. 3789 * @function Cloudinary#image 3790 * @param {string} publicId - the public ID of the image 3791 * @param {Object} [options] - options for the tag and transformations 3792 * @return {HTMLImageElement} an image tag element 3793 */ 3794 3795 Cloudinary.prototype.image = function(publicId, options) { 3796 var client_hints, img, ref, ref1; 3797 if (options == null) { 3798 options = {}; 3799 } 3800 img = this.imageTag(publicId, options); 3801 client_hints = (ref = (ref1 = options.client_hints) != null ? ref1 : this.config('client_hints')) != null ? ref : false; 3802 if (!((options.src != null) || client_hints)) { 3803 img.setAttr("src", ''); 3804 } 3805 img = img.toDOM(); 3806 if (!client_hints) { 3807 Util.setData(img, 'src-cache', this.url(publicId, options)); 3808 this.cloudinary_update(img, options); 3809 } 3810 return img; 3811 }; 3812 3813 3814 /** 3815 * Creates a new ImageTag instance, configured using this own's configuration. 3816 * @function Cloudinary#imageTag 3817 * @param {string} publicId - the public ID of the resource 3818 * @param {Object} options - additional options to pass to the new ImageTag instance 3819 * @return {ImageTag} An ImageTag that is attached (chained) to this Cloudinary instance 3820 */ 3821 3822 Cloudinary.prototype.imageTag = function(publicId, options) { 3823 var tag; 3824 tag = new ImageTag(publicId, this.config()); 3825 tag.transformation().fromOptions(options); 3826 return tag; 3827 }; 3828 3829 3830 /** 3831 * Generate an image tag for the video thumbnail. 3832 * @function Cloudinary#video_thumbnail 3833 * @param {string} publicId - the public ID of the video 3834 * @param {Object} [options] - options for the tag and transformations 3835 * @return {HTMLImageElement} An image tag element 3836 */ 3837 3838 Cloudinary.prototype.video_thumbnail = function(publicId, options) { 3839 return this.image(publicId, Util.merge({}, DEFAULT_POSTER_OPTIONS, options)); 3840 }; 3841 3842 3843 /** 3844 * @function Cloudinary#facebook_profile_image 3845 * @param {string} publicId - the public ID of the image 3846 * @param {Object} [options] - options for the tag and transformations 3847 * @return {HTMLImageElement} an image tag element 3848 */ 3849 3850 Cloudinary.prototype.facebook_profile_image = function(publicId, options) { 3851 return this.image(publicId, Util.assign({ 3852 type: 'facebook' 3853 }, options)); 3854 }; 3855 3856 3857 /** 3858 * @function Cloudinary#twitter_profile_image 3859 * @param {string} publicId - the public ID of the image 3860 * @param {Object} [options] - options for the tag and transformations 3861 * @return {HTMLImageElement} an image tag element 3862 */ 3863 3864 Cloudinary.prototype.twitter_profile_image = function(publicId, options) { 3865 return this.image(publicId, Util.assign({ 3866 type: 'twitter' 3867 }, options)); 3868 }; 3869 3870 3871 /** 3872 * @function Cloudinary#twitter_name_profile_image 3873 * @param {string} publicId - the public ID of the image 3874 * @param {Object} [options] - options for the tag and transformations 3875 * @return {HTMLImageElement} an image tag element 3876 */ 3877 3878 Cloudinary.prototype.twitter_name_profile_image = function(publicId, options) { 3879 return this.image(publicId, Util.assign({ 3880 type: 'twitter_name' 3881 }, options)); 3882 }; 3883 3884 3885 /** 3886 * @function Cloudinary#gravatar_image 3887 * @param {string} publicId - the public ID of the image 3888 * @param {Object} [options] - options for the tag and transformations 3889 * @return {HTMLImageElement} an image tag element 3890 */ 3891 3892 Cloudinary.prototype.gravatar_image = function(publicId, options) { 3893 return this.image(publicId, Util.assign({ 3894 type: 'gravatar' 3895 }, options)); 3896 }; 3897 3898 3899 /** 3900 * @function Cloudinary#fetch_image 3901 * @param {string} publicId - the public ID of the image 3902 * @param {Object} [options] - options for the tag and transformations 3903 * @return {HTMLImageElement} an image tag element 3904 */ 3905 3906 Cloudinary.prototype.fetch_image = function(publicId, options) { 3907 return this.image(publicId, Util.assign({ 3908 type: 'fetch' 3909 }, options)); 3910 }; 3911 3912 3913 /** 3914 * @function Cloudinary#video 3915 * @param {string} publicId - the public ID of the image 3916 * @param {Object} [options] - options for the tag and transformations 3917 * @return {HTMLImageElement} an image tag element 3918 */ 3919 3920 Cloudinary.prototype.video = function(publicId, options) { 3921 if (options == null) { 3922 options = {}; 3923 } 3924 return this.videoTag(publicId, options).toHtml(); 3925 }; 3926 3927 3928 /** 3929 * Creates a new VideoTag instance, configured using this own's configuration. 3930 * @function Cloudinary#videoTag 3931 * @param {string} publicId - the public ID of the resource 3932 * @param {Object} options - additional options to pass to the new VideoTag instance 3933 * @return {VideoTag} A VideoTag that is attached (chained) to this Cloudinary instance 3934 */ 3935 3936 Cloudinary.prototype.videoTag = function(publicId, options) {
3937 options = Util.defaults({}, options, this.config()); 3938 return new VideoTag(publicId, options); 3939 }; 3940 3941 3942 /** 3943 * Generate the URL of the sprite image 3944 * @function Cloudinary#sprite_css 3945 * @param {string} publicId - the public ID of the resource 3946 * @param {Object} [options] - options for the tag and transformations 3947 * @see {@link http://cloudinary.com/documentation/sprite_generation Sprite generation} 3948 */ 3949 3950 Cloudinary.prototype.sprite_css = function(publicId, options) { 3951 options = Util.assign({ 3952 type: 'sprite' 3953 }, options); 3954 if (!publicId.match(/.css$/)) { 3955 options.format = 'css'; 3956 } 3957 return this.url(publicId, options); 3958 }; 3959 3960 3961 /** 3962 * Initialize the responsive behaviour.<br> 3963 * Calls {@link Cloudinary#cloudinary_update} to modify image tags. 3964 * @function Cloudinary#responsive 3965 * @param {Object} options 3966 * @param {String} [options.responsive_class='cld-responsive'] - provide an alternative class used to locate img tags 3967 * @param {number} [options.responsive_debounce=100] - the debounce interval in milliseconds. 3968 * @param {boolean} [bootstrap=true] if true processes the img tags by calling cloudinary_update. When false the tags will be processed only after a resize event. 3969 * @see {@link Cloudinary#cloudinary_update} for additional configuration parameters 3970 */ 3971 3972 Cloudinary.prototype.responsive = function(options, bootstrap) { 3973 var ref, ref1, ref2, responsiveClass, responsiveResize, timeout; 3974 if (bootstrap == null) { 3975 bootstrap = true; 3976 } 3977 this.responsiveConfig = Util.merge(this.responsiveConfig || {}, options); 3978 responsiveClass = (ref = this.responsiveConfig['responsive_class']) != null ? ref : this.config('responsive_class'); 3979 if (bootstrap) { 3980 this.cloudinary_update("img." + responsiveClass + ", img.cld-hidpi", this.responsiveConfig); 3981 } 3982 responsiveResize = (ref1 = (ref2 = this.responsiveConfig['responsive_resize']) != null ? ref2 : this.config('responsive_resize')) != null ? ref1 : true; 3983 if (responsiveResize && !this.responsiveResizeInitialized) { 3984 this.responsiveConfig.resizing = this.responsiveResizeInitialized = true; 3985 timeout = null; 3986 return window.addEventListener('resize', (function(_this) { 3987 return function() { 3988 var debounce, ref3, ref4, reset, run, wait, waitFunc; 3989 debounce = (ref3 = (ref4 = _this.responsiveConfig['responsive_debounce']) != null ? ref4 : _this.config('responsive_debounce')) != null ? ref3 : 100; 3990 reset = function() { 3991 if (timeout) { 3992 clearTimeout(timeout); 3993 return timeout = null; 3994 } 3995 }; 3996 run = function() { 3997 return _this.cloudinary_update("img." + responsiveClass, _this.responsiveConfig); 3998 }; 3999 waitFunc = function() { 4000 reset(); 4001 return run(); 4002 }; 4003 wait = function() { 4004 reset(); 4005 return timeout = setTimeout(waitFunc, debounce); 4006 }; 4007 if (debounce) { 4008 return wait(); 4009 } else { 4010 return run(); 4011 } 4012 }; 4013 })(this)); 4014 } 4015 }; 4016 4017 4018 /** 4019 * @function Cloudinary#calc_breakpoint 4020 * @private 4021 * @ignore 4022 */ 4023 4024 Cloudinary.prototype.calc_breakpoint = function(element, width, steps) { 4025 var breakpoints, point; 4026 breakpoints = Util.getData(element, 'breakpoints') || Util.getData(element, 'stoppoints') || this.config('breakpoints') || this.config('stoppoints') || defaultBreakpoints; 4027 if (Util.isFunction(breakpoints)) { 4028 return breakpoints(width, steps); 4029 } else { 4030 if (Util.isString(breakpoints)) { 4031 breakpoints = ((function() { 4032 var j, len, ref, results; 4033 ref = breakpoints.split(','); 4034 results = []; 4035 for (j = 0, len = ref.length; j < len; j++) {
4036 point = ref[j]; 4037 results.push(parseInt(point)); 4038 } 4039 return results; 4040 })()).sort(function(a, b) { 4041 return a - b; 4042 }); 4043 } 4044 return closestAbove(breakpoints, width); 4045 } 4046 }; 4047 4048 4049 /** 4050 * @function Cloudinary#calc_stoppoint 4051 * @deprecated Use {@link calc_breakpoint} instead. 4052 * @private 4053 * @ignore 4054 */ 4055 4056 Cloudinary.prototype.calc_stoppoint = Cloudinary.prototype.calc_breakpoint; 4057 4058 4059 /** 4060 * @function Cloudinary#device_pixel_ratio 4061 * @private 4062 */ 4063 4064 Cloudinary.prototype.device_pixel_ratio = function(roundDpr) { 4065 var dpr, dprString; 4066 if (roundDpr == null) { 4067 roundDpr = true; 4068 } 4069 dpr = (typeof window !== "undefined" && window !== null ? window.devicePixelRatio : void 0) || 1; 4070 if (roundDpr) { 4071 dpr = Math.ceil(dpr); 4072 } 4073 if (dpr <= 0 || dpr === NaN) { 4074 dpr = 1; 4075 } 4076 dprString = dpr.toString(); 4077 if (dprString.match(/^\d+$/)) { 4078 dprString += '.0'; 4079 } 4080 return dprString; 4081 }; 4082 4083 defaultBreakpoints = function(width, steps) { 4084 if (steps == null) { 4085 steps = 100; 4086 } 4087 return steps * Math.ceil(width / steps); 4088 }; 4089 4090 closestAbove = function(list, value) { 4091 var i; 4092 i = list.length - 2; 4093 while (i >= 0 && list[i] >= value) { 4094 i--; 4095 } 4096 return list[i + 1]; 4097 }; 4098 4099 cdnSubdomainNumber = function(publicId) { 4100 return crc32(publicId) % 5 + 1; 4101 }; 4102 4103 cloudinaryUrlPrefix = function(publicId, options) { 4104 var cdnPart, host, path, protocol, ref, subdomain; 4105 if (((ref = options.cloud_name) != null ? ref.indexOf("/") : void 0) === 0) { 4106 return '/res' + options.cloud_name; 4107 } 4108 protocol = "http://"; 4109 cdnPart = ""; 4110 subdomain = "res"; 4111 host = ".cloudinary.com"; 4112 path = "/" + options.cloud_name; 4113 if (options.protocol) { 4114 protocol = options.protocol + '//'; 4115 } 4116 if (options.private_cdn) { 4117 cdnPart = options.cloud_name + "-"; 4118 path = ""; 4119 } 4120 if (options.cdn_subdomain) { 4121 subdomain = "res-" + cdnSubdomainNumber(publicId); 4122 } 4123 if (options.secure) { 4124 protocol = "https://"; 4125 if (options.secure_cdn_subdomain === false) { 4126 subdomain = "res"; 4127 } 4128 if ((options.secure_distribution != null) && options.secure_distribution !== OLD_AKAMAI_SHARED_CDN && options.secure_distribution !== SHARED_CDN) { 4129 cdnPart = ""; 4130 subdomain = ""; 4131 host = options.secure_distribution; 4132 } 4133 } else if (options.cname) { 4134 protocol = "http://"; 4135 cdnPart = ""; 4136 subdomain = options.cdn_subdomain ? 'a' + ((crc32(publicId) % 5) + 1) + '.' : ''; 4137 host = options.cname; 4138 } 4139 return [protocol, cdnPart, subdomain, host, path].join(""); 4140 }; 4141 4142 4143 /** 4144 * Finds all `img` tags under each node and sets it up to provide the image through Cloudinary 4145 * @param {Element[]} nodes the parent nodes to search for img under 4146 * @param {Object} [options={}] options and transformations params 4147 * @function Cloudinary#processImageTags 4148 */ 4149 4150 Cloudinary.prototype.processImageTags = function(nodes, options) { 4151 var images, imgOptions, node, publicId, url; 4152 if (options == null) { 4153 options = {}; 4154 } 4155 if (Util.isEmpty(nodes)) { 4156 return this; 4157 } 4158 options = Util.defaults({}, options, this.config()); 4159 images = (function() { 4160 var j, len, ref, results; 4161 results = []; 4162 for (j = 0, len = nodes.length; j < len; j++) { 4163 node = nodes[j]; 4164 if (!(((ref = node.tagName) != null ? ref.toUpperCase() : void 0) === 'IMG')) { 4165 continue; 4166 } 4167 imgOptions = Util.assign({ 4168 width: node.getAttribute('width'), 4169 height: node.getAttribute('height'), 4170 src: node.getAttribute('src') 4171 }, options); 4172 publicId = imgOptions['source'] || imgOptions['src']; 4173 delete imgOptions['source']; 4174 delete imgOptions['src']; 4175 url = this.url(publicId, imgOptions); 4176 imgOptions = new Transformation(imgOptions).toHtmlAttributes(); 4177 Util.setData(node, 'src-cache', url); 4178 node.setAttribute('width', imgOptions.width); 4179 node.setAttribute('height', imgOptions.height); 4180 results.push(node); 4181 } 4182 return results; 4183 }).call(this); 4184 this.cloudinary_update(images, options); 4185 return this; 4186 }; 4187 4188 applyBreakpoints = function(tag, width, steps, options) { 4189 var ref, ref1, ref2, responsive_use_breakpoints; 4190 responsive_use_breakpoints = (ref = (ref1 = (ref2 = options['responsive_use_breakpoints']) != null ? ref2 : options['responsive_use_stoppoints']) != null ? ref1 : this.config('responsive_use_breakpoints')) != null ? ref : this.config('responsive_use_stoppoints'); 4191 if ((!responsive_use_breakpoints) || (responsive_use_breakpoints === 'resize' && !
4191options.resizing)) { 4192 return width; 4193 } else { 4194 return this.calc_breakpoint(tag, width, steps); 4195 } 4196 }; 4197 4198 findContainerWidth = function(element) { 4199 var containerWidth, style; 4200 containerWidth = 0; 4201 while (((element = element != null ? element.parentNode : void 0) instanceof Element) && !containerWidth) { 4202 style = window.getComputedStyle(element); 4203 if (!/^inline/.test(style.display)) { 4204 containerWidth = Util.width(element); 4205 } 4206 } 4207 return containerWidth; 4208 }; 4209 4210 updateDpr = function(dataSrc, roundDpr) { 4211 return dataSrc.replace(/\bdpr_(1\.0|auto)\b/g, 'dpr_' + this.device_pixel_ratio(roundDpr)); 4212 }; 4213 4214 maxWidth = function(requiredWidth, tag) { 4215 var imageWidth; 4216 imageWidth = Util.getData(tag, 'width') || 0; 4217 if (requiredWidth > imageWidth) { 4218 imageWidth = requiredWidth; 4219 Util.setData(tag, 'width', requiredWidth); 4220 } 4221 return imageWidth; 4222 }; 4223 4224 4225 /** 4226 * Update hidpi (dpr_auto) and responsive (w_auto) fields according to the current container size and the device pixel ratio. 4227 * Only images marked with the cld-responsive class have w_auto updated. 4228 * @function Cloudinary#cloudinary_update 4229 * @param {(Array|string|NodeList)} elements - the elements to modify 4230 * @param {Object} options 4231 * @param {boolean|string} [options.responsive_use_breakpoints=true] 4232 * - when `true`, always use breakpoints for width 4233 * - when `"resize"` use exact width on first render and breakpoints on resize 4234 * - when `false` always use exact width 4235 * @param {boolean} [options.responsive] - if `true`, enable responsive on this element. Can be done by adding cld-responsive. 4236 * @param {boolean} [options.responsive_preserve_height] - if set to true, original css height is preserved. 4237 * Should only be used if the transformation supports different aspect ratios. 4238 */ 4239 4240 Cloudinary.prototype.cloudinary_update = function(elements, options) { 4241 var containerWidth, dataSrc, j, len, match, ref, ref1, ref2, ref3, ref4, ref5, requiredWidth, responsive, responsiveClass, roundDpr, setUrl, tag; 4242 if (options == null) { 4243 options = {}; 4244 } 4245 if (elements === null) { 4246 return this; 4247 } 4248 responsive = (ref = (ref1 = options.responsive) != null ? ref1 : this.config('responsive')) != null ? ref : false; 4249 elements = (function() { 4250 switch (false) { 4251 case !Util.isArray(elements): 4252 return elements; 4253 case elements.constructor.name !== "NodeList": 4254 return elements; 4255 case !Util.isString(elements): 4256 return document.querySelectorAll(elements); 4257 default: 4258 return [elements]; 4259 } 4260 })(); 4261 responsiveClass = (ref2 = (ref3 = this.responsiveConfig['responsive_class']) != null ? ref3 : options['responsive_class']) != null ? ref2 : this.config('responsive_class'); 4262 roundDpr = (ref4 = options['round_dpr']) != null ? ref4 : this.config('round_dpr'); 4263 for (j = 0, len = elements.length; j < len; j++) { 4264 tag = elements[j]; 4265 if (!((ref5 = tag.tagName) != null ? ref5.match(/img/i) : void 0)) { 4266 continue; 4267 } 4268 setUrl = true; 4269 if (responsive) { 4270 Util.addClass(tag, responsiveClass); 4271 } 4272 dataSrc = Util.getData(tag, 'src-cache') || Util.getData(tag, 'src'); 4273 if (!Util.isEmpty(dataSrc)) { 4274 dataSrc = updateDpr.call(this, dataSrc, roundDpr); 4275 if (HtmlTag.isResponsive(tag, responsiveClass)) { 4276 containerWidth = findContainerWidth(tag); 4277 if (containerWidth !== 0) { 4278 switch (false) { 4279 case !/w_auto:breakpoints/.test(dataSrc): 4280 requiredWidth = maxWidth(containerWidth, tag); 4281 dataSrc = dataSrc.replace(/w_auto:breakpoints([_0-9]*)(:[0-9]+)?/, "w_auto:breakpoints$1:" + requiredWidth); 4282 break; 4283 case !(match = /w_auto(:(\d+))?/.exec(dataSrc)): 4284 requiredWidth = applyBreakpoints.call(this, tag, containerWidth, match[2], options); 4285 requiredWidth = maxWidth(requiredWidth, tag); 4286 dataSrc = dataSrc.replace(/w_auto[^,\/]*/g, "w_" + requiredWidth); 4287 } 4288 Util.removeAttribute(tag, 'width'); 4289 if (!options.responsive_preserve_height) { 4290 Util.removeAttribute(tag, 'height'); 4291 } 4292 } else { 4293 setUrl = false; 4294 } 4295 } 4296 if (setUrl) { 4297 Util.setAttribute(tag, 'src', dataSrc); 4298 } 4299 } 4300 } 4301 return this; 4302 }; 4303 4304 4305 /** 4306 * Provide a transformation object, initialized with own's options, for chaining purposes. 4307 * @function Cloudinary#transformation 4308 * @param {Object} options 4309 * @return {Transformation} 4310 */ 4311 4312 Cloudinary.prototype.transformation = function(options) { 4313 return Transformation["new"](this.config()).fromOptions(options).setParent(this); 4314 }; 4315 4316 return Cloudinary; 4317 4318 })();
4319 4320 /** 4321 * Cloudinary jQuery plugin 4322 * Depends on 'jquery', 'util', 'transformation', 'cloudinary' 4323 */ 4324 CloudinaryJQuery = (function(superClass) { 4325 extend(CloudinaryJQuery, superClass); 4326 4327 4328 /** 4329 * Cloudinary class with jQuery support 4330 * @constructor CloudinaryJQuery 4331 * @extends Cloudinary 4332 */ 4333 4334 function CloudinaryJQuery(options) { 4335 CloudinaryJQuery.__super__.constructor.call(this, options); 4336 } 4337 4338 4339 /** 4340 * @override 4341 */ 4342 4343 CloudinaryJQuery.prototype.image = function(publicId, options) { 4344 var client_hints, img, ref, ref1; 4345 if (options == null) { 4346 options = {}; 4347 } 4348 img = this.imageTag(publicId, options); 4349 client_hints = (ref = (ref1 = options.client_hints) != null ? ref1 : this.config('client_hints')) != null ? ref : false; 4350 if (!((options.src != null) || client_hints)) { 4351 img.setAttr("src", ''); 4352 } 4353 img = jQuery(img.toHtml()); 4354 if (!client_hints) { 4355 img.data('src-cache', this.url(publicId, options)).cloudinary_update(options); 4356 } 4357 return img; 4358 }; 4359 4360 4361 /** 4362 * @override 4363 */ 4364 4365 CloudinaryJQuery.prototype.responsive = function(options) { 4366 var ref, ref1, ref2, responsiveClass, responsiveConfig, responsiveResizeInitialized, responsive_resize, timeout; 4367 responsiveConfig = jQuery.extend(responsiveConfig || {}, options); 4368 responsiveClass = (ref = this.responsiveConfig['responsive_class']) != null ? ref : this.config('responsive_class'); 4369 jQuery("img." + responsiveClass + ", img.cld-hidpi").cloudinary_update(responsiveConfig); 4370 responsive_resize = (ref1 = (ref2 = responsiveConfig['responsive_resize']) != null ? ref2 : this.config('responsive_resize')) != null ? ref1 : true; 4371 if (responsive_resize && !responsiveResizeInitialized) { 4372 responsiveConfig.resizing = responsiveResizeInitialized = true; 4373 timeout = null; 4374 return jQuery(window).on('resize', (function(_this) { 4375 return function() { 4376 var debounce, ref3, ref4, reset, run, wait; 4377 debounce = (ref3 = (ref4 = responsiveConfig['responsive_debounce']) != null ? ref4 : _this.config('responsive_debounce')) != null ? ref3 : 100; 4378 reset = function() { 4379 if (timeout) { 4380 clearTimeout(timeout); 4381 return timeout = null; 4382 } 4383 }; 4384 run = function() { 4385 return jQuery("img." + responsiveClass).cloudinary_update(responsiveConfig); 4386 }; 4387 wait = function() { 4388 reset(); 4389 return setTimeout((function() { 4390 reset(); 4391 return run(); 4392 }), debounce); 4393 }; 4394 if (debounce) { 4395 return wait(); 4396 } else { 4397 return run(); 4398 } 4399 }; 4400 })(this)); 4401 } 4402 }; 4403 4404 return CloudinaryJQuery; 4405 4406 })(Cloudinary); 4407 4408 /** 4409 * The following methods are provided through the jQuery class 4410 * @class jQuery 4411 */ 4412 4413 /** 4414 * Convert all img tags in the collection to utilize Cloudinary. 4415 * @function jQuery#cloudinary 4416 * @param {Object} [options] - options for the tag and transformations 4417 * @returns {jQuery} 4418 */ 4419 jQuery.fn.cloudinary = function(options) { 4420 this.filter('img').each(function() { 4421 var img_options, public_id, url; 4422 img_options = jQuery.extend({ 4423 width: jQuery(this).attr('width'), 4424 height: jQuery(this).attr('height'), 4425 src: jQuery(this).attr('src') 4426 }, jQuery(this).data(), options); 4427 public_id = img_options.source || img_options.src; 4428 delete img_options.source; 4429 delete img_options.src; 4430 url = jQuery.cloudinary.url(public_id, img_options); 4431 img_options = new Transformation(img_options).toHtmlAttributes(); 4432 return jQuery(this).data('src-cache', url).attr({ 4433 width: img_options.width, 4434 height: img_options.height 4435 }); 4436 }).cloudinary_update(options); 4437 return this; 4438 }; 4439 4440 /** 4441 * Update hidpi (dpr_auto) and responsive (w_auto) fields according to the current container size and the device pixel ratio. 4442 * Only images marked with the cld-responsive class have w_auto updated. 4443 * options: 4444 * - responsive_use_stoppoints: 4445 * - true - always use stoppoints for width 4446 * - "resize" - use exact width on first render and stoppoints on resize (default) 4447 * - false - always use exact width 4448 * - responsive: 4449 * - true - enable responsive on this element. Can be done by adding cld-responsive. 4450 * Note that jQuery.cloudinary.responsive() should be called once on the page. 4451 * - responsive_preserve_height: if set to true, original css height is perserved. Should only be used if the transformation supports different aspect ratios. 4452 */ 4453 jQuery.fn.cloudinary_update = function(options) { 4454 if (options == null) { 4455 options = {}; 4456 } 4457 jQuery.cloudinary.cloudinary_update(this.filter('img').toArray(), options); 4458 return this; 4459 }; 4460 webp = null; 4461 4462 /** 4463 * @function jQuery#webpify 4464 */ 4465 jQuery.fn.webpify = function(options, webp_options) { 4466 var that, webp_canary; 4467 if (options == null) { 4468 options = {}; 4469 } 4470 that = this; 4471 webp_options = webp_options != null ? webp_options : options; 4472 if (!webp) { 4473 webp = jQuery.Deferred(); 4474 webp_canary = new Image; 4475 webp_canary.onerror = webp.reject; 4476 webp_canary.onload = webp.resolve; 4477 webp_canary.src = 'data:image/webp;base64,UklGRi4AAABXRUJQVlA4TCEAAAAvAUAAEB8wAiMwAgSSNtse/cXjxyCCmrYNWPwmHRH9jwMA'; 4478 } 4479 jQuery(function() { 4480 return webp.done(function() { 4481 return jQuery(that).cloudinary(jQuery.extend({}, webp_options, { 4482 format: 'webp' 4483 })); 4484 }).fail(function() { 4485 return jQuery(that).cloudinary(options); 4486 }); 4487 });
4488 return this; 4489 }; 4490 jQuery.fn.fetchify = function(options) { 4491 return this.cloudinary(jQuery.extend(options, { 4492 'type': 'fetch' 4493 })); 4494 }; 4495 jQuery.cloudinary = new CloudinaryJQuery(); 4496 jQuery.cloudinary.fromDocument(); 4497 4498 /** 4499 * This module extends CloudinaryJquery to support jQuery File Upload 4500 * Depends on 'jquery', 'util', 'cloudinaryjquery', 'jquery.ui.widget', 'jquery.iframe-transport','jquery.fileupload' 4501 */ 4502 4503 /** 4504 * Delete a resource using the upload token 4505 * @function CloudinaryJQuery#delete_by_token 4506 * @param {string} delete_token - the delete token 4507 * @param {Object} [options] 4508 * @param {string} [options.url] - an alternative URL to use for the API 4509 * @param {string} [options.cloud_name] - an alternative cloud_name to use. This parameter is ignored if `options.url` is provided. 4510 */ 4511 CloudinaryJQuery.prototype.delete_by_token = function(delete_token, options) { 4512 var cloud_name, dataType, url; 4513 options = options || {}; 4514 url = options.url; 4515 if (!url) { 4516 cloud_name = options.cloud_name || jQuery.cloudinary.config().cloud_name; 4517 url = 'https://api.cloudinary.com/v1_1/' + cloud_name + '/delete_by_token'; 4518 } 4519 dataType = jQuery.support.xhrFileUpload ? 'json' : 'iframe json'; 4520 return jQuery.ajax({ 4521 url: url, 4522 method: 'POST', 4523 data: { 4524 token: delete_token 4525 }, 4526 headers: { 4527 'X-Requested-With': 'XMLHttpRequest' 4528 }, 4529 dataType: dataType 4530 }); 4531 }; 4532 4533 /** 4534 * Creates an `input` tag and sets it up to upload files to cloudinary 4535 * @function CloudinaryJQuery#unsigned_upload_tag 4536 * @param {string} 4537 */ 4538 CloudinaryJQuery.prototype.unsigned_upload_tag = function(upload_preset, upload_params, options) { 4539 return jQuery('<input/>').attr({ 4540 type: 'file', 4541 name: 'file' 4542 }).unsigned_cloudinary_upload(upload_preset, upload_params, options); 4543 }; 4544 4545 /** 4546 * Initialize the jQuery File Upload plugin to upload to Cloudinary 4547 * @function jQuery#cloudinary_fileupload 4548 * @param {Object} options 4549 * @returns {jQuery} 4550 */ 4551 jQuery.fn.cloudinary_fileupload = function(options) { 4552 var cloud_name, initializing, resource_type, type, upload_url; 4553 if (!Util.isFunction(jQuery.fn.fileupload)) { 4554 return this; 4555 } 4556 initializing = !this.data('blueimpFileupload'); 4557 if (initializing) { 4558 options = jQuery.extend({ 4559 maxFileSize: 20000000, 4560 dataType: 'json', 4561 headers: { 4562 'X-Requested-With': 'XMLHttpRequest' 4563 } 4564 }, options); 4565 } 4566 this.fileupload(options); 4567 if (initializing) { 4568 this.bind('fileuploaddone', function(e, data) { 4569 var add_field, field, multiple, upload_info; 4570 if (data.result.error) { 4571 return; 4572 } 4573 data.result.path = ['v', data.result.version, '/', data.result.public_id, data.result.format ? '.' + data.result.format : ''].join(''); 4574 if (data.cloudinaryField && data.form.length > 0) { 4575 upload_info = [data.result.resource_type, data.result.type, data.result.path].join('/') + '#' + data.result.signature; 4576 multiple = jQuery(e.target).prop('multiple'); 4577 add_field = function() { 4578 return jQuery('<input/>').attr({ 4579 type: 'hidden', 4580 name: data.cloudinaryField 4581 }).val(upload_info).appendTo(data.form); 4582 }; 4583 if (multiple) { 4584 add_field(); 4585 } else { 4586 field = jQuery(data.form).find('input[name="' + data.cloudinaryField + '"]'); 4587 if (field.length > 0) { 4588 field.val(upload_info); 4589 } else { 4590 add_field(); 4591 } 4592 } 4593 } 4594 return jQuery(e.target).trigger('cloudinarydone', data); 4595 }); 4596 this.bind('fileuploadsend', function(e, data) { 4597 data.headers = jQuery.extend({}, data.headers, { 4598 'X-Unique-Upload-Id': (Math.random() * 10000000000).toString(16) 4599 }); 4600 return true; 4601 }); 4602 this.bind('fileuploadstart', function(e) { 4603 return jQuery(e.target).trigger('cloudinarystart'); 4604 }); 4605 this.bind('fileuploadstop', function(e) { 4606 return jQuery(e.target).trigger('cloudinarystop'); 4607 }); 4608 this.bind('fileuploadprogress', function(e, data) { 4609 return jQuery(e.target).trigger('cloudinaryprogress', data); 4610 }); 4611 this.bind('fileuploadprogressall', function(e, data) { 4612 return jQuery(e.target).trigger('cloudinaryprogressall', data); 4613 }); 4614 this.bind('fileuploadfail', function(e, data) { 4615 return jQuery(e.target).trigger('cloudinaryfail', data); 4616 }); 4617 this.bind('fileuploadalways', function(e, data) { 4618 return jQuery(e.target).trigger('cloudinaryalways', data); 4619 }); 4620 if (!this.fileupload('option').url) {
4621 cloud_name = options.cloud_name || jQuery.cloudinary.config().cloud_name; 4622 resource_type = options.resource_type || 'auto'; 4623 type = options.type || 'upload'; 4624 upload_url = 'https://api.cloudinary.com/v1_1/' + cloud_name + '/' + resource_type + '/' + type; 4625 this.fileupload('option', 'url', upload_url); 4626 } 4627 } 4628 return this; 4629 }; 4630 4631 /** 4632 * Add a file to upload 4633 * @function jQuery#cloudinary_upload_url 4634 * @param {string} remote_url - the url to add 4635 * @returns {jQuery} 4636 */ 4637 jQuery.fn.cloudinary_upload_url = function(remote_url) { 4638 if (!Util.isFunction(jQuery.fn.fileupload)) { 4639 return this; 4640 } 4641 this.fileupload('option', 'formData').file = remote_url; 4642 this.fileupload('add', { 4643 files: [remote_url] 4644 }); 4645 delete this.fileupload('option', 'formData').file; 4646 return this; 4647 }; 4648 4649 /** 4650 * Initialize the jQuery File Upload plugin to upload to Cloudinary using unsigned upload 4651 * @function jQuery#unsigned_cloudinary_upload 4652 * @param {string} upload_preset - the upload preset to use 4653 * @param {Object} [upload_params] - parameters that should be past to the server 4654 * @param {Object} [options] 4655 * @returns {jQuery} 4656 */ 4657 jQuery.fn.unsigned_cloudinary_upload = function(upload_preset, upload_params, options) { 4658 var attr, attrs_to_move, html_options, i, key, value; 4659 if (upload_params == null) { 4660 upload_params = {}; 4661 } 4662 if (options == null) { 4663 options = {}; 4664 } 4665 upload_params = Util.cloneDeep(upload_params); 4666 options = Util.cloneDeep(options); 4667 attrs_to_move = ['cloud_name', 'resource_type', 'type']; 4668 i = 0; 4669 while (i < attrs_to_move.length) { 4670 attr = attrs_to_move[i]; 4671 if (upload_params[attr]) { 4672 options[attr] = upload_params[attr]; 4673 delete upload_params[attr]; 4674 } 4675 i++; 4676 } 4677 for (key in upload_params) { 4678 value = upload_params[key]; 4679 if (Util.isPlainObject(value)) { 4680 upload_params[key] = jQuery.map(value, function(v, k) { 4681 if (Util.isString(v)) { 4682 v = v.replace(/[\|=]/g, "\\$&"); 4683 } 4684 return k + '=' + v; 4685 }).join('|'); 4686 } else if (Util.isArray(value)) { 4687 if (value.length > 0 && jQuery.isArray(value[0])) { 4688 upload_params[key] = jQuery.map(value, function(array_value) { 4689 return array_value.join(','); 4690 }).join('|'); 4691 } else { 4692 upload_params[key] = value.join(','); 4693 } 4694 } 4695 } 4696 if (!upload_params.callback) { 4697 upload_params.callback = '/cloudinary_cors.html'; 4698 } 4699 upload_params.upload_preset = upload_preset; 4700 options.formData = upload_params; 4701 if (options.cloudinary_field) { 4702 options.cloudinaryField = options.cloudinary_field; 4703 delete options.cloudinary_field; 4704 } 4705 html_options = options.html || {}; 4706 html_options["class"] = Util.trim("cloudinary_fileupload " + (html_options["class"] || '')); 4707 if (options.multiple) { 4708 html_options.multiple = true; 4709 } 4710 this.attr(html_options).cloudinary_fileupload(options); 4711 return this; 4712 }; 4713 jQuery.cloudinary = new CloudinaryJQuery(); 4714 cloudinary = { 4715 utf8_encode: utf8_encode, 4716 crc32: crc32, 4717 Util: Util, 4718 Condition: Condition, 4719 Transformation: Transformation, 4720 Configuration: Configuration, 4721 HtmlTag: HtmlTag, 4722 ImageTag: ImageTag, 4723 VideoTag: VideoTag, 4724 ClientHintsMetaTag: ClientHintsMetaTag, 4725 Layer: Layer, 4726 FetchLayer: FetchLayer, 4727 TextLayer: TextLayer, 4728 SubtitlesLayer: SubtitlesLayer, 4729 Cloudinary: Cloudinary, 4730 VERSION: "2.5.0", 4731 CloudinaryJQuery: CloudinaryJQuery 4732 }; 4733 return cloudinary; 4734}); 4735 4736
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.