diff --git a/public/language/en_GB/topic.json b/public/language/en_GB/topic.json index 85a923afbb..fedb625fd3 100644 --- a/public/language/en_GB/topic.json +++ b/public/language/en_GB/topic.json @@ -72,5 +72,12 @@ "composer.discard": "Discard", "composer.submit": "Submit", "composer.replying_to": "Replying to", - "composer.new_topic": "New Topic" + "composer.new_topic": "New Topic", + + "composer.uploading": "uploading...", + "composer.thumb_url_label": "Paste a topic thumbnail URL", + "composer.thumb_title": "Add a thumbnail to this topic", + "composer.thumb_url_placeholder": "http://example.com/thumb.png", + "composer.thumb_file_label": "Or upload a file", + "composer.thumb_remove": "Clear fields" } diff --git a/public/src/modules/composer.js b/public/src/modules/composer.js index 866f8ecdf6..7d5c98548e 100644 --- a/public/src/modules/composer.js +++ b/public/src/modules/composer.js @@ -4,6 +4,11 @@ define(['taskbar'], function(taskbar) { posts: {} }; + function resetInputFile($el) { + $el.wrap('
').closest('form').get(0).reset(); + $el.unwrap(); + } + function allowed() { if(!(parseInt(app.uid, 10) > 0 || config.allowGuestPosting)) { app.alert({ @@ -21,16 +26,263 @@ define(['taskbar'], function(taskbar) { return true; } + function push(post) { + var uuid = utils.generateUUID(); + + translator.translate('[[topic:composer.new_topic]]', function(newTopicStr) { + taskbar.push('composer', uuid, { + title: post.title ? post.title : newTopicStr, + icon: post.picture + }); + }); + + composer.posts[uuid] = post; + composer.posts[uuid].uploadsInProgress = []; + + composer.load(uuid); + } + + //http://stackoverflow.com/questions/14441456/how-to-detect-which-device-view-youre-on-using-twitter-bootstrap-api + function findBootstrapEnvironment() { + var envs = ['xs', 'sm', 'md', 'lg']; + + $el = $('
'); + $el.appendTo($('body')); + + for (var i = envs.length - 1; i >= 0; i--) { + var env = envs[i]; + + $el.addClass('hidden-'+env); + if ($el.is(':hidden')) { + $el.remove(); + return env; + } + } + } + + function composerAlert(title, message) { + $('.action-bar button').removeAttr('disabled'); + app.alert({ + type: 'danger', + timeout: 2000, + title: title, + message: message, + alert_id: 'post_error' + }); + } + + function initializeDragAndDrop(post_uuid) { + + if(jQuery.event.props.indexOf('dataTransfer') === -1) { + jQuery.event.props.push('dataTransfer'); + } + + var draggingDocument = false; + + var postContainer = $('#cmp-uuid-' + post_uuid), + fileForm = postContainer.find('#fileForm'), + drop = postContainer.find('.imagedrop'), + tabContent = postContainer.find('.tab-content'), + textarea = postContainer.find('textarea'); + + $(document).off('dragstart').on('dragstart', function(e) { + draggingDocument = true; + }).off('dragend').on('dragend', function(e) { + draggingDocument = false; + }); + + textarea.on('dragenter', function(e) { + if(draggingDocument) { + return; + } + drop.css('top', tabContent.position().top + 'px'); + drop.css('height', textarea.height()); + drop.css('line-height', textarea.height() + 'px'); + drop.show(); + + drop.on('dragleave', function(ev) { + drop.hide(); + drop.off('dragleave'); + }); + }); + + function cancel(e) { + e.preventDefault(); + return false; + } + + drop.on('dragover', cancel); + drop.on('dragenter', cancel); + + drop.on('drop', function(e) { + e.preventDefault(); + var dt = e.dataTransfer, + files = dt.files; + + if(files.length) { + var fd = new FormData(); + for (var i = 0, file; file = dt.files[i]; i++) { + fd.append('files[]', file, file.name); + } + + fileForm[0].reset(); + uploadContentFiles({files: files, post_uuid: post_uuid, route: '/api/post/upload', formData: fd}); + } + + drop.hide(); + return false; + }); + + $(window).off('paste').on('paste', function(event) { + + var items = (event.clipboardData || event.originalEvent.clipboardData).items; + + if(items && items.length) { + + var blob = items[0].getAsFile(); + if(blob) { + blob.name = 'upload-'+ utils.generateUUID(); + + var fd = new FormData(); + fd.append('files[]', blob, blob.name); + + fileForm[0].reset(); + uploadContentFiles({files: [blob], post_uuid: post_uuid, route: '/api/post/upload', formData: fd}); + } + } + }); + } + + function uploadContentFiles(params) { + var files = params.files, + post_uuid = params.post_uuid, + route = params.route, + formData = params.formData, + callback = params.callback, + postContainer = $('#cmp-uuid-' + post_uuid), + textarea = postContainer.find('textarea'), + text = textarea.val(), + uploadForm = postContainer.find('#fileForm'); + + uploadForm.attr('action', route); + + for(var i = 0; i < files.length; ++i) { + var isImage = files[i].type.match('image.*'); + text += (isImage ? '!' : '') + '[' + files[i].name + '](uploading...) '; + + if(files[i].size > parseInt(config.maximumFileSize, 10) * 1024) { + uploadForm[0].reset(); + return composerAlert('File too big', 'Maximum allowed file size is ' + config.maximumFileSize + 'kbs'); + } + } + + textarea.val(text); + + uploadForm.off('submit').submit(function() { + + $(this).find('#postUploadCsrf').val($('#csrf_token').val()); + if(formData) { + formData.append('_csrf', $('#csrf_token').val()); + } + + composer.posts[post_uuid].uploadsInProgress.push(1); + + $(this).ajaxSubmit({ + resetForm: true, + clearForm: true, + formData: formData, + error: function(xhr) { + app.alertError('Error uploading file! ' + xhr.status); + composer.posts[post_uuid].uploadsInProgress.pop(); + if (typeof callback == 'function') + callback(xhr); + }, + uploadProgress: function(event, position, total, percent) { + var current = textarea.val(); + for(var i=0; i 0) { translator.translate('[[topic:composer.replying_to]]: ' + postData.title, function(newTitle) { @@ -139,13 +393,44 @@ define(['taskbar'], function(taskbar) { titleEl.prop('disabled', false); } }); + toggleThumbEls(); } else { titleEl.val(postData.title); titleEl.prop('disabled', false); + toggleThumbEls(); } bodyEl.val(postData.body); + thumbToggleBtnEl.on('click', function() { + var container = postContainer.find('.topic-thumb-container'); + if (container.hasClass('hide')) { + container.removeClass('hide'); + } else { + container.addClass('hide'); + } + }); + + postContainer.on('click', '.topic-thumb-clear-btn', function(e) { + postContainer.find('input#topic-thumb-url').val('').trigger('change'); + resetInputFile(postContainer.find('input#topic-thumb-file')); + $(this).addClass('hide'); + e.preventDefault(); + }); + + postContainer.on('paste change keypress', 'input#topic-thumb-url', function(e) { + var urlEl = $(this); + setTimeout(function(){ + var url = urlEl.val(); + if (url) { + postContainer.find('.topic-thumb-clear-btn').removeClass('hide'); + } else { + resetInputFile(postContainer.find('input#topic-thumb-file')); + postContainer.find('.topic-thumb-clear-btn').addClass('hide'); + } + postContainer.find('img.topic-thumb-preview').attr('src', url); + }, 100); + }); postContainer.on('change', 'input, textarea', function() { composer.posts[post_uuid].modified = true; @@ -236,7 +521,18 @@ define(['taskbar'], function(taskbar) { $('#files').on('change', function(e) { var files = e.target.files; if(files) { - uploadSubmit(files, post_uuid, '/api/post/upload'); + uploadContentFiles({files: files, post_uuid: post_uuid, route: '/api/post/upload'}); + } + }); + + postContainer.find('#topic-thumb-file').on('change', function(e) { + var files = e.target.files; + if(files) { + var fd = new FormData(); + for (var i = 0, file; file = files[i]; i++) { + fd.append('files[]', file, file.name); + } + uploadTopicThumb({files: files, post_uuid: post_uuid, route: '/api/topic/thumb/upload', formData: fd}); } }); @@ -337,24 +633,6 @@ define(['taskbar'], function(taskbar) { }); } - //http://stackoverflow.com/questions/14441456/how-to-detect-which-device-view-youre-on-using-twitter-bootstrap-api - function findBootstrapEnvironment() { - var envs = ['xs', 'sm', 'md', 'lg']; - - $el = $('
'); - $el.appendTo($('body')); - - for (var i = envs.length - 1; i >= 0; i--) { - var env = envs[i]; - - $el.addClass('hidden-'+env); - if ($el.is(':hidden')) { - $el.remove(); - return env; - } - } - } - composer.activateReposition = function(post_uuid) { if(composer.active && composer.active !== post_uuid) { @@ -395,7 +673,7 @@ define(['taskbar'], function(taskbar) { $('body').css({'margin-bottom': postContainer.css('height')}); composer.focusElements(post_uuid); - } + }; composer.focusElements = function(post_uuid) { var postContainer = $('#cmp-uuid-' + post_uuid), @@ -410,15 +688,18 @@ define(['taskbar'], function(taskbar) { } else if (parseInt(postData.cid) > 0) { titleEl.focus(); } - } + }; + composer.post = function(post_uuid) { var postData = composer.posts[post_uuid], postContainer = $('#cmp-uuid-' + post_uuid), titleEl = postContainer.find('.title'), - bodyEl = postContainer.find('textarea'); + bodyEl = postContainer.find('textarea'), + thumbEl = postContainer.find('input#topic-thumb-url'); titleEl.val(titleEl.val().trim()); bodyEl.val(bodyEl.val().trim()); + thumbEl.val(thumbEl.val().trim()); var checkTitle = parseInt(postData.cid, 10) || parseInt(postData.pid, 10); @@ -434,20 +715,22 @@ define(['taskbar'], function(taskbar) { if (parseInt(postData.cid, 10) > 0) { socket.emit('topics.post', { - 'title' : titleEl.val(), - 'content' : bodyEl.val(), - 'category_id' : postData.cid + title: titleEl.val(), + content: bodyEl.val(), + topic_thumb: thumbEl.val(), + category_id: postData.cid }, done); } else if (parseInt(postData.tid, 10) > 0) { socket.emit('posts.reply', { - 'topic_id' : postData.tid, - 'content' : bodyEl.val() + topic_id: postData.tid, + content: bodyEl.val() }, done); } else if (parseInt(postData.pid, 10) > 0) { socket.emit('posts.edit', { pid: postData.pid, content: bodyEl.val(), - title: titleEl.val() + title: titleEl.val(), + topic_thumb: thumbEl.val() }, done); } @@ -457,18 +740,7 @@ define(['taskbar'], function(taskbar) { composer.discard(post_uuid); } } - } - - function composerAlert(title, message) { - $('.action-bar button').removeAttr('disabled'); - app.alert({ - type: 'danger', - timeout: 2000, - title: title, - message: message, - alert_id: 'post_error' - }); - } + }; composer.discard = function(post_uuid) { if (composer.posts[post_uuid]) { @@ -479,164 +751,14 @@ define(['taskbar'], function(taskbar) { $('body').css({'margin-bottom': 0}); $('.action-bar button').removeAttr('disabled'); } - } + }; composer.minimize = function(post_uuid) { var postContainer = $('#cmp-uuid-' + post_uuid); postContainer.css('visibility', 'hidden'); composer.active = undefined; taskbar.minimize('composer', post_uuid); - } - - function initializeDragAndDrop(post_uuid) { - - if(jQuery.event.props.indexOf('dataTransfer') === -1) { - jQuery.event.props.push('dataTransfer'); - } - - var draggingDocument = false; - - var postContainer = $('#cmp-uuid-' + post_uuid), - fileForm = postContainer.find('#fileForm'); - drop = postContainer.find('.imagedrop'), - tabContent = postContainer.find('.tab-content'), - textarea = postContainer.find('textarea'); - - $(document).off('dragstart').on('dragstart', function(e) { - draggingDocument = true; - }).off('dragend').on('dragend', function(e) { - draggingDocument = false; - }); - - textarea.on('dragenter', function(e) { - if(draggingDocument) { - return; - } - drop.css('top', tabContent.position().top + 'px'); - drop.css('height', textarea.height()); - drop.css('line-height', textarea.height() + 'px'); - drop.show(); - - drop.on('dragleave', function(ev) { - drop.hide(); - drop.off('dragleave'); - }); - }); - - function cancel(e) { - e.preventDefault(); - return false; - } - - drop.on('dragover', cancel); - drop.on('dragenter', cancel); - - drop.on('drop', function(e) { - e.preventDefault(); - var dt = e.dataTransfer, - files = dt.files; - - if(files.length) { - var fd = new FormData(); - for (var i = 0, file; file = dt.files[i]; i++) { - fd.append('files[]', file, file.name); - } - - fileForm[0].reset(); - uploadSubmit(files, post_uuid, '/api/post/upload', fd); - } - - drop.hide(); - return false; - }); - - $(window).off('paste').on('paste', function(event) { - - var items = (event.clipboardData || event.originalEvent.clipboardData).items; - - if(items && items.length) { - - var blob = items[0].getAsFile(); - if(blob) { - blob.name = 'upload-'+ utils.generateUUID(); - - var fd = new FormData(); - fd.append('files[]', blob, blob.name); - - fileForm[0].reset(); - uploadSubmit([blob], post_uuid, '/api/post/upload', fd); - } - } - }); - } - - function uploadSubmit(files, post_uuid, route, formData, callback) { - var postContainer = $('#cmp-uuid-' + post_uuid), - textarea = postContainer.find('textarea'), - text = textarea.val(), - uploadForm = postContainer.find('#fileForm'); - - uploadForm.attr('action', route); - - for(var i=0; i parseInt(config.maximumFileSize, 10) * 1024) { - uploadForm[0].reset(); - return composerAlert('File too big', 'Maximum allowed file size is ' + config.maximumFileSize + 'kbs'); - } - } - - textarea.val(text); - - uploadForm.off('submit').submit(function() { - - $(this).find('#postUploadCsrf').val($('#csrf_token').val()); - if(formData) { - formData.append('_csrf', $('#csrf_token').val()); - } - - composer.posts[post_uuid].uploadsInProgress.push(1); - - $(this).ajaxSubmit({ - resetForm: true, - clearForm: true, - formData: formData, - error: function(xhr) { - app.alertError('Error uploading file! ' + xhr.status); - composer.posts[post_uuid].uploadsInProgress.pop(); - }, - - uploadProgress: function(event, position, total, percent) { - var current = textarea.val(); - for(var i=0; i Allow guests to search without logging in
+
+ +