summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2013-04-03 05:52:51 -0400
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2013-04-03 05:52:51 -0400
commit580dce30624e7af950159e3f74f9181506b57a5d (patch)
tree3d6c188bfb3e96aa7f85cc02aead734fe5d36161
parent38493ea737e25c37f806004142c259dc89bfe269 (diff)
downloadaskbot-580dce30624e7af950159e3f74f9181506b57a5d.tar.gz
askbot-580dce30624e7af950159e3f74f9181506b57a5d.tar.bz2
askbot-580dce30624e7af950159e3f74f9181506b57a5d.zip
improved image and file upload menues
-rw-r--r--askbot/media/js/tinymce/plugins/askbot_attachment/editor_plugin.js4
-rw-r--r--askbot/media/js/tinymce/plugins/askbot_imageuploader/editor_plugin.js3
-rw-r--r--askbot/media/js/utils.js214
-rw-r--r--askbot/media/style/style.css74
-rw-r--r--askbot/media/style/style.less41
-rw-r--r--askbot/views/writers.py13
6 files changed, 282 insertions, 67 deletions
diff --git a/askbot/media/js/tinymce/plugins/askbot_attachment/editor_plugin.js b/askbot/media/js/tinymce/plugins/askbot_attachment/editor_plugin.js
index d1ef13b4..5f996804 100644
--- a/askbot/media/js/tinymce/plugins/askbot_attachment/editor_plugin.js
+++ b/askbot/media/js/tinymce/plugins/askbot_attachment/editor_plugin.js
@@ -27,11 +27,9 @@
}
};
- var modalMenuHeadline = gettext('Insert a file');
-
var createDialog = function() {
var dialog = new FileUploadDialog();
- dialog.setHeadingText(modalMenuHeadline);
+ dialog.setFileType('attachment');
dialog.setPostUploadHandler(insertIntoDom);
dialog.setInputId('askbot_attachment_input');
dialog.setUrlInputTooltip(gettext('Or paste file url here'));
diff --git a/askbot/media/js/tinymce/plugins/askbot_imageuploader/editor_plugin.js b/askbot/media/js/tinymce/plugins/askbot_imageuploader/editor_plugin.js
index 7fa6b6be..0cd70473 100644
--- a/askbot/media/js/tinymce/plugins/askbot_imageuploader/editor_plugin.js
+++ b/askbot/media/js/tinymce/plugins/askbot_imageuploader/editor_plugin.js
@@ -27,11 +27,8 @@
}
};
- var modalMenuHeadline = gettext('Upload an image');
-
var createDialog = function() {
var dialog = new FileUploadDialog();
- dialog.setHeadingText(modalMenuHeadline);
dialog.setPostUploadHandler(insertIntoDom);
dialog.setUrlInputTooltip('Or paste image url here');
dialog.setInputId('askbot_imageuploader_input');
diff --git a/askbot/media/js/utils.js b/askbot/media/js/utils.js
index 8ce4e205..a26c1ec9 100644
--- a/askbot/media/js/utils.js
+++ b/askbot/media/js/utils.js
@@ -903,6 +903,7 @@ var ModalDialog = function() {
var me = this;
this._reject_handler = function() { me.hide(); };
this._content_element = undefined;
+ this._headerEnabled = true;
};
inherits(ModalDialog, WrappedElement);
@@ -965,19 +966,21 @@ ModalDialog.prototype.createDom = function() {
element.addClass('modal');
//1) create header
- var header = this.makeElement('div')
- header.addClass('modal-header');
- element.append(header);
+ if (this._headerEnabled) {
+ var header = this.makeElement('div')
+ header.addClass('modal-header');
+ element.append(header);
+ var close_link = this.makeElement('div');
+ close_link.addClass('close');
+ close_link.attr('data-dismiss', 'modal');
+ close_link.html('x');
+ header.append(close_link);
+ var title = this.makeElement('h3');
+ title.html(this._heading_text);
+ header.append(title);
+ }
- var close_link = this.makeElement('div');
- close_link.addClass('close');
- close_link.attr('data-dismiss', 'modal');
- close_link.html('x');
- header.append(close_link);
- var title = this.makeElement('h3');
- title.html(this._heading_text);
- header.append(title);
//2) create content
var body = this.makeElement('div')
@@ -994,13 +997,13 @@ ModalDialog.prototype.createDom = function() {
element.append(footer);
var accept_btn = this.makeElement('button');
- accept_btn.addClass('btn btn-primary');
+ accept_btn.addClass('submit');
accept_btn.html(this._accept_button_text);
footer.append(accept_btn);
if (this._reject_button_text) {
var reject_btn = this.makeElement('button');
- reject_btn.addClass('btn cancel');
+ reject_btn.addClass('submit cancel');
reject_btn.html(this._reject_button_text);
footer.append(reject_btn);
}
@@ -1010,7 +1013,9 @@ ModalDialog.prototype.createDom = function() {
if (this._reject_button_text) {
setupButtonEventHandlers(reject_btn, this._reject_handler);
}
- setupButtonEventHandlers(close_link, this._reject_handler);
+ if (this._headerEnabled) {
+ setupButtonEventHandlers(close_link, this._reject_handler);
+ }
this.hide();
};
@@ -1020,10 +1025,27 @@ ModalDialog.prototype.createDom = function() {
*/
var FileUploadDialog = function() {
ModalDialog.call(this);
- self._post_upload_handler = undefined;
+ this._post_upload_handler = undefined;
+ this._fileType = 'image';
+ this._headerEnabled = false;
};
inherits(FileUploadDialog, ModalDialog);
+/**
+ * allowed values: 'image', 'attachment'
+ */
+FileUploadDialog.prototype.setFileType = function(fileType) {
+ this._fileType = fileType;
+};
+
+FileUploadDialog.prototype.getFileType = function() {
+ return this._fileType;
+};
+
+FileUploadDialog.prototype.setButtonText = function(text) {
+ this._fakeInput.val(text);
+};
+
FileUploadDialog.prototype.setPostUploadHandler = function(handler) {
this._post_upload_handler = handler;
};
@@ -1040,6 +1062,10 @@ FileUploadDialog.prototype.getInputId = function() {
return this._input_id;
};
+FileUploadDialog.prototype.setLabelText= function(text) {
+ this._label.html(text);
+};
+
FileUploadDialog.prototype.setUrlInputTooltip = function(text) {
this._url_input_tooltip = text;
};
@@ -1063,30 +1089,112 @@ FileUploadDialog.prototype.resetInputs = function() {
this._upload_input.val('');
};
+FileUploadDialog.prototype.getInputElement = function() {
+ return $('#' + this.getInputId());
+};
+
+FileUploadDialog.prototype.installFileUploadHandler = function(handler) {
+ var upload_input = this.getInputElement();
+ upload_input.unbind('change');
+ //todo: fix this - make event handler reinstall work
+ upload_input.change(handler);
+};
+
FileUploadDialog.prototype.show = function() {
//hack around the ajaxFileUpload plugin
FileUploadDialog.superClass_.show.call(this);
- var upload_input = this._upload_input;
- upload_input.unbind('change');
- //todo: fix this - make event handler reinstall work
- upload_input.change(this.getStartUploadHandler());
+ var handler = this.getStartUploadHandler();
+ this.installFileUploadHandler(handler);
};
-FileUploadDialog.prototype.getStartUploadHandler = function(){
- /* startUploadHandler is passed in to re-install the event handler
- * which is removed by the ajaxFileUpload jQuery extension
- */
+FileUploadDialog.prototype.getUrlInputElement = function() {
+ return this._url_input.getElement();
+};
+
+/*
+ * argument startUploadHandler is very special it must
+ * be a function calling this one!!! Todo: see if there
+ * is a more civilized way to do this.
+ */
+FileUploadDialog.prototype.startFileUpload = function(startUploadHandler) {
+
var spinner = this._spinner;
- var uploadInputId = this.getInputId();
- var urlInput = this._url_input;
+ var label = this._label;
+
+ spinner.ajaxStart(function(){
+ spinner.show();
+ label.hide();
+ });
+ spinner.ajaxComplete(function(){
+ spinner.hide();
+ label.show();
+ });
+
+ /* important!!! upload input must be loaded by id
+ * because ajaxFileUpload monkey-patches the upload form */
+ var uploadInput = this.getInputElement();
+ uploadInput.ajaxStart(function(){ uploadInput.hide(); });
+ uploadInput.ajaxComplete(function(){ uploadInput.show(); });
+
+ //var localFilePath = upload_input.val();
+
+ var me = this;
+
+ $.ajaxFileUpload({
+ url: askbot['urls']['upload'],
+ secureuri: false,//todo: check on https
+ fileElementId: this.getInputId(),
+ dataType: 'xml',
+ success: function (data, status) {
+
+ var fileURL = $(data).find('file_url').text();
+ var origFileName = $(data).find('orig_file_name').text();
+ var newStatus = interpolate(
+ gettext('Uploaded file: %s'),
+ [origFileName]
+ );
+ /*
+ * hopefully a fix for the "fakepath" issue
+ * https://www.mediawiki.org/wiki/Special:Code/MediaWiki/83225
+ */
+ fileURL = fileURL.replace(/\w:.*\\(.*)$/,'$1');
+ var error = $(data).find('error').text();
+ if (error != ''){
+ alert(error);
+ } else {
+ me.getUrlInputElement().attr('value', fileURL);
+ me.setLabelText(newStatus);
+ if (me.getFileType() === 'image') {
+ var buttonText = gettext('Choose a different image');
+ } else {
+ var buttonText = gettext('Choose a different file');
+ }
+ me.setButtonText(buttonText);
+ }
+
+ /* re-install this as the upload extension
+ * will remove the handler to prevent double uploading
+ * this hack is a manipulation around the
+ * ajaxFileUpload jQuery plugin. */
+ me.installFileUploadHandler(startUploadHandler);
+ },
+ error: function (data, status, e) {
+ /* re-install this as the upload extension
+ * will remove the handler to prevent double uploading */
+ me.installFileUploadHandler(startUploadHandler);
+ }
+ });
+ return false;
+};
+
+FileUploadDialog.prototype.getStartUploadHandler = function(){
+ var me = this;
var handler = function() {
- var options = {
- 'spinner': spinner,
- 'uploadInputId': uploadInputId,
- 'urlInput': urlInput.getElement(),
- 'startUploadHandler': handler//pass in itself
- };
- return ajaxFileUpload(options);
+ /* the trick is that we need inside the function call
+ * to have a reference to itself
+ * in order to reinstall the handler later
+ * because ajaxFileUpload jquery extension might be destroying it */
+ return me.startFileUpload(handler);
};
return handler;
};
@@ -1113,10 +1221,11 @@ FileUploadDialog.prototype.createDom = function() {
superClass.createDom.call(this);
var form = this.makeElement('form');
+ form.addClass('ajax-file-upload');
form.css('margin-bottom', 0);
this.prependContent(form);
- // File upload button
+ // Browser native file upload field
var upload_input = this.makeElement('input');
upload_input.attr({
id: this._input_id,
@@ -1126,9 +1235,32 @@ FileUploadDialog.prototype.createDom = function() {
});
form.append(upload_input);
this._upload_input = upload_input;
- form.append($('<br/>'));
- // The url input text box
+ var fakeInput = this.makeElement('input');
+ fakeInput.attr('type', 'button');
+ fakeInput.addClass('submit');
+ fakeInput.addClass('fake-file-input');
+ if (this._fileType === 'image') {
+ var buttonText = gettext('Choose an image to insert');
+ } else {
+ var buttonText = gettext('Choose a file to insert');
+ }
+ fakeInput.val(buttonText);
+ this._fakeInput = fakeInput;
+ form.append(fakeInput);
+
+ setupButtonEventHandlers(fakeInput, function() { upload_input.click() });
+
+ // Label which will also serve as status display
+ var label = this.makeElement('label');
+ label.attr('for', this._input_id);
+ var types = askbot['settings']['allowedUploadFileTypes'];
+ types = types.join(', ');
+ label.html(gettext('Allowed file types are:') + ' ' + types + '.');
+ form.append(label);
+ this._label = label;
+
+ // The url input text box, probably unused in fact
var url_input = new TippedInput();
url_input.setInstruction(this._url_input_tooltip || gettext('Or paste file url here'));
var url_input_element = url_input.getElement();
@@ -1140,15 +1272,6 @@ FileUploadDialog.prototype.createDom = function() {
//form.append($('<br/>'));
this._url_input = url_input;
- var label = this.makeElement('label');
- label.attr('for', this._input_id);
-
- var types = askbot['settings']['allowedUploadFileTypes'];
- types = types.join(', ');
- label.html(gettext('Allowed file types are:') + ' ' + types + '.');
- form.append(label);
- form.append($('<br/>'));
-
/* //Description input box
var descr_input = new TippedInput();
descr_input.setInstruction(gettext('Describe the image here'));
@@ -1158,8 +1281,9 @@ FileUploadDialog.prototype.createDom = function() {
this._description_input = descr_input;
*/
var spinner = this.makeElement('img');
- spinner.attr('src', mediaUrl('media/images/indicator.gif'));
+ spinner.attr('src', mediaUrl('media/images/ajax-loader.gif'));
spinner.css('display', 'none');
+ spinner.addClass('spinner');
form.append(spinner);
this._spinner = spinner;
diff --git a/askbot/media/style/style.css b/askbot/media/style/style.css
index 3c447e56..9e386c09 100644
--- a/askbot/media/style/style.css
+++ b/askbot/media/style/style.css
@@ -144,6 +144,12 @@ html {
height: 0;
visibility: hidden;
}
+.invisible {
+ margin: -1px 0 0 -1px;
+ height: 1px;
+ overflow: hidden;
+ width: 1px;
+}
.badges a {
color: #763333;
text-decoration: underline;
@@ -610,19 +616,20 @@ input[type="submit"],
input[type="button"],
input[type="reset"],
.button {
+ border: 0 !important;
+ border-top: #eaf2f3 1px solid;
cursor: pointer;
color: #4a757f;
- height: 27px;
font-family: 'Open Sans Condensed', Arial, sans-serif;
font-size: 14px;
font-weight: bold;
+ height: 27px;
+ margin-right: 10px;
text-align: center;
text-decoration: none;
text-shadow: 0px 1px 0px #c6d9dd;
-moz-text-shadow: 0px 1px 0px #c6d9dd;
-webkit-text-shadow: 0px 1px 0px #c6d9dd;
- border: 0 !important;
- border-top: #eaf2f3 1px solid;
background-color: #d1e2e5;
background-repeat: no-repeat;
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#d1e2e5), color-stop(25%, #d1e2e5), to(#a9c2c7));
@@ -678,6 +685,39 @@ input[type="submit"].link {
input[type="submit"].link:hover {
text-decoration: underline;
}
+form.ajax-file-upload {
+ height: 60px;
+ position: relative;
+}
+form.ajax-file-upload input[type="file"],
+form.ajax-file-upload input.fake-file-input {
+ cursor: pointer;
+ height: 32px;
+ position: absolute;
+ top: 0;
+ left: 0;
+}
+form.ajax-file-upload input[type="file"] {
+ z-index: 2;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
+ filter: alpha(opacity=0);
+ -moz-opacity: 0;
+ -khtml-opacity: 0;
+ opacity: 0;
+}
+form.ajax-file-upload input.fake-file-input {
+ z-index: 1;
+}
+form.ajax-file-upload label,
+form.ajax-file-upload img.spinner {
+ bottom: 0;
+ left: 3px;
+ position: absolute;
+}
+form.ajax-file-upload img.spinner {
+ bottom: 6px;
+ left: 10px;
+}
#askButton {
/* check blocks/secondary_header.html and widgets/ask_button.html*/
@@ -1750,6 +1790,13 @@ ul#related-tags li {
width: 723px;
width: 100%;
}
+.ask-page .post-comments .wmd-container,
+.question-page .post-comments .wmd-container,
+.edit-question-page .post-comments .wmd-container,
+.edit-answer-page .post-comments .wmd-container {
+ margin-bottom: 8px;
+ margin-left: -2px;
+}
.ask-page #editor,
.question-page #editor,
.edit-question-page #editor,
@@ -1967,6 +2014,10 @@ ul#related-tags li {
width: 20px;
vertical-align: top;
}
+.question-page .answer-table .mceEditor td,
+.question-page #question-table .mceEditor td {
+ width: auto;
+}
.question-page .question-body,
.question-page .answer-body {
overflow: auto;
@@ -2298,6 +2349,13 @@ ul#related-tags li {
vertical-align: top;
width: 100px;
}
+.question-page .comments input[name="suppress_email"] {
+ margin: 4px 5px 0 0;
+ width: auto;
+}
+.question-page .comments label[for="suppress_email"] {
+ vertical-align: top;
+}
.question-page .comments button.submit {
height: 26px;
line-height: 26px;
@@ -2308,7 +2366,6 @@ ul#related-tags li {
display: inline-block;
width: 245px;
float: right;
- color: #b6a475 !important;
vertical-align: top;
font-family: Arial;
float: right;
@@ -3082,16 +3139,16 @@ ins {
/* ----- Red Popup notification ----- */
.vote-notification {
z-index: 1;
+ background-color: #8e0000;
+ color: white;
cursor: pointer;
display: none;
- position: absolute;
font-family: Arial;
font-size: 14px;
font-weight: normal;
- color: white;
- background-color: #8e0000;
- text-align: center;
padding-bottom: 10px;
+ position: absolute;
+ text-align: center;
-webkit-box-shadow: 0px 2px 4px #370000;
-moz-box-shadow: 0px 2px 4px #370000;
box-shadow: 0px 2px 4px #370000;
@@ -3108,6 +3165,7 @@ ins {
margin-bottom: 5px;
border-top: #8e0000 1px solid;
color: #fff;
+ line-height: 20px;
font-weight: normal;
border-top-right-radius: 4px;
border-top-left-radius: 4px;
diff --git a/askbot/media/style/style.less b/askbot/media/style/style.less
index 85b18ac1..3c50090e 100644
--- a/askbot/media/style/style.less
+++ b/askbot/media/style/style.less
@@ -665,17 +665,18 @@ input[type="submit"],
input[type="button"],
input[type="reset"],
.button {
+ border: 0 !important;
+ border-top: #eaf2f3 1px solid;
cursor: pointer;
color: @button-label;
- height: 27px;
font-family: @main-font;
font-size: 14px;
font-weight: bold;
+ height: 27px;
+ margin-right: 10px;
text-align: center;
text-decoration: none;
.text-shadow(0px,1px,0px,#c6d9dd);
- border: 0 !important;
- border-top: #eaf2f3 1px solid;
.linear-gradient(#d1e2e5,#a9c2c7);
.rounded-corners(4px);
.box-shadow(1px, 1px, 2px, #636363)
@@ -709,6 +710,40 @@ input[type="submit"].link:hover {
text-decoration: underline;
}
+form.ajax-file-upload {
+ height: 60px;
+ position: relative;
+ input[type="file"],
+ input.fake-file-input {
+ cursor: pointer;
+ height: 32px;
+ position: absolute;
+ top: 0;
+ left: 0;
+ }
+ input[type="file"] {
+ z-index: 2;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
+ filter: alpha(opacity=0);
+ -moz-opacity: 0;
+ -khtml-opacity: 0;
+ opacity: 0;
+ }
+ input.fake-file-input {
+ z-index: 1;
+ }
+ label,
+ img.spinner {
+ bottom: 0;
+ left: 3px;
+ position: absolute;
+ }
+ img.spinner {
+ bottom: 6px;
+ left: 10px;
+ }
+}
+
#askButton { /* check blocks/secondary_header.html and widgets/ask_button.html*/
float:right;
font-size: 20px;
diff --git a/askbot/views/writers.py b/askbot/views/writers.py
index 896ef09d..deec46cc 100644
--- a/askbot/views/writers.py
+++ b/askbot/views/writers.py
@@ -62,6 +62,8 @@ ANSWERS_PAGE_SIZE = 10
def upload(request):#ajax upload file to a question or answer
"""view that handles file upload via Ajax
"""
+ import pdb
+ pdb.set_trace()
# check upload permission
result = ''
@@ -81,10 +83,11 @@ def upload(request):#ajax upload file to a question or answer
raise exceptions.PermissionDenied('invalid upload file name prefix')
#todo: check file type
- f = request.FILES['file-upload']#take first file
+ uploaded_file = request.FILES['file-upload']#take first file
+ orig_file_name = uploaded_file.name
#todo: extension checking should be replaced with mimetype checking
#and this must be part of the form validation
- file_extension = os.path.splitext(f.name)[1].lower()
+ file_extension = os.path.splitext(orig_file_name)[1].lower()
if not file_extension in settings.ASKBOT_ALLOWED_UPLOAD_FILE_TYPES:
file_types = "', '".join(settings.ASKBOT_ALLOWED_UPLOAD_FILE_TYPES)
msg = _("allowed file types are '%(file_types)s'") % \
@@ -93,7 +96,7 @@ def upload(request):#ajax upload file to a question or answer
# generate new file name and storage object
file_storage, new_file_name, file_url = store_file(
- f, file_name_prefix
+ uploaded_file, file_name_prefix
)
# check file size
# byte
@@ -122,8 +125,8 @@ def upload(request):#ajax upload file to a question or answer
# 'file_url': file_url
#})
#return HttpResponse(data, mimetype = 'application/json')
- xml_template = "<result><msg><![CDATA[%s]]></msg><error><![CDATA[%s]]></error><file_url>%s</file_url></result>"
- xml = xml_template % (result, error, file_url)
+ xml_template = "<result><msg><![CDATA[%s]]></msg><error><![CDATA[%s]]></error><file_url>%s</file_url><orig_file_name><![CDATA[%s]]></orig_file_name></result>"
+ xml = xml_template % (result, error, file_url, orig_file_name)
return HttpResponse(xml, mimetype="application/xml")