PageRenderTime 61ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/chute.js

https://github.com/shinebig/media-chooser
JavaScript | 1803 lines | 1280 code | 268 blank | 255 comment | 368 complexity | de866c87b905cd888b1231a74b959109 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. function chutelog(what) {
  2. try {
  3. console.log(what);
  4. }
  5. catch (e) {}
  6. finally {
  7. return;
  8. }
  9. }
  10. /*
  11. * jQuery SlideChute Plugin 1.0.0
  12. * www.slidechute.com
  13. * Copyright 2012, Chute Corporation
  14. * Free to use under the MIT license.
  15. * http://www.opensource.org/licenses/mit-license.php
  16. */
  17. var currentWidget = null;
  18. var $chuteWidget;
  19. function chuteGetScript(url, success) {
  20. var script = document.createElement('script');
  21. script.src = url;
  22. var head = document.getElementsByTagName('head')[0],
  23. done = false;
  24. script.onload = script.onreadystatechange = function() {
  25. if (!done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')) {
  26. done = true;
  27. success();
  28. script.onload = script.onreadystatechange = null;
  29. head.removeChild(script);
  30. }
  31. };
  32. head.appendChild(script);
  33. }
  34. var __chute = function(element, data){
  35. function _loader(element, data){
  36. __chuteFunctions()
  37. jQuery(element).chute(data);
  38. }
  39. if (typeof(jQuery) != 'undefined') {
  40. _loader(element, data);
  41. }
  42. var _readyCallback = function(){
  43. if (typeof(jQuery) == 'undefined'){
  44. chuteGetScript('//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js', function(){
  45. setTimeout(function(){
  46. _loader(element, data);
  47. }, 10);
  48. });
  49. } else {
  50. _loader(element, data);
  51. }
  52. }
  53. var _loadCallback = function(){
  54. if (document.readyState == 'complete'){
  55. _readyCallback();
  56. }
  57. };
  58. if (typeof(jQuery) == 'undefined'){
  59. if (document.readyState == 'complete'){
  60. _readyCallback();
  61. } else if (document.addEventListener){
  62. document.addEventListener("readystatechange", _loadCallback);
  63. } else {
  64. document.attachEvent("onreadystatechange", _loadCallback);
  65. }
  66. }
  67. }
  68. var __chuteFunctions = function(){
  69. (function($) {
  70. var CHUTE = {
  71. popupHtml: "<style type='text/css'>.chute-reveal-modal { visibility:hidden }</style><div class='chute-popup chute-reveal-modal'>\
  72. <iframe width='100%' height='100%' marginWidth='0' marginHeight='0' frameBorder='0' scrolling='no' title='' src='//s3.amazonaws.com/cdn.getchute.com/html/v1/loading.html'>IFrame not supported</iframe>\
  73. <a class='close-chute-reveal-modal'>&#215;</a>\
  74. </div>\
  75. <div class='chute-thanks chute-reveal-modal'>\
  76. <div class='chute-thanks-header'>SUCCESS_MESSAGE</div>\
  77. <div class='chute-thanks-footer'>\
  78. <a href='mailto:info@getchute.com'>info@getchute.com</a>\
  79. </div>\
  80. <a class='close-chute-reveal-modal'>&nbsp;</a>\
  81. </div>",
  82. defaultDisplayTemplateHtml: "<style type='text/css'>.chute-thumbnails a{margin: 5px} .chute-thumbnails img{width:100px;height:100px;} .chute-thumbnail-reveal-modal {visibility: hidden;top: 0;left: 50%;margin-left: -250px;width: 500px;max-height: 800px;position: fixed;z-index: 10001;background-color:#fff;-moz-box-shadow: 0 0 10px rgba(0,0,0,.4);-webkit-box-shadow: 0 0 10px rgba(0,0,0,.4);-box-shadow: 0 0 10px rgba(0,0,0,.4);overflow:hidden;} .chute-thumbnail-reveal-modal img{width: 100%;float: left;} .chute-thumbnail-reveal-modal .close-chute-thumbnail-reveal-modal {font-size: 22px;line-height: .5;position: absolute;top: 15px;right: 11px;color: #aaa;text-shadow: 0 -1px 1px rbga(0,0,0,.6);font-weight: bold;cursor: pointer;} .chute-thumbnail-reveal-modal .chute-thumbnail-source{position:absolute;left: 0;bottom: 30px;background-color: #000;background-color: rgba(0,0,0, 0.6);color: #fff;padding: 5px;text-decoration: none;-moz-box-shadow: 0 0 5px #888;-webkit-box-shadow: 0 0 5px#888;box-shadow: 0 0 5px #888;} .chute-reveal-modal-bg {position: fixed;height: 100%;width: 100%;background: #000;background: rgba(150,150,150,.8);z-index: 10000;display: none;top: 0;left: 0;}</style><div class='chute-thumbnails'>{{#images}}<a href='{{url}}' data-source-url='{{source_url}}' data-url='{{url}}'><img src='{{url}}/100x100'></a>{{/images}}</div>",
  83. defaultCollectTemplateHtml: "<a href='#' class='chute-browseButton'><img src='//s3.amazonaws.com/cdn.getchute.com/v1/images/add-photos.png' style='border:0'></a>",
  84. // Paths
  85. paths: {
  86. assets : '/assets/:id', // Path to assets data
  87. gallery : '/chutes/:id.js', // Path to gallery data
  88. collection : '/collection/:id' // Path to collection data
  89. },
  90. // Defaults
  91. defaults: {
  92. uploadServer : '//upload.getchute.com', // Path to Upload Server
  93. apiServer : '//api.getchute.com', // Path to API
  94. cdnRoot : '//s3.amazonaws.com/cdn.getchute.com/v1',
  95. popup : false,
  96. app : null, // ID of the app
  97. disable_auto_identifier : false,
  98. display_template_name : null, // required only with an external url based template
  99. display_template : null, // jQuery Object or HTML template
  100. collector_template_name : null, // collector theme name
  101. collector_template : null, // collector theme path
  102. collector_width : '635px', // collector template width
  103. collector_height : '435px', // collector template height
  104. template_options : {},
  105. // Data Sources
  106. assets : null, // ID of Asset(s) to render as comma-delimited list
  107. gallery : null, // ID of the Gallery to render
  108. collection : null, // ID of the Collection to render
  109. // Externals
  110. css : '', // Comma-delimited list of css externals to load
  111. css_loaded : false, // Boolean indicating if all required css is loaded
  112. scripts : '', // Comma-delimited list of js externals to load
  113. scripts_lodaed : false, // Boolean indicating if all required js is loaded,
  114. exclusions : "",
  115. file_types : 1, // 0 = all, 1 = image, 2 = video
  116. file_limit : 0, // 0 = unlimited
  117. is_display : true,
  118. success_message : "<h3>Thanks!</h3><p>Your photos will be online as soon as they're approved</p>",
  119. // Plugin Events
  120. onComplete : function() {}, // Fired when the the plugin has completely initialized
  121. // Display Events
  122. onTemplateLoaded : function() {}, // Fired when template loaded
  123. onDependenciesLoaded : function() {}, // Fired when template dependencies loaded
  124. onAssetsLoading : function() {}, // Fired when assets are starting to load
  125. onAssetsLoaded : function() {}, // Fired when assets are loaded
  126. onAssetsRendered : null, // Fired when assets are rendered
  127. onAssetsReRendered : function() {}, // Fired when assets are re-rendered
  128. // Collection Events
  129. onDrop : function() {}, // Fired when assets are dropped on the plugin
  130. onAlbumList : function() {}, // Fired when the listing of albums is loaded
  131. onAlbumLoad : function() {}, // Fired when an external album loads
  132. onAdd : function() {}, // Fired when assets are selection for inclusion
  133. onRemove : function() {}, // Fired when assets are removed from inclusion
  134. onSelection : function() {}, // Fired when selection of photos has been completed
  135. onConfirmation : function() {}, // Fired when rights are confirmed
  136. onProfileComplete : function() {}, // Fired when custom profile is completed
  137. onSelectionComplete : function() {} // Fired when widget has completed the process
  138. },
  139. // Initializer
  140. init: function(element, options) {
  141. // Save values
  142. this.$element = $(element);
  143. this.$element.addClass('chute-loaded');
  144. // pull in options specified by html5 tags
  145. var _htmlOptions = {
  146. app : this.$element.attr('data-app-id'),
  147. identifier : this.$element.attr('data-identifier') == undefined || this.$element.attr('data-identifier') == '' ? null : this.$element.attr('data-identifier'),
  148. disable_auto_identifier : this.$element.attr('data-disable-auto-identifier') == undefined ? this.defaults.disable_auto_identifier : true,
  149. id : this.$element.attr('data-id') == undefined ? null : this.$element.attr('data-id'),
  150. bundle_id : this.$element.attr('data-bundle-id') == undefined ? '' : this.$element.attr('data-bundle-id'),
  151. custom_id : this.$element.attr('data-custom_id') == undefined ? '' : this.$element.attr('data-custom_id'),
  152. assets : this.$element.attr('data-assets') == undefined ? this.defaults.assets : this.$element.attr('data-assets').split(','),
  153. name : this.$element.attr('data-name'),
  154. url : this.$element.attr('data-url') == undefined ? document.location.href : this.$element.attr('data-url'),
  155. tags : this.$element.attr('data-tags') == undefined ? '' : this.$element.attr('data-tags'),
  156. css : this.$element.attr('data-css') == undefined ? '' : this.$element.attr('data-css'),
  157. screens : this.$element.attr('data-screens') == undefined ? '' : this.$element.attr('data-screens'),
  158. display_template_name : this.$element.attr('data-display-template-name') == undefined ? this.defaults.display_template_name : this.$element.attr('data-display-template-name'),
  159. display_template : this.$element.attr('data-display-template') == undefined ? this.defaults.display_template : this.$element.attr('data-display-template'),
  160. collector_template_name : this.$element.attr('data-collector-template-name') == undefined ? this.defaults.collector_template_name : this.$element.attr('data-collector-template-name'),
  161. collector_template : this.$element.attr('data-collector-template') == undefined ? this.defaults.collector_template : this.$element.attr('data-collector-template'),
  162. collector_width : this.$element.attr('data-collector-width') == undefined ? this.defaults.collector_width : this.$element.attr('data-collector-width'),
  163. collector_height : this.$element.attr('data-collector-height') == undefined ? this.defaults.collector_height : this.$element.attr('data-collector-height'),
  164. template_options : this.$element.attr('data-template-options') == undefined ? this.defaults.template_options : $.parseJSON(this.$element.attr('data-template-options')),
  165. captions : this.$element.attr('data-captions') == undefined ? 'hide' : this.$element.attr('data-captions'),
  166. exclusions : this.$element.attr('data-services-exclude') == undefined ? this.defaults.exclusions : this.$element.attr('data-services-exclude'),
  167. inclusions : this.$element.attr('data-services-include') == undefined ? '' : this.$element.attr('data-services-include'),
  168. dialogTitle : this.$element.attr('data-chooser-button-text') == undefined ? 'Choose Photos' : this.$element.attr('data-chooser-button-text'),
  169. mode : this.$element.attr('data-mode') == undefined ? 'thumbnails' : this.$element.attr('data-mode'),
  170. uploadServer : this.$element.attr('data-uploadServer') == undefined ? this.defaults.uploadServer : this.$element.attr('data-uploadServer'),
  171. apiServer : this.$element.attr('data-apiServer') == undefined ? this.defaults.apiServer : this.$element.attr('data-apiServer'),
  172. cdnRoot : this.$element.attr('data-cdnRoot') == undefined ? this.defaults.cdnRoot : this.$element.attr('data-cdnRoot'),
  173. file_types : this.$element.attr('data-file-types') == undefined ? this.defaults.file_types : this.$element.attr('data-file-types'),
  174. file_limit : this.$element.attr('data-file-limit') == undefined ? this.defaults.file_limit : this.$element.attr('data-file-limit'),
  175. share_text : this.$element.attr('data-share-text') == undefined ? '' : this.$element.attr('data-share-text'),
  176. awesm_key : this.$element.attr('data-awesm-key') == undefined ? '' : this.$element.attr('data-awesm-key'),
  177. popup : this.$element.attr('data-popup') == 'popup',
  178. success_message : this.$element.attr('data-success_message') == undefined ? this.defaults.success_message : this.$element.attr('data-success_message')
  179. }
  180. // Set the options
  181. this.options = $.extend({}, this.defaults, _htmlOptions);
  182. this.options = $.extend({}, this.options, options);
  183. this.options.is_display = !(this.options.mode == 'collector' || this.options.mode == 'chooser');
  184. this.popupHtml = this.popupHtml.replace('SUCCESS_MESSAGE', this.options.success_message);
  185. if (this.options.identifier == null && !this.options.disable_auto_identifier){
  186. this.options.identifier = '';
  187. this.options.id = '';
  188. }
  189. // use popup window when in an iframe hosted by us, or on a mobile
  190. // browser, unless already specified
  191. if ((!this.options.popup && window!=window.top && (document.location.host.indexOf("chute.com") == 0 || document.location.host.indexOf("slidechute.com") == 0))
  192. || navigator.userAgent.match(/Android|webOS|iPhone|iPad|iPod|BlackBerry/i)) {
  193. this.options.popup = true;
  194. }
  195. var me = this;
  196. me.$element.addClass('chute-base-widget').css('position', 'relative');
  197. me.$element.data('options', this.options);
  198. me.$element.data('instanceReference', this);
  199. if (me.options.is_display){
  200. if (this.options.display_template == null && this.options.display_template_name != null){
  201. this.options.display_template = this.options.cdnRoot + "/templates/display/" + this.options.display_template_name + "/template.js";
  202. }
  203. if (me.options.display_template && me.options.display_template.indexOf('#') == 0){
  204. me.options.display_template = $(me.options.display_template).html();
  205. me.renderData();
  206. } else if (this.options.display_template != undefined && (this.options.display_template.indexOf('http') == 0 || this.options.display_template.indexOf('//') == 0)){
  207. $.getScript(me.options.display_template, function() {
  208. me.loadTemplateData(function(){
  209. me.options.onDependenciesLoaded(me.$element);
  210. me.renderData();
  211. });
  212. });
  213. } else if (this.options.display_template_name == undefined || this.options.display_template_name == 'default' || this.options.display_template_name == ''){
  214. this.options.display_template = this.defaultDisplayTemplateHtml;
  215. this.options.onAssetsRendered = this.assetsRendered;
  216. me.renderData();
  217. }
  218. }
  219. else {
  220. if (this.options.collector_template == null && this.options.collector_template_name == null){
  221. this.options.collector_template = this.defaultCollectTemplateHtml;
  222. }
  223. else if (this.options.collector_template == null){
  224. this.options.collector_template = this.options.cdnRoot + "/templates/collector/" + this.options.collector_template_name + "/template.js";
  225. }
  226. me.renderData();
  227. }
  228. me.options.onComplete();
  229. return me;
  230. },
  231. renderData: function(page_url){
  232. var me = this;
  233. me.resetTimestamp();
  234. if (me.options.is_display){
  235. if (me.options.id == null && me.options.identifier == null){
  236. me.$element.addClass('chute-disabled').css('opacity', '0.5');
  237. return;
  238. }
  239. me.options.onAssetsLoading(me.$element);
  240. var defaultUrl = me.options.imagesUrl;
  241. // if assets already given then get the ids
  242. if (me.options.assets){
  243. var staticAssets = "";
  244. if (typeof me.options.assets == 'string')
  245. me.options.assets = me.options.assets.split(',');
  246. if (me.options.assets[0].indexOf('http') == 0) {
  247. staticAssets = "assets=" + $.map(me.options.assets, function(asset_url){
  248. var match = asset_url.match("\/m\/([^\/]+)/");
  249. return match.pop();
  250. }).join(',');
  251. } else {
  252. staticAssets = "assets=" + me.options.assets.join(',');
  253. }
  254. defaultUrl += "&" + staticAssets;
  255. }
  256. if (this.options.template_options.per_page)
  257. defaultUrl += "&per_page=" + this.options.template_options.per_page;
  258. var loadState = page_url == undefined ? -1 : (page_url == me.options.nextImagesUrl ? 0 : 1);
  259. var _url = page_url ? page_url : defaultUrl;
  260. // if there is a hash in the document, then it could point to an asset
  261. // make sure its there in the page
  262. if (loadState == -1 && document.location.hash != "" && document.location.hash != "#"){
  263. var _extraAssetId = document.location.hash.replace('#', '');
  264. _url = _url + "&extra_assets=" + _extraAssetId;
  265. }
  266. me.loadPath(_url, function(data){
  267. // new data link
  268. // don't update when requesting next and previous pages
  269. if (data.data.next_url && loadState != 1){
  270. me.options.nextImagesUrl = data.data.next_url;
  271. }
  272. // paginations link
  273. // don't update when requesting new data
  274. if (loadState != 0){
  275. me.options.nextPageUrl = data.data.next_page_url;
  276. me.options.previousPageUrl = data.data.previous_page_url;
  277. }
  278. if (data.data.assets.length > 0){
  279. if (me.options.onAssetsLoaded(me.$element, data) != false){
  280. // writeout template html in page
  281. me.displayRender(data, loadState);
  282. }
  283. }
  284. });
  285. } else {
  286. me.setupCollectorModal();
  287. me.collectorRender(function(){
  288. me.$element.find('.chute-popup').css({
  289. width: me.options.collector_width,
  290. height: me.options.collector_height,
  291. 'margin-left' : '-' + parseInt(me.options.collector_width)/2 + 'px'
  292. });
  293. if (me.options.id == null && me.options.identifier == null){
  294. me.$element.addClass('chute-disabled').css('opacity', '0.5');
  295. return;
  296. }
  297. me.makeDroppable(me.$element.find('.chutedrop'));
  298. });
  299. }
  300. },
  301. hasNextPage: function(){
  302. return (this.options.nextPageUrl != undefined);
  303. },
  304. hasPreviousPage: function(){
  305. return (this.options.previousPageUrl != undefined);
  306. },
  307. hasNewPage: function(){
  308. return (this.options.nextImagesUrl != undefined);
  309. },
  310. renderNextPage: function(){
  311. if (this.hasNextPage()){
  312. this.renderData(this.options.nextPageUrl)
  313. }
  314. },
  315. renderPreviousPage: function(){
  316. if (this.hasPreviousPage())
  317. this.renderData(this.options.previousPageUrl)
  318. },
  319. renderNewData: function(){
  320. if (this.hasNewPage()){
  321. this.renderData(this.options.nextImagesUrl)
  322. }
  323. },
  324. //////////////////////////////////////////////////////////
  325. // Loaders
  326. //////////////////////////////////////////////////////////
  327. // Load CSS dependencies
  328. loadCSS: function(url) {
  329. if(!url) return;
  330. if (typeof(url) == 'string') {
  331. if (url.indexOf('http') != 0)
  332. url = document.location.protocol + url;
  333. $('head').append( '<link rel="stylesheet" type="text/css" href="' + url + '" />' );
  334. }
  335. else {
  336. $.each(url, function(i, _url){
  337. if (_url.indexOf('http') != 0)
  338. _url = document.location.protocol + _url;
  339. $('head').append( '<link rel="stylesheet" type="text/css" href="' + _url + '" />' );
  340. });
  341. }
  342. },
  343. // Load JS dependencies
  344. loadJS: function(url, callback) {
  345. if(!url) {
  346. callback();
  347. return;
  348. }
  349. if (typeof(url) == 'string') {
  350. $.getScript(url, callback);
  351. }
  352. else if (url.length == 0) {
  353. callback();
  354. }
  355. else if (url.length == 1) {
  356. $.getScript(url[0], callback);
  357. }
  358. else {
  359. // http://www.jquery4u.com/ajax/getscript-mutiple-scripts/
  360. var // reference declaration & localization
  361. length = url.length,
  362. deferreds = [],
  363. counter = 0,
  364. idx = 0;
  365. var handler = function(){
  366. counter++;
  367. if (counter == length) {
  368. callback();
  369. }
  370. }
  371. for ( ; idx < length; idx++ ) {
  372. deferreds.push(
  373. $.getScript( url[ idx ], handler )
  374. );
  375. }
  376. }
  377. },
  378. // Load the data based on the passed data sources
  379. // Data order: Collection > Gallery > Asset
  380. loadData: function(callback) {
  381. var path = '';
  382. // Collection
  383. if (this.options.collection != null) {
  384. path = this.paths.collection.replace(':id',this.options.collection);
  385. // Gallery
  386. } else if (this.options.gallery != null) {
  387. path = this.paths.gallery.replace(':id',this.options.gallery);
  388. // Asset
  389. } else if (this.options.assets != null) {
  390. path = this.paths.asset.replace(':id',this.options.asset);
  391. }
  392. // If we have found a data call to make, complete it
  393. if (path.length) {
  394. var url = this.paths.api + path;
  395. /*this.loadJS(this.paths.api + path, function(data, status) {
  396. console.log(data)
  397. console.log(status)
  398. });*/
  399. //$.get(url, function(data, status) { console.log(data); console.log(status);}, "json");
  400. $.ajax({
  401. url : this.paths.api + path,
  402. dataType : 'jsonp',
  403. success : function(data, textStatus, jqXHR) {
  404. // console.log(data);
  405. },
  406. error : function(e) {
  407. // console.log(e);
  408. }
  409. });
  410. }
  411. },
  412. loadPath: function(path, callback){
  413. $.ajax({
  414. url : path,
  415. dataType : 'jsonp',
  416. success : function(data, textStatus, jqXHR) {
  417. callback(data);
  418. },
  419. error : function(e) {
  420. // console.log(e);
  421. }
  422. });
  423. },
  424. //////////////////////////////////////////////////////////
  425. // Load Template Data
  426. //////////////////////////////////////////////////////////
  427. loadTemplateData : function(callback){
  428. var me = this;
  429. if (this.options.is_display){
  430. this.options.display_template = eval(this.options.display_template_name + '_template_definition');
  431. if (typeof(this.options.display_template) != 'string'){
  432. this.options = $.extend({}, this.options, this.options.display_template.bindings);
  433. this.options.onTemplateLoaded(me.$element);
  434. me.loadCSS(this.options.display_template.requires.css);
  435. me.loadJS(this.options.display_template.requires.js, function(){
  436. callback();
  437. });
  438. } else {
  439. callback();
  440. }
  441. }
  442. },
  443. //////////////////////////////////////////////////////////
  444. // Collectors
  445. //////////////////////////////////////////////////////////
  446. // Load dependencies for collection mode
  447. setupCollectorModal: function() {
  448. if (!$('#chute-collector-modal').length) {
  449. // Load Reveal External
  450. this.loadCSS(this.options.cdnRoot + '/css/c.css');
  451. }
  452. },
  453. // Render Collector
  454. collectorRender: function(callback) {
  455. var me = this;
  456. if (me.options.collector_template.indexOf('http') == 0) {
  457. $.getScript(me.options.collector_template, function() {
  458. me.$element.html(me.popupHtml + eval(me.options.collector_template_name + '_template_html'));
  459. callback();
  460. });
  461. } else {
  462. me.$element.html(me.popupHtml + me.options.collector_template);
  463. callback();
  464. }
  465. },
  466. // Collector Modal
  467. collectorModal: function() {
  468. this.setupCollectorModal();
  469. // Attach the behavior
  470. this.$element.click(function(event) {
  471. event.preventDefault();
  472. })
  473. },
  474. makeDroppable: function(element) {
  475. var me = this;
  476. me.$element.find('.chute-browseButton, .chute-dropBox').click(function(event){
  477. event.preventDefault();
  478. me.openChuteBrowser();
  479. });
  480. me.openChuteBrowser = function(){
  481. if (me.options.popup){
  482. var width = 700;
  483. var height = 450
  484. var left = parseInt((screen.availWidth/2) - (width/2));
  485. var top = parseInt((screen.availHeight/2) - (height/2));
  486. var windowFeatures = "width=" + width + ",height=" + height + ",status,resizable,scrollbars=0,left=" + left + ",top=" + top + "screenX=" + left + ",screenY=" + top;
  487. window.open(me.options.browsePath, "chute_browse_popup", windowFeatures);
  488. } else if (me.options.embed) {
  489. var element = jQuery(me.options.embed).append(me.$element.find('.chute-popup iframe').clone().attr('src', me.options.browsePath));
  490. element.css({
  491. width: 600,
  492. height: 400
  493. });
  494. } else {
  495. me.$element.find(".chute-popup iframe").attr('src', me.options.browsePath);
  496. me.$element.find(".chute-popup").chuteReveal();
  497. }
  498. this.resetTimestamp();
  499. currentWidget = me;
  500. }
  501. me.$element.find('.chute-popup .close-chute-reveal-modal').click(function(){
  502. me.resetIframe();
  503. });
  504. if(element.length == 0) return;
  505. var totalImagesCount = 0;
  506. var uploadedImagesCount = 0;
  507. var totalUploadPercentDone = 0;
  508. var maxFileSize = '';
  509. var extensions = '';
  510. var browseTitle = '';
  511. if (me.options.file_types == 0) {
  512. maxFileSize = '50MB';
  513. extensions = 'jpg,gif,png,jpeg,mov,mp4,mpeg,mpeg,avi';
  514. browseTitle = 'Media Files';
  515. } else if (me.options.file_types == 1) {
  516. maxFileSize = '5MB';
  517. extensions = 'jpg,gif,png,jpeg';
  518. browseTitle = 'Image Files';
  519. } else {
  520. maxFileSize = '50MB';
  521. extensions = 'mov,mp4,mpeg,mpeg,avi';
  522. browseTitle = 'Video Files';
  523. }
  524. element.attr('id', me.options.timestamp);
  525. // upload code - start
  526. var ChuteUploader = new plupload.Uploader({
  527. runtimes : 'html5,flash,silverlight',
  528. browse_button : '',
  529. container : me.options.timestamp,
  530. max_file_size : maxFileSize,
  531. resize : { quality : 90 },
  532. url : me.options.uploadPath,
  533. flash_swf_url : '//s3.amazonaws.com/cdn.getchute.com/objects/v1/plupload.flash.swf',
  534. silverlight_xap_url : '//s3.amazonaws.com/cdn.getchute.com/objects/v1/plupload.silverlight.xap',
  535. filters : [{
  536. title : browseTitle,
  537. extensions : extensions
  538. }],
  539. drop_element : me.options.timestamp
  540. });
  541. ChuteUploader.bind('Init', function(up, params) {
  542. // ready
  543. setTimeout(function(){
  544. me.$element.find('.plupload.html5 input').attr('size', 300);
  545. }, 100);
  546. me.$element.find('.chute-select-button').click(function(event){
  547. event.preventDefault();
  548. me.openChuteBrowser();
  549. });
  550. });
  551. $('#uploadfiles').click(function(e) {
  552. ChuteUploader.start();
  553. e.preventDefault();
  554. });
  555. ChuteUploader.init();
  556. ChuteUploader.bind('FilesAdded', function(up, files) {
  557. me.options.onDrop(me.$element, files);
  558. me.setChuteFileProgress(0);
  559. $.each(files, function(i, file) {
  560. totalImagesCount++;
  561. });
  562. up.refresh(); // Reposition Flash/Silverlight
  563. // automatically start upload, no need to click a button
  564. ChuteUploader.start();
  565. });
  566. ChuteUploader.bind('UploadProgress', function(up, file) {
  567. totalUploadPercentDone = (file.percent + uploadedImagesCount*100)/totalImagesCount;
  568. me.setChuteFileProgress(totalUploadPercentDone);
  569. });
  570. ChuteUploader.bind('Error', function(up, err) {
  571. alert('Files cannot be larger than ' + maxFileSize);
  572. up.refresh(); // Reposition Flash/Silverlight
  573. });
  574. ChuteUploader.bind('FileUploaded', function(up, file) {
  575. uploadedImagesCount ++;
  576. totalUploadPercentDone = (uploadedImagesCount*100)/totalImagesCount;
  577. me.setChuteFileProgress(totalUploadPercentDone);
  578. });
  579. ChuteUploader.bind('UploadComplete', function(up, file) {
  580. totalUploadPercentDone = 100;
  581. me.setChuteFileProgress(totalUploadPercentDone);
  582. me.openChuteBrowser();
  583. });
  584. me.setChuteFileProgress = function(progress){
  585. if (progress < 100) {
  586. me.$element.find('.chute-collector').addClass('chute-uploading');
  587. } else {
  588. me.$element.find('.chute-collector').removeClass('chute-uploading');
  589. }
  590. me.$element.find('.chute-uploadProgress .chute-bar').css('width', progress + "%");
  591. }
  592. // upload code - end
  593. },
  594. resetTimestamp: function(){
  595. var d = new Date();
  596. var timestamp = ("" + (d.getTime()-d.getMilliseconds())/1000 + "-" + Math.random()).replace("0.", "");
  597. this.options.timestamp = timestamp;
  598. var toURIParams = function(obj) {
  599. var val, params=[];
  600. for (var key in obj) {
  601. val = obj[key];
  602. if (val && typeof val != 'undefined' && (val.length > 0 || typeof val === 'number')) {
  603. params.push(key + "=" + encodeURIComponent(val));
  604. }
  605. }
  606. return params.join('&');
  607. };
  608. this.options.uploadPath = this.options.uploadServer + '/upload?' + toURIParams({
  609. timestamp : this.options.timestamp,
  610. app_id : this.options.app,
  611. id : this.options.id,
  612. identifier : this.options.identifier,
  613. title : this.options.name,
  614. url : this.options.url,
  615. tags : this.options.tags,
  616. screens : this.options.screens,
  617. css : this.options.css,
  618. captions : this.options.captions,
  619. exclusions : this.options.exclusions,
  620. inclusions : this.options.inclusions
  621. });
  622. this.options.browsePath = this.options.uploadServer + '/payload/' + this.options.timestamp + "?" + toURIParams({
  623. app_id : this.options.app,
  624. id : this.options.id,
  625. identifier : this.options.identifier,
  626. custom_id : this.options.custom_id,
  627. title : this.options.name,
  628. url : this.options.url,
  629. tags : this.options.tags,
  630. host : document.location.host,
  631. page : document.location.href,
  632. screens : this.options.screens,
  633. css : this.options.css,
  634. scripts : this.options.scripts,
  635. iframe : this.options.iframe,
  636. iframe_position : this.options.iframe_position,
  637. iframe_title : this.options.iframe_title,
  638. captions : this.options.captions,
  639. exclusions : this.options.exclusions,
  640. inclusions : this.options.inclusions,
  641. dialog_title : this.options.dialogTitle,
  642. popup : this.options.popup.toString(),
  643. picker_version : this.options.picker_version,
  644. limit : this.options.limit,
  645. config : this.options.config
  646. });
  647. this.options.imagesUrl = this.options.apiServer + '/widget/data?' + toURIParams({
  648. app_id : this.options.app,
  649. id : this.options.id,
  650. identifier : this.options.identifier,
  651. origin : document.location.host
  652. });
  653. },
  654. resetIframe: function(){
  655. this.$element.find(".chute-popup iframe").attr('src', "//s3.amazonaws.com/cdn.getchute.com/html/v1/loading.html");
  656. },
  657. uploadComplete: function(data){
  658. if (data.moderated && !this.options.popup){
  659. if (data.success_message && typeof data.success_message === 'string' && data.success_message.length > 0) {
  660. this.$element.find('.chute-thanks .chute-thanks-header').html(data.success_message);
  661. }
  662. this.$element.find('.chute-thanks').chuteReveal();
  663. }
  664. this.options.onSelectionComplete(this.$element, data);
  665. if (typeof(chuteSelectionComplete) == 'function'){
  666. chuteSelectionComplete(this.$element, data);
  667. }
  668. },
  669. //////////////////////////////////////////////////////////
  670. // Presenters
  671. //////////////////////////////////////////////////////////
  672. assetsRendered: function(element, data){
  673. var chuteThumbnailReveal = jQuery('#chute-thumbnail-reveal');
  674. if (chuteThumbnailReveal.length == 0){
  675. jQuery('body').append('<div class="chute-thumbnail-reveal-modal" id="chute-thumbnail-reveal"><img src=""><a class="chute-thumbnail-source" href="" target="_blank">source</a><a class="close-chute-thumbnail-reveal-modal">&#215;</a></div>');
  676. chuteThumbnailReveal = jQuery('#chute-thumbnail-reveal');
  677. }
  678. element.find('.chute-thumbnails a').live('click', function(event){
  679. event.preventDefault();
  680. chuteThumbnailReveal.find('img').attr('src', $(this).attr('data-url'));
  681. chuteThumbnailReveal.find('.chute-thumbnail-source').attr('href', $(this).attr('data-source-url'));
  682. chuteThumbnailReveal.chuteReveal({
  683. dismissmodalclass: 'close-chute-thumbnail-reveal-modal',
  684. top: "50px"
  685. });
  686. });
  687. },
  688. // Render Display Template
  689. displayRender: function(data, loadState) {
  690. var _templateDefinition = typeof(this.options.display_template) == 'string' ? this.options.display_template : this.options.display_template.template;
  691. var _templateContainer = typeof(this.options.display_template) == 'string' ? null : this.options.display_template.templateContainer;
  692. for (var key in this.options.template_options){
  693. if (this.options.display_template.options[key]){
  694. this.options.display_template.options[key].value = this.options.template_options[key];
  695. }
  696. }
  697. if (typeof(this.options.display_template.options) != 'undefined') {
  698. this.options.display_template.options.share_text = this.options.share_text;
  699. this.options.display_template.options.awesm_key = this.options.awesm_key;
  700. this.options.display_template.options.chute_id = this.options.chute_id;
  701. this.options.display_template.options.widget_id = this.options.widget_id;
  702. }
  703. for (var i in data.data.assets) {
  704. data.data.assets[i].serialized = encodeURIComponent($.serializeJSON(data.data.assets[i]).replace(/(\r\n|\n|\r|\t)/gm, ""));
  705. }
  706. var _html = ChuteMustache.to_html(_templateDefinition, { images: data.data.assets, options : this.options.display_template.options });
  707. if (_templateContainer){
  708. _html = _templateContainer.replace("{{yield}}", _html);
  709. }
  710. var appendContent = false;
  711. if (this.options.display_template.systemOptions && this.options.display_template.systemOptions.appendContent)
  712. appendContent = true;
  713. if (loadState > -1){
  714. if (_templateContainer){
  715. // new data
  716. if (loadState == 0)
  717. this.options.templateContainer.prepend(_html);
  718. // paginated data
  719. else if (appendContent)
  720. this.options.templateContainer.append(_html);
  721. else
  722. this.options.templateContainer.html(_html);
  723. } else {
  724. // new data
  725. if (loadState == 0)
  726. this.$element.prepend(_html);
  727. // paginted data
  728. else if (appendContent)
  729. this.$element.append(_html);
  730. else
  731. this.$element.html(_html);
  732. }
  733. this.options.onAssetsReRendered(this.$element, data, this.options.display_template.options, loadState);
  734. } else {
  735. this.options.templateContainer = this.$element.html(_html);
  736. if (typeof(this.options.onAssetsRendered) == 'function')
  737. this.options.onAssetsRendered(this.$element, data, this.options.display_template.options);
  738. }
  739. }
  740. };
  741. var methods = {
  742. init : function(options){
  743. if (options == undefined) options = {};
  744. return this.each(function () {
  745. var chute = $.extend({}, CHUTE);
  746. chute.init(this, options);
  747. chute.$element.data('callback', function(){
  748. if(chute.options.popup) {
  749. // do something
  750. } else {
  751. chute.$element.find(".close-chute-reveal-modal").click();
  752. }
  753. });
  754. if (options != undefined && typeof(options.success) == "function"){
  755. chute.$element.data('success-callback', options.success);
  756. }
  757. });
  758. },
  759. chooser : function(callback){
  760. var me = $(this);
  761. if (callback != undefined)
  762. me.data('success-callback', callback);
  763. me.find('.chute-browseButton').click();
  764. return me;
  765. },
  766. close : function(){
  767. var me = $(this);
  768. me.find('.close-chute-reveal-modal').click();
  769. return me;
  770. },
  771. success : function(files){
  772. var me = $(this);
  773. if (typeof(me.data('callback')) == 'function')
  774. me.data('callback')();
  775. if (typeof(me.data('success-callback')) == 'function')
  776. me.data('success-callback')(files);
  777. return me;
  778. },
  779. widget : function(){
  780. return $(this).find('.chute-popup iframe');
  781. }
  782. }
  783. $.fn.chute = function(method, callback){
  784. if (method == undefined || typeof(method) == 'object'){
  785. return methods.init.apply( this, arguments );
  786. } else if ( methods[method] ) {
  787. return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
  788. } else {
  789. $.error( 'Method ' + method + ' does not exist on jQuery.chute' );
  790. }
  791. };
  792. })(jQuery);
  793. (function($) {
  794. if ($chuteWidget != undefined){
  795. // add listsners just once
  796. $('.chute-widget:not(.chute-loaded)').chute();
  797. return;
  798. }
  799. $chuteWidget = 'chute';
  800. if (document.addEventListener){
  801. window.addEventListener('message', receiveMessage, false);
  802. } else {
  803. window.attachEvent('onmessage', receiveMessage);
  804. }
  805. function receiveMessage(event){
  806. receiveData(event.data);
  807. }
  808. function parseJSON(data){
  809. if (typeof(JSON) != 'undefined'){
  810. return JSON.parse(data);
  811. } else {
  812. return $.parseJSON(data);
  813. }
  814. }
  815. function receiveData(data){
  816. try {
  817. data = parseJSON(data);
  818. } catch(ex){
  819. data = data;
  820. }
  821. if (currentWidget && data.moderated != undefined){
  822. currentWidget.$element.chute('success', data);
  823. currentWidget.uploadComplete(data);
  824. }
  825. }
  826. chuteImageLoaded = function(image){
  827. $(image).chuteScaleImage({fade: Math.floor(Math.random()*1000)});
  828. }
  829. })(jQuery);
  830. /*********************************************
  831. mustache
  832. **********************************************/
  833. /*
  834. mustache.js — Logic-less templates in JavaScript
  835. See http://mustache.github.com/ for more info.
  836. */
  837. ChuteMustache = function() {
  838. var regexCache = {};
  839. var Renderer = function() {};
  840. Renderer.prototype = {
  841. otag: "{{",
  842. ctag: "}}",
  843. pragmas: {},
  844. buffer: [],
  845. pragmas_implemented: {
  846. "IMPLICIT-ITERATOR": true
  847. },
  848. context: {},
  849. render: function(template, context, partials, in_recursion) {
  850. // reset buffer & set context
  851. if(!in_recursion) {
  852. this.context = context;
  853. this.buffer = []; // TODO: make this non-lazy
  854. }
  855. // fail fast
  856. if(!this.includes("", template)) {
  857. if(in_recursion) {
  858. return template;
  859. } else {
  860. this.send(template);
  861. return;
  862. }
  863. }
  864. // get the pragmas together
  865. template = this.render_pragmas(template);
  866. // render the template
  867. var html = this.render_section(template, context, partials);
  868. // render_section did not find any sections, we still need to render the tags
  869. if (html === false) {
  870. html = this.render_tags(template, context, partials, in_recursion);
  871. }
  872. if (in_recursion) {
  873. return html;
  874. } else {
  875. this.sendLines(html);
  876. }
  877. },
  878. /*
  879. Sends parsed lines
  880. */
  881. send: function(line) {
  882. if(line !== "") {
  883. this.buffer.push(line);
  884. }
  885. },
  886. sendLines: function(text) {
  887. if (text) {
  888. var lines = text.split("\n");
  889. for (var i = 0; i < lines.length; i++) {
  890. this.send(lines[i]);
  891. }
  892. }
  893. },
  894. /*
  895. Looks for %PRAGMAS
  896. */
  897. render_pragmas: function(template) {
  898. // no pragmas
  899. if(!this.includes("%", template)) {
  900. return template;
  901. }
  902. var that = this;
  903. var regex = this.getCachedRegex("render_pragmas", function(otag, ctag) {
  904. return new RegExp(otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" + ctag, "g");
  905. });
  906. return template.replace(regex, function(match, pragma, options) {
  907. if(!that.pragmas_implemented[pragma]) {
  908. throw({message:
  909. "This implementation of mustache doesn't understand the '" +
  910. pragma + "' pragma"});
  911. }
  912. that.pragmas[pragma] = {};
  913. if(options) {
  914. var opts = options.split("=");
  915. that.pragmas[pragma][opts[0]] = opts[1];
  916. }
  917. return "";
  918. // ignore unknown pragmas silently
  919. });
  920. },
  921. /*
  922. Tries to find a partial in the curent scope and render it
  923. */
  924. render_partial: function(name, context, partials) {
  925. name = this.trim(name);
  926. if(!partials || partials[name] === undefined) {
  927. throw({message: "unknown_partial '" + name + "'"});
  928. }
  929. if(typeof(context[name]) != "object") {
  930. return this.render(partials[name], context, partials, true);
  931. }
  932. return this.render(partials[name], context[name], partials, true);
  933. },
  934. /*
  935. Renders inverted (^) and normal (#) sections
  936. */
  937. render_section: function(template, context, partials) {
  938. if(!this.includes("#", template) && !this.includes("^", template)) {
  939. // did not render anything, there were no sections
  940. return false;
  941. }
  942. var that = this;
  943. var regex = this.getCachedRegex("render_section", function(otag, ctag) {
  944. // This regex matches _the first_ section ({{#foo}}{{/foo}}), and captures the remainder
  945. return new RegExp(
  946. "^([\\s\\S]*?)" + // all the crap at the beginning that is not {{*}} ($1)
  947. otag + // {{
  948. "(\\^|\\#)\\s*(.+)\\s*" + // #foo (# == $2, foo == $3)
  949. ctag + // }}
  950. "\n*([\\s\\S]*?)" + // between the tag ($2). leading newlines are dropped
  951. otag + // {{
  952. "\\/\\s*\\3\\s*" + // /foo (backreference to the opening tag).
  953. ctag + // }}
  954. "\\s*([\\s\\S]*)$", // everything else in the string ($4). leading whitespace is dropped.
  955. "g");
  956. });
  957. // for each {{#foo}}{{/foo}} section do...
  958. return template.replace(regex, function(match, before, type, name, content, after) {
  959. // before contains only tags, no sections
  960. var renderedBefore = before ? that.render_tags(before, context, partials, true) : "",
  961. // after may contain both sections and tags, so use full rendering function
  962. renderedAfter = after ? that.render(after, context, partials, true) : "",
  963. // will be computed below
  964. renderedContent,
  965. value = that.find(name, context);
  966. if (type === "^") { // inverted section
  967. if (!value || that.is_array(value) && value.length === 0) {
  968. // false or empty list, render it
  969. renderedContent = that.render(content, context, partials, true);
  970. } else {
  971. renderedContent = "";
  972. }
  973. } else if (type === "#") { // normal section
  974. if (that.is_array(value)) { // Enumerable, Let's loop!
  975. renderedContent = that.map(value, function(row) {
  976. return that.render(content, that.create_context(row), partials, true);
  977. }).join("");
  978. } else if (that.is_object(value)) { // Object, Use it as subcontext!
  979. renderedContent = that.render(content, that.create_context(value),
  980. partials, true);
  981. } else if (typeof value === "function") {
  982. // higher order section
  983. renderedContent = value.call(context, content, function(text) {
  984. return that.render(text, context, partials, true);
  985. });
  986. } else if (value) { // boolean section
  987. renderedContent = that.render(content, context, partials, true);
  988. } else {
  989. renderedContent = "";
  990. }
  991. }
  992. return renderedBefore + renderedContent + renderedAfter;
  993. });
  994. },
  995. /*
  996. Replace {{foo}} and friends with values from our view
  997. */
  998. render_tags: function(template, context, partials, in_recursion) {
  999. // tit for tat
  1000. var that = this;
  1001. var new_regex = function() {
  1002. return that.getCachedRegex("render_tags", function(otag, ctag) {
  1003. return new RegExp(otag + "(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?" + ctag + "+", "g");
  1004. });
  1005. };
  1006. var regex = new_regex();
  1007. var tag_replace_callback = function(match, operator, name) {
  1008. switch(operator) {
  1009. case "!": // ignore comments
  1010. return "";
  1011. case "=": // set new delimiters, rebuild the replace regexp
  1012. that.set_delimiters(name);
  1013. regex = new_regex();
  1014. return "";
  1015. case ">": // render partial
  1016. return that.render_partial(name, context, partials);
  1017. case "{": // the triple mustache is unescaped
  1018. return that.find(name, context);
  1019. default: // escape the value
  1020. return that.escape(that.find(name, context));
  1021. }
  1022. };
  1023. var lines = template.split("\n");
  1024. for(var i = 0; i < lines.length; i++) {
  1025. lines[i] = lines[i].replace(regex, tag_replace_callback, this);
  1026. if(!in_recursion) {
  1027. this.send(lines[i]);
  1028. }
  1029. }
  1030. if(in_recursion) {
  1031. return lines.join("\n");
  1032. }
  1033. },
  1034. set_delimiters: function(delimiters) {
  1035. var dels = delimiters.split(" ");
  1036. this.otag = this.escape_regex(dels[0]);
  1037. this.ctag = this.escape_regex(dels[1]);
  1038. },
  1039. escape_regex: function(text) {
  1040. // thank you Simon Willison
  1041. if(!arguments.callee.sRE) {
  1042. var specials = [
  1043. '/', '.', '*', '+', '?', '|',
  1044. '(', ')', '[', ']', '{', '}', '\\'
  1045. ];
  1046. arguments.callee.sRE = new RegExp(
  1047. '(\\' + specials.join('|\\') + ')', 'g'
  1048. );
  1049. }
  1050. return text.replace(arguments.callee.sRE, '\\$1');
  1051. },
  1052. /*
  1053. find `name` in current `context`. That is find me a value
  1054. from the view object
  1055. */
  1056. find: function(name, context) {
  1057. name = this.trim(name);
  1058. // Checks whether a value is thruthy or false or 0
  1059. function is_kinda_truthy(bool) {
  1060. return bool === false || bool === 0 || bool;
  1061. }
  1062. var value;
  1063. // check for dot notation eg. foo.bar
  1064. if(name.match(/([a-z_]+)\./ig)){
  1065. var childValue = this.walk_context(name, context);
  1066. if(is_kinda_truthy(childValue)) {
  1067. value = childValue;
  1068. }
  1069. }
  1070. else{
  1071. if(is_kinda_truthy(context[name])) {
  1072. value = context[name];
  1073. } else if(is_kinda_truthy(this.context[name])) {
  1074. value = this.context[name];
  1075. }
  1076. }
  1077. if(typeof value === "function") {
  1078. return value.apply(context);
  1079. }
  1080. if(value !== undefined) {
  1081. return value;
  1082. }
  1083. // silently ignore unkown variables
  1084. return "";
  1085. },
  1086. walk_context: function(name, context){
  1087. var path = name.split('.');
  1088. // if the var doesn't exist in current context, check the top level context
  1089. var value_context = (context[path[0]] != undefined) ? context : this.context;
  1090. var value = value_context[path.shift()];
  1091. while(value != undefined && path.length > 0){
  1092. value_context = value;
  1093. value = value[path.shift()];
  1094. }
  1095. // if the value is a function, call it, binding the correct context
  1096. if(typeof value === "function") {
  1097. return value.apply(val

Large files files are truncated, but you can click here to view the full file