This is a script for PuTao users; if you have no idea what PuTao is, this is not for you.
Available on Userscript (or its mirror). Authored by OpenGG (on mirror, Putao). See tutorial on Putao.
This is a script for PuTao users; if you have no idea what PuTao is, this is not for you.
Available on Userscript (or its mirror). Authored by OpenGG (on mirror, Putao). See tutorial on Putao.
| // ==UserScript== | |
| // @name Putao.Ajax.Uploader | |
| // @namespace Putao.Ajax.Uploader | |
| // @description Putao.Ajax.Uploader, alternative way of uploading images for `pt.sjtu.edu.cn` | |
| // @require https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js | |
| // @match https://pt.sjtu.edu.cn/forums.php?action=reply&* | |
| // @match https://pt.sjtu.edu.cn/forums.php?action=newtopic&* | |
| // @match https://pt.sjtu.edu.cn/forums.php?action=quotepost&* | |
| // ==/UserScript== | |
| function recent(sCurrent){ | |
| var sBase='1.7'; | |
| //$([]).on() works on 1.6 and after | |
| var aBase=sBase.split('.'); | |
| var aCurrent=sCurrent.split('.'); | |
| for(var i=0;i<aBase.length;++i){ | |
| //console.log([parseInt(aBase[i]||0),parseInt(aCurrent[i]||0)]); | |
| if(parseInt(aBase[i]||0,10)>parseInt(aCurrent[i]||0,10)){ | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| function addJQuery(callback) { | |
| var script = document.createElement("script"); | |
| script.setAttribute("src", "http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"); | |
| script.addEventListener('load', function () { | |
| var script = document.createElement("script"); | |
| script.textContent = "(" + callback.toString() + ")();"; | |
| document.body.appendChild(script); | |
| }, false); | |
| document.body.appendChild(script); | |
| } | |
| // the guts of this userscript | |
| function main(){ | |
| jQuery(function($){ | |
| (function ($) { | |
| /* | |
| * Default text - jQuery plugin for html5 dragging files from desktop to browser | |
| * | |
| * Author: Weixi Yen | |
| * | |
| * Email: [Firstname][Lastname]@gmail.com | |
| * | |
| * Copyright (c) 2010 Resopollution | |
| * | |
| * Licensed under the MIT license: | |
| * http://www.opensource.org/licenses/mit-license.php | |
| * | |
| * Project home: | |
| * http://www.github.com/weixiyen/jquery-filedrop | |
| * | |
| * Version: 0.1.0 | |
| * | |
| * Features: | |
| * Allows sending of extra parameters with file. | |
| * Works with Firefox 3.6+ | |
| * Future-compliant with HTML5 spec (will work with Webkit browsers and IE9) | |
| * Usage: | |
| * See README at project homepage | |
| * | |
| */ | |
| jQuery.event.props.push("dataTransfer"); | |
| var opts = {}, | |
| default_opts = { | |
| url: '', | |
| refresh: 1000, | |
| paramname: 'userfile', | |
| maxfiles: 25, | |
| maxfilesize: 1, | |
| // MBs | |
| data: {}, | |
| drop: empty, | |
| dragEnter: empty, | |
| dragOver: empty, | |
| dragLeave: empty, | |
| docEnter: empty, | |
| docOver: empty, | |
| docLeave: empty, | |
| beforeEach: empty, | |
| afterAll: empty, | |
| rename: empty, | |
| error: function (err, file, i) { | |
| alert(err); | |
| }, | |
| uploadStarted: empty, | |
| uploadFinished: empty, | |
| progressUpdated: empty, | |
| speedUpdated: empty | |
| }, | |
| errors = ["BrowserNotSupported", "TooManyFiles", "FileTooLarge"], | |
| doc_leave_timer, stop_loop = false, | |
| files_count = 0, | |
| files; | |
| $.fn.filedrop = function (options) { | |
| opts = $.extend({}, default_opts, options); | |
| this.bind('drop', drop).bind('dragenter', dragEnter).bind('dragover', dragOver).bind('dragleave', dragLeave); | |
| $(document).bind('drop', docDrop).bind('dragenter', docEnter).bind('dragover', docOver).bind('dragleave', docLeave); | |
| }; | |
| function drop(e) { | |
| opts.drop(e); | |
| files = e.dataTransfer.files; | |
| if (files === null || files === undefined) { | |
| opts.error(errors[0]); | |
| return false; | |
| } | |
| files_count = files.length; | |
| upload(); | |
| e.preventDefault(); | |
| return false; | |
| } | |
| function getBuilder(filename, filedata, boundary) { | |
| var dashdash = '--', | |
| crlf = '\r\n', | |
| builder = ''; | |
| $.each(opts.data, function (i, val) { | |
| if (typeof val === 'function') val = val(); | |
| builder += dashdash; | |
| builder += boundary; | |
| builder += crlf; | |
| builder += 'Content-Disposition: form-data; name="' + i + '"'; | |
| builder += crlf; | |
| builder += crlf; | |
| builder += val; | |
| builder += crlf; | |
| }); | |
| builder += dashdash; | |
| builder += boundary; | |
| builder += crlf; | |
| builder += 'Content-Disposition: form-data; name="' + opts.paramname + '"'; | |
| builder += '; filename="' + encodeURIComponent(filename) + '"'; | |
| builder += crlf; | |
| builder += 'Content-Type: application/octet-stream'; | |
| builder += crlf; | |
| builder += crlf; | |
| builder += filedata; | |
| builder += crlf; | |
| builder += dashdash; | |
| builder += boundary; | |
| builder += dashdash; | |
| builder += crlf; | |
| return builder; | |
| } | |
| function progress(e) { | |
| if (e.lengthComputable) { | |
| var percentage = Math.round((e.loaded * 100) / e.total); | |
| if (this.currentProgress != percentage) { | |
| this.currentProgress = percentage; | |
| opts.progressUpdated(this.index, this.file, this.currentProgress); | |
| var elapsed = new Date().getTime(); | |
| var diffTime = elapsed - this.currentStart; | |
| if (diffTime >= opts.refresh) { | |
| var diffData = e.loaded - this.startData; | |
| var speed = diffData / diffTime; // KB per second | |
| opts.speedUpdated(this.index, this.file, speed); | |
| this.startData = e.loaded; | |
| this.currentStart = elapsed; | |
| } | |
| } | |
| } | |
| } | |
| function upload() { | |
| stop_loop = false; | |
| if (!files) { | |
| opts.error(errors[0]); | |
| return false; | |
| } | |
| var filesDone = 0, | |
| filesRejected = 0; | |
| if (files_count > opts.maxfiles) { | |
| opts.error(errors[1]); | |
| return false; | |
| } | |
| for (var i = 0; i < files_count; i++) { | |
| if (stop_loop) return false; | |
| try { | |
| if (beforeEach(files[i]) != false) { | |
| if (i === files_count) return; | |
| var reader = new FileReader(), | |
| max_file_size = 1048576 * opts.maxfilesize; | |
| reader.index = i; | |
| if (files[i].size > max_file_size) { | |
| opts.error(errors[2], files[i], i); | |
| filesRejected++; | |
| continue; | |
| } | |
| reader.onloadend = send; | |
| reader.readAsBinaryString(files[i]); | |
| } else { | |
| filesRejected++; | |
| } | |
| } catch (err) { | |
| opts.error(errors[0]); | |
| return false; | |
| } | |
| } | |
| function send(e) { | |
| // Sometimes the index is not attached to the | |
| // event object. Find it by size. Hack for sure. | |
| if (e.target.index == undefined) { | |
| e.target.index = getIndexBySize(e.total); | |
| } | |
| var xhr = new XMLHttpRequest(), | |
| upload = xhr.upload, | |
| file = files[e.target.index], | |
| index = e.target.index, | |
| start_time = new Date().getTime(), | |
| boundary = '------multipartformboundary' + (new Date).getTime(), | |
| builder; | |
| newName = rename(file.name); | |
| if (typeof newName === "string") { | |
| builder = getBuilder(newName, e.target.result, boundary); | |
| } else { | |
| builder = getBuilder(file.name, e.target.result, boundary); | |
| } | |
| upload.index = index; | |
| upload.file = file; | |
| upload.downloadStartTime = start_time; | |
| upload.currentStart = start_time; | |
| upload.currentProgress = 0; | |
| upload.startData = 0; | |
| upload.addEventListener("progress", progress, false); | |
| xhr.open("POST", opts.url, true); | |
| xhr.setRequestHeader('content-type', 'multipart/form-data; boundary=' + boundary); | |
| xhr.sendAsBinary(builder); | |
| opts.uploadStarted(index, file, files_count); | |
| xhr.onload = function () { | |
| if (xhr.responseText) { | |
| var now = new Date().getTime(), | |
| timeDiff = now - start_time, | |
| result = opts.uploadFinished(index, file, xhr.responseText, timeDiff); | |
| filesDone++; | |
| if (filesDone == files_count - filesRejected) { | |
| afterAll(); | |
| } | |
| if (result === false) stop_loop = true; | |
| } | |
| }; | |
| } | |
| } | |
| function getIndexBySize(size) { | |
| for (var i = 0; i < files_count; i++) { | |
| if (files[i].size == size) { | |
| return i; | |
| } | |
| } | |
| return undefined; | |
| } | |
| function rename(name) { | |
| return opts.rename(name); | |
| } | |
| function beforeEach(file) { | |
| return opts.beforeEach(file); | |
| } | |
| function afterAll() { | |
| return opts.afterAll(); | |
| } | |
| function dragEnter(e) { | |
| clearTimeout(doc_leave_timer); | |
| e.preventDefault(); | |
| opts.dragEnter(e); | |
| } | |
| function dragOver(e) { | |
| clearTimeout(doc_leave_timer); | |
| e.preventDefault(); | |
| opts.docOver(e); | |
| opts.dragOver(e); | |
| } | |
| function dragLeave(e) { | |
| clearTimeout(doc_leave_timer); | |
| opts.dragLeave(e); | |
| e.stopPropagation(); | |
| } | |
| function docDrop(e) { | |
| e.preventDefault(); | |
| opts.docLeave(e); | |
| return false; | |
| } | |
| function docEnter(e) { | |
| clearTimeout(doc_leave_timer); | |
| e.preventDefault(); | |
| opts.docEnter(e); | |
| return false; | |
| } | |
| function docOver(e) { | |
| clearTimeout(doc_leave_timer); | |
| e.preventDefault(); | |
| opts.docOver(e); | |
| return false; | |
| } | |
| function docLeave(e) { | |
| doc_leave_timer = setTimeout(function () { | |
| opts.docLeave(e); | |
| }, 200); | |
| } | |
| function empty() {} | |
| try { | |
| if (XMLHttpRequest.prototype.sendAsBinary) return; | |
| XMLHttpRequest.prototype.sendAsBinary = function (datastr) { | |
| function byteValue(x) { | |
| return x.charCodeAt(0) & 0xff; | |
| } | |
| var ords = Array.prototype.map.call(datastr, byteValue); | |
| var ui8a = new Uint8Array(ords); | |
| this.send(ui8a.buffer); | |
| } | |
| } catch (e) {} | |
| })(jQuery); | |
| jQuery.fn.extend({ | |
| insertAtCaret: function (myValue) { | |
| return this.each(function (i) { | |
| if (document.selection) { | |
| //For browsers like Internet Explorer | |
| this.focus(); | |
| sel = document.selection.createRange(); | |
| sel.text = myValue; | |
| this.focus(); | |
| } else if (this.selectionStart || this.selectionStart == '0') { | |
| //For browsers like Firefox and Webkit based | |
| var startPos = this.selectionStart; | |
| var endPos = this.selectionEnd; | |
| var scrollTop = this.scrollTop; | |
| this.value = this.value.substring(0, startPos) + myValue + this.value.substring(endPos, this.value.length); | |
| this.focus(); | |
| this.selectionStart = startPos + myValue.length; | |
| this.selectionEnd = startPos + myValue.length; | |
| this.scrollTop = scrollTop; | |
| } else { | |
| this.value += myValue; | |
| this.focus(); | |
| } | |
| }) | |
| } | |
| }); | |
| /* function getUrlVars(){ | |
| var vars = [], hash; | |
| var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); | |
| for(var i = 0; i < hashes.length; i++) | |
| { | |
| hash = hashes[i].split('='); | |
| vars.push(hash[0]); | |
| vars[hash[0]] = hash[1]; | |
| } | |
| return vars; | |
| } */ | |
| //$('.post').html('<input type="submit" value="发表文章"><input type="reset" value="内容复原">'); | |
| $('<style type="text/css">.clearfix:after{content:".";display:block;clear:both;visibility:hidden;line-height:0;height:0}#dropbox{color:#fff;font-size:13px;width:800px;padding:10px 0;background:none repeat scroll 0 0 #111;border-radius:3px 3px 3px 3px;box-shadow:0 0 4px rgba(0,0,0,0.3) inset, 0 -3px 2px rgba(0,0,0,0.1);overflow:hidden;margin:5px auto 30px}#dropbox a,#dropbox a:link,#dropbox a:visited,#dropbox a:hover{color:inherit}#dropbox .message{display:block;text-align:center}#dropbox .message i{color:#CCC;font-size:10px}#dropbox .preview{float:left;position:relative;text-align:center;width:200px}#dropbox .preview img{box-shadow:0 0 2px #000;display:block;margin:auto;max-height:180px;max-width:170px}#dropbox .imageHolder{display:block;position:relative;height:180px;padding:20px 10px 10px 10px}#dropbox .uploaded{display:none;height:100%;left:0;position:absolute;top:0;width:100%}#dropbox .preview.done .uploaded{display:block}#dropbox .progressHolder{background-color:#252F38;box-shadow:0 0 2px #000;margin:0 10px}#dropbox .progress{-moz-transition:all .25s ease 0;background-color:#2586D0;box-shadow:0 0 1px rgba(255,255,255,0.4) inset;height:10px;width:0}#dropbox .preview.done .progress{width:100%!important}.addAllBar{margin:auto;width:180px;text-align:center;cursor:pointer;padding:5px 0;border:1px solid #fff;border-radius:5px;}.addAllBar:hover{box-shadow:0 0 4px #fff;}</style>').appendTo("head"); | |
| $('<div id="dropbox" class="clearfix"><div class="message">Drop images here to upload.<br /><i><a href="http://opengg.me/">Authored by MiaoMiao.</a></i></div></div>').appendTo($('input#qr').parent()); | |
| var dropbox = $('#dropbox'), | |
| message = $('.message', dropbox); | |
| var textarea = $('textarea#body'); | |
| var imgurls = []; | |
| var posted=[]; | |
| var addAllBar = $('<div class="addAllBar">Click here to Add all images to your post.<br /><span class="dropbox_uploaded"></span> / <span class="dropbox_count"></span></div>').appendTo(dropbox).hide().on('click', function () { | |
| textarea.insertAtCaret('\n[img=' + imgurls.join(']\n\n[img=') + ']\n'); | |
| $.merge(posted, imgurls); | |
| }); | |
| var waitingBar=$('<div class="addAllBar">Uploading, please wait and don\'t close this tab.<br /><span class="dropbox_uploaded"></span> / <span class="dropbox_count"></span></div>').appendTo(dropbox).hide(); | |
| //var board=getUrlVars().board; | |
| var amountLimit=8; | |
| var uploaded=0; | |
| $('form#compose').submit(function(e){ | |
| function arr_unique(arr) { | |
| var arrVal = arr; | |
| var uniqueArr = []; | |
| for (var i = arrVal.length; i--; ) { | |
| var val = arrVal[i]; | |
| if ($.inArray(val, uniqueArr) === -1) { | |
| uniqueArr.unshift(val); | |
| } | |
| } | |
| return uniqueArr; | |
| } | |
| posted=arr_unique(posted); | |
| if(posted.length<imgurls.length){ | |
| if(!confirm('上传的图片未全部贴出,你确定要发布这个帖子吗?')){ | |
| if(e.preventDefault){ | |
| e.preventDefault(); | |
| } | |
| return false; | |
| } | |
| } | |
| }); | |
| dropbox.filedrop({ | |
| // The name of the $_FILES entry: | |
| paramname: 'file', | |
| maxfiles: 10000, | |
| maxfilesize: 2, | |
| url: 'picbucket-upload.php', | |
| /* data: { | |
| board: board | |
| }, */ | |
| drop:function(e){ | |
| var n=e.dataTransfer.files.length; | |
| $('.dropbox_count').html(n); | |
| n>amountLimit?alert('你上传的文件过多,全部预览可能会占用较多系统资源,只显示部分预览'):false; | |
| addAllBar.hide(); | |
| waitingBar.show(); | |
| }, | |
| uploadFinished: function (i, file, response) { | |
| if (response.indexOf('URL') !== -1) { | |
| var imgholder = $.data(file); | |
| var imgurl = response.match('<img src="https:\/\/pt\.sjtu\.edu\.cn\/picbucket\/[^"]+')[0].replace('<img src="',''); | |
| //console.log(response); | |
| //console.log($(response)); | |
| //console.log($(response).find('img')); | |
| //console.log($(response).find('img')[0]); | |
| //console.log(imgurl); | |
| //imgholder.add | |
| //$('<div/>').appendTo(imgholder).on('click',function(){textarea.insertAtCaret(imgurl)}); | |
| //console.log([imgholder,textarea]); | |
| if(imgurl.length>0){ | |
| $('.dropbox_uploaded').html(++uploaded); | |
| imgurls.push(imgurl); | |
| if(imgholder.length>0){ | |
| imgholder.on('click', function () { | |
| textarea.insertAtCaret('\n[img=' + imgurl + ']\n'); | |
| posted.push(imgurl); | |
| }); | |
| $.data(file).addClass('done'); | |
| } | |
| } | |
| } | |
| // response is the JSON object that post_file.php returns | |
| }, | |
| error: function (err, file) { | |
| switch (err) { | |
| case 'BrowserNotSupported': | |
| showMessage('Your browser does not support HTML5 file uploads!'); | |
| break; | |
| case 'TooManyFiles': | |
| alert('Too many files! Please select 5 at most! (configurable)'); | |
| break; | |
| case 'FileTooLarge': | |
| alert(file.name + ' is too large! Please upload files up to 2mb (configurable).'); | |
| break; | |
| default: | |
| console.log([file, err]); | |
| break; | |
| } | |
| }, | |
| afterAll:function(){addAllBar.show();waitingBar.hide();}, | |
| // Called before each upload is started | |
| beforeEach: function (file) { | |
| /* if (!file.type.match(/^image\//)) { | |
| console.log(file.type); | |
| // Returning false will cause the | |
| // file to be rejected | |
| return false; | |
| } */ | |
| }, | |
| uploadStarted: function (i, file, len) { | |
| i<amountLimit?createImage(file):false; | |
| }, | |
| progressUpdated: function (i, file, progress) { | |
| var imgholder=$.data(file); | |
| imgholder.length>0?$.data(file).find('.progress').width(progress):false; | |
| } | |
| }); | |
| var template = '<div class="preview">' | |
| + '<span class="imageHolder">' | |
| + '<img />' | |
| + '<span class="uploaded"></span>' | |
| + '</span>' | |
| + '<div class="progressHolder">' | |
| + '<div class="progress"></div>' | |
| + '</div>' | |
| + '</div>'; | |
| function createImage(file) { | |
| var preview = $(template), | |
| image = $('img', preview); | |
| var reader = new FileReader(); | |
| image.width = 100; | |
| image.height = 100; | |
| reader.onload = function (e) { | |
| // e.target.result holds the DataURL which | |
| // can be used as a source of the image: | |
| image.attr('src', e.target.result); | |
| }; | |
| // Reading the file as a DataURL. When finished, | |
| // this will trigger the onload function above: | |
| reader.readAsDataURL(file); | |
| message.hide(); | |
| preview.appendTo(dropbox); | |
| // Associating a preview container | |
| // with the file, using jQuery's $.data(): | |
| $.data(file, preview); | |
| } | |
| function showMessage(msg) { | |
| message.html(msg); | |
| } | |
| }); | |
| } | |
| ((typeof jQuery!=='undefined')&&recent(jQuery.fn.jquery)&&!jQuery.browser.webkit)?main():addJQuery(main); |