-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 28928ac
Showing
14 changed files
with
1,203 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.DS_Store | ||
|
||
node_modules | ||
|
||
dist/core.css | ||
dist/core.css.map | ||
dist/index.min.js | ||
dist/index.min.js.map |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
5.3.0 |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
var gulp = require('gulp'), | ||
concat = require('gulp-concat'), | ||
uglify = require('gulp-uglify'), | ||
sourcemaps = require('gulp-sourcemaps'), | ||
util = require('gulp-util'), | ||
del = require('del'), | ||
sass = require('gulp-sass'), | ||
notify = require("gulp-notify"), | ||
autoprefixer = require('gulp-autoprefixer'); | ||
|
||
|
||
var paths = { | ||
styles: [ | ||
'./sass/*.scss' | ||
], | ||
scripts: [ | ||
'node_modules/jquery/dist/jquery.js', | ||
'js/index.js' | ||
], | ||
destination: 'dist' | ||
}; | ||
|
||
gulp.task('clean', function(cb) { | ||
del(['dist/*.map'], cb); | ||
}); | ||
|
||
gulp.task('sass', function() { | ||
gulp.src(paths.styles) | ||
.pipe(sass().on('error', notify.onError(function(error) { | ||
return "Error: " + error.message; | ||
}))) | ||
.pipe(sourcemaps.init()) | ||
.pipe(sass({outputStyle: 'compressed'})) | ||
.pipe(autoprefixer()) | ||
.pipe(sourcemaps.write('.')) | ||
.pipe(gulp.dest(paths.destination)); | ||
}); | ||
|
||
gulp.task('sass-prod', function() { | ||
gulp.src(paths.styles) | ||
.pipe(sass().on('error', notify.onError(function(error) { | ||
return "Error: " + error.message; | ||
}))) | ||
.pipe(sass({outputStyle: 'compressed'})) | ||
.pipe(autoprefixer()) | ||
.pipe(gulp.dest(paths.destination)); | ||
}); | ||
|
||
gulp.task('scripts', function() { | ||
gulp.src(paths.scripts) | ||
.pipe(uglify().on('error', notify.onError(function(error) { | ||
return "Error: " + error.message; | ||
}))) | ||
.pipe(sourcemaps.init()) | ||
.pipe(concat('index.min.js')) | ||
.pipe(sourcemaps.write('.')) | ||
.pipe(gulp.dest(paths.destination)); | ||
}); | ||
|
||
gulp.task('scripts-prod', ['clean'], function() { | ||
gulp.src(paths.scripts) | ||
.pipe(uglify().on('error', notify.onError(function(error) { | ||
return "Error: " + error.message; | ||
}))) | ||
.pipe(concat('index.min.js')) | ||
.pipe(gulp.dest(paths.destination)); | ||
}); | ||
|
||
gulp.task('watch', function() { | ||
gulp.watch(paths.scripts, ['scripts']); | ||
gulp.watch(paths.styles, ['sass']); | ||
}); | ||
|
||
gulp.task('default', ['scripts', 'sass', 'watch']); | ||
gulp.task('prod', ['scripts-prod', 'sass-prod']); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,271 @@ | ||
var LOADING_PANE_CLASS = 'reddit-imgur-uploader-loading-pane'; | ||
|
||
$('#siteTable form[action="#"] div.bottom-area a.reddiquette, ' + // comments page's post text section | ||
'.commentarea form[action="#"] div.bottom-area a.reddiquette').after( // comments page's comments section | ||
'<label class="image-uploader-button">upload image' + | ||
'<input type="file" class="image-uploader">' + | ||
'<span class="error-tooltip"></span>' + | ||
'</label>' | ||
); | ||
|
||
// submit page's text section | ||
$('form.submit div.bottom-area a.reddiquette').after( | ||
'<label class="image-uploader-button for-submit-text-page">upload image' + | ||
'<input type="file" class="image-uploader">' + | ||
'<span class="error-tooltip"></span>' + | ||
'</label>' | ||
); | ||
|
||
// use an iife here so that the scope of these vars doesn't get too crazy | ||
;(function() { | ||
var $suggestTitleDiv = $('#suggest-title'); | ||
$suggestTitleDiv.append( | ||
'<label class="image-uploader-button for-submit-link-page">upload image' + | ||
'<input type="file" class="image-uploader">' + | ||
'<span class="error-tooltip"></span>' + | ||
'</label>' | ||
); | ||
|
||
var $imageUploaderButton = $suggestTitleDiv.find('.image-uploader-button'), | ||
$suggestTitleButton = $suggestTitleDiv.find('button'); | ||
|
||
// subtract 1px to offset the extra bit of padding in our lable that looks like a button | ||
$imageUploaderButton.css('margin-top', parseInt($suggestTitleButton.css('margin-top')) - 1); | ||
})(); | ||
|
||
$('body').click(function(event) { | ||
var $target = $(event.target) | ||
if ($target.is('label.image-uploader-button')) { | ||
// reddit is sometimes slapping `for="<random numbers>"` on our label/button | ||
// when a new comment textarea is opened. we want that attribute to go away | ||
// when the user clicks the button so that it opens up our file chooser | ||
$target.removeAttr('for'); | ||
|
||
removeButtonError($target); | ||
setUpFileHandler($target); | ||
} else if ($target.is('a.access-required[data-event-action="reply"]')) { | ||
var $reddiquetteLink = $target.closest('.thing[data-type="comment"]').find('.child form[action="#"] div.bottom-area a.reddiquette') | ||
|
||
if ($reddiquetteLink.siblings('label.image-uploader-button').length == 0) { | ||
$reddiquetteLink.after( | ||
'<label class="image-uploader-button">upload image' + | ||
'<input type="file" class="image-uploader">' + | ||
'<span class="error-tooltip"></span>' + | ||
'</label>' | ||
); | ||
} | ||
} | ||
}); | ||
|
||
function setUpFileHandler($button) { | ||
var $fileInput = $button.find('.image-uploader'); | ||
|
||
$fileInput | ||
.off('change') | ||
.on('change', function(event) { | ||
var image = event.target.files[0]; | ||
|
||
// if we don't reset the element, then if the user chooses the same | ||
// file back to back, it won't trigger a change event the second time | ||
resetFileInputElement($fileInput, event); | ||
|
||
if (image) { | ||
if (! hasAcceptableMimeType(image)) { | ||
showButtonError($button, "Sorry, it's gotta be some sort of image file!"); | ||
return | ||
} | ||
|
||
// if over 10MB | ||
if (image.size > 10000000) { | ||
showButtonError($button, "Sorry, the file can only be a maximum of 10MB"); | ||
return | ||
} | ||
|
||
uploadImageFromFileInput(image, $fileInput); | ||
} | ||
}); | ||
} | ||
|
||
function resetFileInputElement($fileInput, event) { | ||
$fileInput.wrap('<form>').closest('form').get(0).reset(); | ||
$fileInput.unwrap(); | ||
|
||
event.stopPropagation(); | ||
event.preventDefault(); | ||
} | ||
|
||
function uploadImageFromFileInput(image, $fileInput) { | ||
var $button = $fileInput.closest('label.image-uploader-button'), | ||
$input = $button.find('input'), | ||
data = new FormData(), | ||
$targetTextElement; | ||
|
||
if ($button.hasClass('for-submit-link-page')) { | ||
$targetTextElement = $button.closest('#suggest-title').siblings('input#url'); | ||
} else if ($button.hasClass('for-submit-text-page')) { | ||
$targetTextElement = $button.closest('.usertext-edit').find('.md textarea'); | ||
} else { | ||
$targetTextElement = $fileInput.closest('form').find('textarea'); | ||
} | ||
|
||
data.append("image", image); | ||
|
||
$input.attr('disabled', 'true'); | ||
|
||
showLoading($targetTextElement); | ||
|
||
$.ajax( | ||
"https://api.imgur.com/3/upload", | ||
{ | ||
data: data, | ||
method: "POST", | ||
headers: { | ||
"Authorization": "Client-ID 68238063ee04a62" // Reddit Imgur Uploader's unique app id | ||
}, | ||
processData: false, | ||
contentType: false | ||
} | ||
) | ||
.done(function(data, textStatus, jqXHR) { | ||
if (data && data.data && data.data.link && data.data.link.length > 0) { | ||
var currentText = $targetTextElement.val(), | ||
imgurUrl = data.data.link.replace('http://', 'https://'); // imgur often passes back non-SSL URLs | ||
|
||
$targetTextElement | ||
.focus() | ||
.val(currentText + (currentText.trim().length > 0 ? " " : "") + imgurUrl); | ||
|
||
// highlight our newly inserted URL | ||
var textareaNode = $targetTextElement[0]; | ||
if (textareaNode) { | ||
currentText = $targetTextElement.val(); | ||
textareaNode.selectionStart = currentText.indexOf(imgurUrl); | ||
textareaNode.selectionEnd = currentText.length; | ||
} | ||
} else { | ||
showButtonError($button, "Uh oh, something went wrong" + | ||
(data && data.data && data.data.error ? " " + data.data.error : "")); | ||
} | ||
}) | ||
.fail(function(jqXHR, textStatus, errorThrown) { | ||
showButtonError($button, "Uh oh, something went wrong" + | ||
(jqXHR && jqXHR.responseJSON && jqXHR.responseJSON.data && jqXHR.responseJSON.data.error ? | ||
" " + jqXHR.responseJSON.data.error : | ||
"")); | ||
}) | ||
.always(function(data) { | ||
$input.removeAttr('disabled'); | ||
|
||
hideLoading($targetTextElement); | ||
}); | ||
} | ||
|
||
function hasAcceptableMimeType(image) { | ||
var acceptableMimeTypes = [ | ||
'image/jpeg', | ||
'image/png', | ||
'image/gif', | ||
'image/tiff', | ||
'image/x-tiff', | ||
'image/bmp', | ||
'image/x-bmp', | ||
'image/x-bitmap', | ||
'image/x-xbitmap', | ||
'image/x-win-bitmap', | ||
'image/x-windows-bmp', | ||
'image/ms-bmp', | ||
'image/x-ms-bmp', | ||
'application/bmp', | ||
'application/x-bmp', | ||
'application/x-win-bitmap', | ||
'application/pdf', | ||
'application/x-pdf', | ||
'image/x-xcf', | ||
'image/xcf' | ||
], | ||
isAcceptable = false; | ||
|
||
acceptableMimeTypes.forEach(function(type) { | ||
if (image.type == type) { | ||
isAcceptable = true; | ||
} | ||
}); | ||
|
||
return isAcceptable | ||
} | ||
|
||
function showLoading($targetTextElement) { | ||
var $containerDiv, | ||
height, | ||
width, | ||
marginTop = 0, | ||
marginLeft = 0, | ||
loadingGifUrl = chrome.extension.getURL('dist/images/loading.gif'); | ||
|
||
if ($targetTextElement.is('#url')) { | ||
$containerDiv = $targetTextElement.closest('#url-field') | ||
height = $containerDiv.outerHeight() | ||
width = $containerDiv.outerWidth() | ||
|
||
} else { | ||
$containerDiv = $targetTextElement.closest('.md') | ||
height = $targetTextElement.outerHeight() | ||
width = $targetTextElement.outerWidth() | ||
marginTop = $containerDiv.css("padding-top") // give our loading div some margin to offset any | ||
marginLeft = $containerDiv.css("padding-left") // padding that the container div may have | ||
} | ||
|
||
$containerDiv | ||
.css('position', 'relative') | ||
.append($('<div/>').addClass(LOADING_PANE_CLASS).text('Uploading...')); | ||
|
||
$containerDiv.find('.' + LOADING_PANE_CLASS).css({ | ||
'background-image': 'url(' + loadingGifUrl + ')', | ||
'height': height, | ||
'width': width, | ||
'margin-top': marginTop, | ||
'margin-left': marginLeft | ||
}); | ||
} | ||
|
||
function hideLoading($targetTextElement) { | ||
var $containerDiv = $targetTextElement.is('#url') ? | ||
$targetTextElement.closest('#url-field') : | ||
$targetTextElement.closest('.md'); | ||
|
||
var $loadingPane = $containerDiv.find('.' + LOADING_PANE_CLASS); | ||
|
||
$loadingPane.css('opacity', 0); | ||
|
||
setTimeout(function() { | ||
$loadingPane.remove(); | ||
$targetTextElement.css('transition', ''); | ||
$containerDiv.closest('.md').css('position', 'static'); | ||
}, 210); | ||
} | ||
|
||
function showButtonError($button, errorMsg) { | ||
var $tooltip = $button.find('.error-tooltip') | ||
|
||
$tooltip.text(errorMsg); | ||
|
||
// pretty much some magic numbers :) | ||
var topOffset = - ($tooltip.height() + 17) | ||
leftOffset = 40 - $tooltip.width() / 2; | ||
|
||
$button | ||
.find('.error-tooltip') | ||
.css({ | ||
"top": topOffset, | ||
"left": leftOffset | ||
}); | ||
|
||
$button | ||
.addClass('reddit-imgur-uploader-error'); | ||
|
||
setTimeout(removeButtonError.bind(null, $button), 6000); | ||
} | ||
|
||
function removeButtonError($button) { | ||
$button.removeClass('reddit-imgur-uploader-error'); | ||
}; |
Oops, something went wrong.