loft 0.1.2 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
data/bower.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "loft",
3
+ "version": "0.1.5",
4
+ "homepage": "https://github.com/slate-studio/loft",
5
+ "authors": [
6
+ "Slate Studio (http://www.slatestudio.com)"
7
+ ],
8
+ "license": "MIT",
9
+ "description": "Media assets manager for Character CMS.",
10
+ "main": "app/assets/stylesheets/_loft.scss, dist/loft.js, app/assets/images/loft/library@3x.png",
11
+ "keywords": [
12
+ "character",
13
+ "cms",
14
+ "gallery",
15
+ "pugin",
16
+ "images",
17
+ "files"
18
+ ],
19
+ "ignore": [
20
+ "**/.*",
21
+ "lib",
22
+ "docs",
23
+ "chr.gemspec",
24
+ "Gemfile",
25
+ "Gemfile.lock",
26
+ "Gruntfile.coffee",
27
+ "package.json",
28
+ "Rakefile"
29
+ ],
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/slate-studio/loft.git"
33
+ },
34
+ "dependencies": {
35
+ "bourbon": ">=4.0",
36
+ "normalize-scss": ">=3.0"
37
+ }
38
+ }
data/dist/loft.js ADDED
@@ -0,0 +1,603 @@
1
+ this.LoftGroupActions = (function() {
2
+ function LoftGroupActions(list, loft) {
3
+ this.list = list;
4
+ this.loft = loft;
5
+ this._render();
6
+ this._bind_checkboxes();
7
+ }
8
+
9
+ LoftGroupActions.prototype._render = function() {
10
+ this.$el = $("<div class='assets-group-actions' style='display:none;'></div>");
11
+ this.list.$header.append(this.$el);
12
+ this.$acceptBtn = $("<a href='#' class='accept'>Accept</a>");
13
+ this.$acceptBtn.on('click', (function(_this) {
14
+ return function(e) {
15
+ e.preventDefault();
16
+ return _this._accept_selected_items();
17
+ };
18
+ })(this));
19
+ this.$el.append(this.$acceptBtn);
20
+ this.$deleteBtn = $("<a href='#' class='delete'>Delete Selected</a>");
21
+ this.$deleteBtn.on('click', (function(_this) {
22
+ return function(e) {
23
+ e.preventDefault();
24
+ return _this._delete_selected_list_items();
25
+ };
26
+ })(this));
27
+ this.$el.append(this.$deleteBtn);
28
+ this.$unselectBtn = $("<a href='#' class='unselect'>Unselect</a>");
29
+ this.$unselectBtn.on('click', (function(_this) {
30
+ return function(e) {
31
+ e.preventDefault();
32
+ return _this._unselect_list_items();
33
+ };
34
+ })(this));
35
+ return this.$el.append(this.$unselectBtn);
36
+ };
37
+
38
+ LoftGroupActions.prototype._bind_checkboxes = function() {
39
+ return this.list.$el.on('click', '.asset .asset-checkbox input', (function(_this) {
40
+ return function(e) {
41
+ var selectedItems;
42
+ if (!_this.loft.selectMultipleAssets) {
43
+ _this._select_single_item($(e.target));
44
+ }
45
+ selectedItems = _this._selected_list_items();
46
+ if (selectedItems.length > 0) {
47
+ return _this._show();
48
+ } else {
49
+ return _this.hide();
50
+ }
51
+ };
52
+ })(this));
53
+ };
54
+
55
+ LoftGroupActions.prototype._select_single_item = function($checkbox) {
56
+ if ($checkbox.prop('checked')) {
57
+ this.list.$el.find('.asset .asset-checkbox input:checked').prop('checked', false);
58
+ return $checkbox.prop('checked', true);
59
+ }
60
+ };
61
+
62
+ LoftGroupActions.prototype._selected_list_items = function() {
63
+ return $.map(this.list.$el.find('.asset .asset-checkbox input:checked'), function(checkbox) {
64
+ return $(checkbox).parent().parent();
65
+ });
66
+ };
67
+
68
+ LoftGroupActions.prototype._unselect_list_items = function() {
69
+ this.list.$el.find('.asset .asset-checkbox input').prop('checked', false);
70
+ return this.hide();
71
+ };
72
+
73
+ LoftGroupActions.prototype._delete_selected_list_items = function() {
74
+ var $item, $selectedItems, filesToRemoveCounter, i, len, objectId;
75
+ if (confirm("Are you sure?")) {
76
+ $selectedItems = this._selected_list_items();
77
+ filesToRemoveCounter = $selectedItems.length;
78
+ for (i = 0, len = $selectedItems.length; i < len; i++) {
79
+ $item = $selectedItems[i];
80
+ objectId = $item.attr('data-id');
81
+ this.list.config.arrayStore.remove(objectId, {
82
+ onSuccess: (function(_this) {
83
+ return function() {};
84
+ })(this),
85
+ onError: (function(_this) {
86
+ return function() {};
87
+ })(this)
88
+ });
89
+ }
90
+ return this.hide();
91
+ }
92
+ };
93
+
94
+ LoftGroupActions.prototype._accept_selected_items = function() {
95
+ var $item, $selectedItems, i, len, object, objectId, objects;
96
+ $selectedItems = this._selected_list_items();
97
+ objects = [];
98
+ for (i = 0, len = $selectedItems.length; i < len; i++) {
99
+ $item = $selectedItems[i];
100
+ objectId = $item.attr('data-id');
101
+ object = this.list.config.arrayStore.get(objectId);
102
+ objects.push(object);
103
+ }
104
+ this.loft.onAcceptCallback(objects);
105
+ return this.loft.closeModal();
106
+ };
107
+
108
+ LoftGroupActions.prototype._show = function() {
109
+ return this.$el.show();
110
+ };
111
+
112
+ LoftGroupActions.prototype.hide = function() {
113
+ return this.$el.hide();
114
+ };
115
+
116
+ return LoftGroupActions;
117
+
118
+ })();
119
+
120
+ var 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; },
121
+ hasProp = {}.hasOwnProperty;
122
+
123
+ this.LoftAssetItem = (function(superClass) {
124
+ extend(LoftAssetItem, superClass);
125
+
126
+ function LoftAssetItem(module, path, object1, config) {
127
+ this.module = module;
128
+ this.path = path;
129
+ this.object = object1;
130
+ this.config = config;
131
+ this.$el = $("<div class='item asset asset-" + this.object.type + "' data-id='" + this.object._id + "'></div>");
132
+ this.render();
133
+ }
134
+
135
+ LoftAssetItem.prototype._bind_name_input = function() {
136
+ this.$nameInput.on('blur', (function(_this) {
137
+ return function(e) {
138
+ return _this._update_name_if_changed();
139
+ };
140
+ })(this));
141
+ return this.$nameInput.on('keyup', (function(_this) {
142
+ return function(e) {
143
+ if (e.keyCode === 13) {
144
+ $(e.target).blur();
145
+ }
146
+ if (e.keyCode === 27) {
147
+ return _this._cancel_name_change();
148
+ }
149
+ };
150
+ })(this));
151
+ };
152
+
153
+ LoftAssetItem.prototype._edit_name = function(e) {
154
+ this.$el.addClass('edit-name');
155
+ return this.$nameInput.focus().select();
156
+ };
157
+
158
+ LoftAssetItem.prototype._cancel_name_change = function() {
159
+ var name;
160
+ this.$el.removeClass('edit-name');
161
+ name = this.$title.html();
162
+ return this.$nameInput.val(name);
163
+ };
164
+
165
+ LoftAssetItem.prototype._update_name_if_changed = function() {
166
+ var name;
167
+ this.$el.removeClass('edit-name');
168
+ name = this.$nameInput.val();
169
+ if (name === this.$title.html()) {
170
+ return;
171
+ }
172
+ this.$title.html(name);
173
+ return this.config.arrayStore.update(this.object._id, {
174
+ '[name]': name
175
+ }, {
176
+ onSuccess: (function(_this) {
177
+ return function(object) {};
178
+ })(this),
179
+ onError: (function(_this) {
180
+ return function(errors) {};
181
+ })(this)
182
+ });
183
+ };
184
+
185
+ LoftAssetItem.prototype.render = function() {
186
+ var name;
187
+ this.$el.html('').removeClass('item-folder has-subtitle has-thumbnail');
188
+ this._render_title();
189
+ this._render_subtitle();
190
+ this.$link = $("<a class='asset-icon' href='" + this.object.file.url + "' target='_blank'></a>");
191
+ this.$el.prepend(this.$link);
192
+ if (this.object.type === 'image' && this.object.grid_item_thumbnail !== '') {
193
+ this.$thumbnailSmall = $("<img class='asset-thumbnail-small' src='" + this.object.item_thumbnail.small + "' />");
194
+ this.$thumbnailMedium = $("<img class='asset-thumbnail-medium' src='" + this.object.item_thumbnail.medium + "' />");
195
+ this.$link.append(this.$thumbnailSmall);
196
+ this.$link.append(this.$thumbnailMedium);
197
+ }
198
+ this.$checkbox = $("<div class='asset-checkbox'></div>");
199
+ this.$checkboxInput = $("<input type='checkbox' />");
200
+ this.$checkbox.append(this.$checkboxInput);
201
+ this.$el.prepend(this.$checkbox);
202
+ name = this.$title.text();
203
+ this.$name = $("<div class='asset-name'></div>");
204
+ this.$nameInput = $("<input type='text' value='" + name + "' />");
205
+ this.$name.append(this.$nameInput);
206
+ this.$title.before(this.$name);
207
+ this._bind_name_input();
208
+ return this.$title.on('click', (function(_this) {
209
+ return function(e) {
210
+ return _this._edit_name(e);
211
+ };
212
+ })(this));
213
+ };
214
+
215
+ return LoftAssetItem;
216
+
217
+ })(Item);
218
+
219
+ this.Loft = (function() {
220
+ function Loft(title, resource, resourcePath, arrayStoreClass, arrayStoreConfig) {
221
+ var moduleConfig;
222
+ this.arrayStoreClass = arrayStoreClass;
223
+ this.arrayStoreConfig = arrayStoreConfig;
224
+ this.module = {};
225
+ this.store = {};
226
+ if (this.arrayStoreClass == null) {
227
+ this.arrayStoreClass = RailsArrayStore;
228
+ }
229
+ if (this.arrayStoreConfig == null) {
230
+ this.arrayStoreConfig = {
231
+ resource: resource,
232
+ path: resourcePath,
233
+ sortBy: 'created_at',
234
+ sortReverse: true,
235
+ searchable: true
236
+ };
237
+ }
238
+ this._uploadsCounter = 0;
239
+ moduleConfig = {
240
+ title: title,
241
+ showNestedListsAside: true,
242
+ items: {
243
+ loft_all: this._nested_list_config('All'),
244
+ loft_images: this._nested_list_config('Images', 'image'),
245
+ loft_text: this._nested_list_config('Text', 'text'),
246
+ loft_archives: this._nested_list_config('Archives', 'archive'),
247
+ loft_audio: this._nested_list_config('Audio', 'audio'),
248
+ loft_video: this._nested_list_config('Video', 'video'),
249
+ loft_other: this._nested_list_config('Other', 'other')
250
+ },
251
+ onModuleInit: (function(_this) {
252
+ return function(module) {
253
+ return _this._initialize_module(module);
254
+ };
255
+ })(this)
256
+ };
257
+ return moduleConfig;
258
+ }
259
+
260
+ Loft.prototype._initialize_module = function(module) {
261
+ this.module = module;
262
+ this.store = this.module.nestedLists.loft_all.config.arrayStore;
263
+ this.module.showModal = (function(_this) {
264
+ return function(assetType, selectMultipleAssets, callback) {
265
+ return _this.showModal(assetType, selectMultipleAssets, callback);
266
+ };
267
+ })(this);
268
+ this.selectMultipleAssets = true;
269
+ this.module.rootList.$modalCloseBtn = $("<a href='#' class='modal-close'>Cancel</a>");
270
+ this.module.rootList.$header.prepend(this.module.rootList.$modalCloseBtn);
271
+ this.module.rootList.$modalCloseBtn.on('click', (function(_this) {
272
+ return function(e) {
273
+ e.preventDefault();
274
+ return _this.closeModal();
275
+ };
276
+ })(this));
277
+ this.module.rootList.$items.on('click', 'a', (function(_this) {
278
+ return function(e) {
279
+ var $item, listName;
280
+ if (_this.module.$el.hasClass('module-modal')) {
281
+ e.preventDefault();
282
+ $item = $(e.currentTarget);
283
+ listName = $item.attr('href').split('/')[2];
284
+ _this.module.activeList.hide();
285
+ _this.module.showList(listName);
286
+ _this.module.activeList.updateItems();
287
+ $item.parent().children('.active').removeClass('active');
288
+ return $item.addClass('active');
289
+ }
290
+ };
291
+ })(this));
292
+ if (!chr.isMobile()) {
293
+ return this.module.$el.addClass('grid-mode');
294
+ }
295
+ };
296
+
297
+ Loft.prototype._nested_list_config = function(moduleName, assetType) {
298
+ var config, storeConfig;
299
+ storeConfig = {};
300
+ $.extend(storeConfig, this.arrayStoreConfig);
301
+ if (assetType) {
302
+ $.extend(storeConfig, {
303
+ urlParams: {
304
+ by_type: assetType
305
+ }
306
+ });
307
+ }
308
+ config = {
309
+ title: moduleName,
310
+ itemTitleField: 'name',
311
+ itemSubtitleField: 'created_ago',
312
+ showWithParent: true,
313
+ itemClass: LoftAssetItem,
314
+ arrayStore: new this.arrayStoreClass(storeConfig),
315
+ onListInit: (function(_this) {
316
+ return function(list) {
317
+ return _this._inititialize_list(list);
318
+ };
319
+ })(this),
320
+ onListShow: (function(_this) {
321
+ return function(list) {
322
+ return _this._clear_assets_selection();
323
+ };
324
+ })(this)
325
+ };
326
+ return config;
327
+ };
328
+
329
+ Loft.prototype._inititialize_list = function(list) {
330
+ list.$uploadInput = $("<input class='asset-upload' type='file' multiple='multiple' />");
331
+ list.$search.before(list.$uploadInput);
332
+ list.$uploadInput.on('change', (function(_this) {
333
+ return function(e) {
334
+ var file, files, i, len, results;
335
+ files = e.target.files;
336
+ if (files.length > 0) {
337
+ results = [];
338
+ for (i = 0, len = files.length; i < len; i++) {
339
+ file = files[i];
340
+ results.push(_this._upload(file, list));
341
+ }
342
+ return results;
343
+ }
344
+ };
345
+ })(this));
346
+ list.groupActions = new LoftGroupActions(list, this);
347
+ list.$switchMode = $("<a class='assets-switch-mode' href='#'></a>");
348
+ list.$backBtn.after(list.$switchMode);
349
+ list.$switchMode.on('click', (function(_this) {
350
+ return function(e) {
351
+ e.preventDefault();
352
+ return _this.module.$el.toggleClass('grid-mode');
353
+ };
354
+ })(this));
355
+ return list.$header.on('click', '.back', (function(_this) {
356
+ return function(e) {
357
+ if (_this.module.$el.hasClass('module-modal')) {
358
+ e.preventDefault();
359
+ return _this.module.showList();
360
+ }
361
+ };
362
+ })(this));
363
+ };
364
+
365
+ Loft.prototype._upload = function(file, list) {
366
+ var obj;
367
+ obj = {};
368
+ obj["__FILE__[file]"] = file;
369
+ this._start_file_upload();
370
+ return this.store.push(obj, {
371
+ onSuccess: (function(_this) {
372
+ return function(object) {
373
+ return _this._finish_file_upload(list);
374
+ };
375
+ })(this),
376
+ onError: (function(_this) {
377
+ return function(errors) {
378
+ _this._finish_file_upload(list);
379
+ return chr.showError('Can\'t upload file.');
380
+ };
381
+ })(this)
382
+ });
383
+ };
384
+
385
+ Loft.prototype._start_file_upload = function() {
386
+ this._uploadsCounter += 1;
387
+ return this.module.$el.addClass('assets-uploading');
388
+ };
389
+
390
+ Loft.prototype._finish_file_upload = function(list) {
391
+ this._uploadsCounter -= 1;
392
+ if (this._uploadsCounter === 0) {
393
+ this.module.$el.removeClass('assets-uploading');
394
+ if (this.module.activeList.name !== 'loft_all') {
395
+ return this.module.activeList.updateItems();
396
+ }
397
+ }
398
+ };
399
+
400
+ Loft.prototype._clear_assets_selection = function() {
401
+ var list, name, ref, results;
402
+ ref = this.module.nestedLists;
403
+ results = [];
404
+ for (name in ref) {
405
+ list = ref[name];
406
+ list.groupActions.hide();
407
+ results.push(list.$items.find('.asset-checkbox').prop('checked', false));
408
+ }
409
+ return results;
410
+ };
411
+
412
+ Loft.prototype.closeModal = function() {
413
+ this.selectMultipleAssets = true;
414
+ this._clear_assets_selection();
415
+ this.module.$el.removeClass('module-modal');
416
+ return this.module.hide();
417
+ };
418
+
419
+ Loft.prototype.showModal = function(assetType, selectMultipleAssets1, onAcceptCallback) {
420
+ if (assetType == null) {
421
+ assetType = 'all';
422
+ }
423
+ this.selectMultipleAssets = selectMultipleAssets1 != null ? selectMultipleAssets1 : false;
424
+ this.onAcceptCallback = onAcceptCallback != null ? onAcceptCallback : $.noop;
425
+ this.module.$el.addClass('module-modal');
426
+ this.module.show();
427
+ this.module.showList("loft_" + assetType);
428
+ this.module.activeList.updateItems();
429
+ this.module.rootList.$items.children().removeClass('active');
430
+ return this.module.rootList.$items.children("[href='#/loft/loft_" + assetType + "']").addClass('active');
431
+ };
432
+
433
+ return Loft;
434
+
435
+ })();
436
+
437
+ if (!this.RedactorPlugins) {
438
+ this.RedactorPlugins = {};
439
+ }
440
+
441
+ RedactorPlugins.loft = function() {
442
+ var methods;
443
+ methods = {
444
+ init: function() {
445
+ var fileButton, imageButton;
446
+ imageButton = this.button.add('image', 'Insert Image');
447
+ this.button.addCallback(imageButton, this.loft.showImagesModal);
448
+ fileButton = this.button.add('file', 'Insert File');
449
+ return this.button.addCallback(fileButton, this.loft.showAllModal);
450
+ },
451
+ showImagesModal: function() {
452
+ return chr.modules.loft.showModal('images', true, (function(_this) {
453
+ return function(objects) {
454
+ return _this.loft.insertImages(objects);
455
+ };
456
+ })(this));
457
+ },
458
+ showAllModal: function() {
459
+ var multipleAssets;
460
+ multipleAssets = this.selection.getText() === '';
461
+ return chr.modules.loft.showModal('all', multipleAssets, (function(_this) {
462
+ return function(objects) {
463
+ return _this.loft.insertFiles(objects);
464
+ };
465
+ })(this));
466
+ },
467
+ insertFiles: function(objects) {
468
+ var asset, html, i, len, links, selectedText;
469
+ if (objects.length > 0) {
470
+ selectedText = this.selection.getText();
471
+ if (selectedText !== '') {
472
+ asset = objects[0];
473
+ html = "<a href='" + asset.file.url + "' target='_blank'>" + selectedText + "</a>";
474
+ } else {
475
+ links = [];
476
+ for (i = 0, len = objects.length; i < len; i++) {
477
+ asset = objects[i];
478
+ links.push("<a href='" + asset.file.url + "' target='_blank'>" + asset.name + "</a>");
479
+ }
480
+ html = links.join('<br>');
481
+ }
482
+ return this.insert.html(html, false);
483
+ }
484
+ },
485
+ insertImages: function(objects) {
486
+ var asset, html, i, images, len;
487
+ if (objects.length > 0) {
488
+ images = [];
489
+ for (i = 0, len = objects.length; i < len; i++) {
490
+ asset = objects[i];
491
+ images.push("<img src='" + asset.file.url + "' alt='" + asset.name + "' />");
492
+ }
493
+ html = images.join('<br>');
494
+ return this.insert.html(html, false);
495
+ }
496
+ }
497
+ };
498
+ return methods;
499
+ };
500
+
501
+
502
+
503
+ var 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; },
504
+ hasProp = {}.hasOwnProperty;
505
+
506
+ this.InputLoftImage = (function(superClass) {
507
+ extend(InputLoftImage, superClass);
508
+
509
+ function InputLoftImage() {
510
+ return InputLoftImage.__super__.constructor.apply(this, arguments);
511
+ }
512
+
513
+ InputLoftImage.prototype._add_input = function() {
514
+ var base;
515
+ if ((base = this.config).placeholder == null) {
516
+ base.placeholder = 'Image url';
517
+ }
518
+ this.$input = $("<input type='string' name='" + this.name + "' value='" + (this._safe_value()) + "' id='" + this.name + "' />");
519
+ this.$el.append(this.$input);
520
+ this.$input.on('change', (function(_this) {
521
+ return function(e) {
522
+ return _this.updateValue($(e.target).val());
523
+ };
524
+ })(this));
525
+ this._add_image();
526
+ this._add_choose_button();
527
+ this._add_remove_button();
528
+ return this._update_input_class();
529
+ };
530
+
531
+ InputLoftImage.prototype._add_image = function() {
532
+ this.$image = $("<a href='' target='_blank' class='image'><img src='' /></a>");
533
+ this.$el.append(this.$image);
534
+ return this._update_image();
535
+ };
536
+
537
+ InputLoftImage.prototype._add_choose_button = function() {
538
+ this.$chooseBtn = $("<a href='#' class='choose'></a><br/>");
539
+ this.$el.append(this.$chooseBtn);
540
+ this._update_choose_button_title();
541
+ return this.$chooseBtn.on('click', (function(_this) {
542
+ return function(e) {
543
+ e.preventDefault();
544
+ return chr.modules.loft.showModal('images', false, function(objects) {
545
+ var asset;
546
+ asset = objects[0];
547
+ return _this.updateValue(asset.file.url);
548
+ });
549
+ };
550
+ })(this));
551
+ };
552
+
553
+ InputLoftImage.prototype._add_remove_button = function() {
554
+ this.$removeBtn = $("<a href='#' class='remove'>Remove</a>");
555
+ this.$el.append(this.$removeBtn);
556
+ return this.$removeBtn.on('click', (function(_this) {
557
+ return function(e) {
558
+ e.preventDefault();
559
+ if (confirm('Are you sure?')) {
560
+ return _this.updateValue('');
561
+ }
562
+ };
563
+ })(this));
564
+ };
565
+
566
+ InputLoftImage.prototype._update_image = function() {
567
+ var url;
568
+ url = this.value;
569
+ this.$image.attr('href', this.value).children().attr('src', this.value);
570
+ if (this.value === '') {
571
+ return this.$image.hide();
572
+ } else {
573
+ return this.$image.show();
574
+ }
575
+ };
576
+
577
+ InputLoftImage.prototype._update_choose_button_title = function() {
578
+ var title;
579
+ title = this.value === '' ? 'Choose or upload' : 'Choose other or upload';
580
+ return this.$chooseBtn.html(title);
581
+ };
582
+
583
+ InputLoftImage.prototype._update_input_class = function() {
584
+ if (this.value === '') {
585
+ return this.$el.removeClass('has-value');
586
+ } else {
587
+ return this.$el.addClass('has-value');
588
+ }
589
+ };
590
+
591
+ InputLoftImage.prototype.updateValue = function(value) {
592
+ this.value = value;
593
+ this.$input.val(this.value);
594
+ this._update_image();
595
+ this._update_choose_button_title();
596
+ return this._update_input_class();
597
+ };
598
+
599
+ return InputLoftImage;
600
+
601
+ })(InputString);
602
+
603
+ chr.formInputs['loft-image'] = InputLoftImage;