Redo image uploading

Reduce size before saving, hopefully should reduce issues with
quotas. This will only affect images selected via shift-click.

Also, try to handle 404'd mascots.
This commit is contained in:
Zixaphir 2013-08-31 20:13:41 -07:00
parent fa569e5451
commit ac764fd102
5 changed files with 304 additions and 138 deletions

View File

@ -1,10 +1,12 @@
### v2.3.10 ### v2.3.10
*2013-08-31* *2013-08-31*
**Zixaphir**:
- Catalog bugfix
### v2.3.9 ### v2.3.9
*2013-08-30* *2013-08-30*
**MayhemYDG**: **MayhemYDG**:
- New desktop notification: - New desktop notification:
* The QR will now warn you when you are running low on cached captchas while auto-posting. * The QR will now warn you when you are running low on cached captchas while auto-posting.

View File

@ -12074,9 +12074,8 @@
innerHTML: "<img>" innerHTML: "<img>"
}), }),
change: function(mascot) { change: function(mascot) {
var el; var el, img;
el = this.el.firstElementChild;
if (Conf['Mascot Position'] === 'default') { if (Conf['Mascot Position'] === 'default') {
$.rmClass(doc, 'mascot-position-above-post-form'); $.rmClass(doc, 'mascot-position-above-post-form');
$.rmClass(doc, 'mascot-position-bottom'); $.rmClass(doc, 'mascot-position-bottom');
@ -12092,9 +12091,34 @@
} else if (!Conf['Silhouettize Mascots']) { } else if (!Conf['Silhouettize Mascots']) {
$.rmClass(doc, 'silhouettize-mascots'); $.rmClass(doc, 'silhouettize-mascots');
} }
el = $.el('img');
$.on(el, 'error', MascotTools.error);
el.src = Array.isArray(mascot.image) ? Style.lightTheme ? mascot.image[1] : mascot.image[0] : mascot.image; el.src = Array.isArray(mascot.image) ? Style.lightTheme ? mascot.image[1] : mascot.image[0] : mascot.image;
$.off(img = this.el.firstElementChild, 'error', MascotTools.error);
$.replace(img, el);
return Style.mascot.textContent = "#mascot img {\nheight: " + (mascot.height && isNaN(parseFloat(mascot.height)) ? mascot.height : mascot.height ? parseInt(mascot.height, 10) + 'px' : 'auto') + ";\nwidth: " + (mascot.width && isNaN(parseFloat(mascot.width)) ? mascot.width : mascot.width ? parseInt(mascot.width, 10) + 'px' : 'auto') + ";\n}\n#mascot {\nmargin: " + (mascot.vOffset || 0) + "px " + (mascot.hOffset || 0) + "px;\n}\n.sidebar-large #mascot {\nleft: " + (mascot.center ? 25 : 0) + "px;\nright: " + (mascot.center ? 25 : 0) + "px;\n}\n.mascot-position-above-post-form.post-form-style-fixed #mascot {\ntransform: translateY(-" + (QR.nodes ? QR.nodes.el.getBoundingClientRect().height : 0) + "px);\n}"; return Style.mascot.textContent = "#mascot img {\nheight: " + (mascot.height && isNaN(parseFloat(mascot.height)) ? mascot.height : mascot.height ? parseInt(mascot.height, 10) + 'px' : 'auto') + ";\nwidth: " + (mascot.width && isNaN(parseFloat(mascot.width)) ? mascot.width : mascot.width ? parseInt(mascot.width, 10) + 'px' : 'auto') + ";\n}\n#mascot {\nmargin: " + (mascot.vOffset || 0) + "px " + (mascot.hOffset || 0) + "px;\n}\n.sidebar-large #mascot {\nleft: " + (mascot.center ? 25 : 0) + "px;\nright: " + (mascot.center ? 25 : 0) + "px;\n}\n.mascot-position-above-post-form.post-form-style-fixed #mascot {\ntransform: translateY(-" + (QR.nodes ? QR.nodes.el.getBoundingClientRect().height : 0) + "px);\n}";
}, },
error: function() {
var ctx, el,
_this = this;
if (MascotTools.imageError) {
this.src = MascotTools.imageError;
}
el = $.el('canvas', {
width: 248,
height: 100
});
ctx = el.getContext('2d');
ctx.font = "50px " + Conf['Font'];
ctx.fillStyle = "#" + Style.colorToHex((Themes[Conf['theme']] || Themes['Yotsuba B'])['Text']);
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText("Mascot 404", 124, 50);
return el.toBlob(function(blob) {
return _this.src = MascotTools.imageError = URL.createObjectURL(blob);
});
},
toggle: function() { toggle: function() {
var enabled, i, len, mascot, name, string; var enabled, i, len, mascot, name, string;
@ -12149,41 +12173,47 @@
case "text": case "text":
div = this.input(item, name); div = this.input(item, name);
input = $('input', div); input = $('input', div);
if (name === 'image') { switch (name) {
$.on(input, 'blur', function() { case 'image':
editMascot[this.name] = this.value; $.on(input, 'blur', function() {
return MascotTools.change(editMascot); if (MascotTools.URL === this.value) {
}); return MascotTools.change(editMascot);
fileInput = $.el('input', { } else if (MascotTools.URL) {
type: "file", URL.revokeObjectURL(MascotTools.URL);
accept: "image/*", delete MascotTools.URL;
title: "imagefile", }
hidden: "hidden" editMascot[this.name] = this.value;
}); return MascotTools.change(editMascot);
$.on(input, 'click', function(evt) { });
if (evt.shiftKey) { fileInput = $.el('input', {
return this.nextSibling.click(); type: "file",
} accept: "image/*",
}); title: "imagefile",
$.on(fileInput, 'change', function(evt) { hidden: "hidden"
return MascotTools.uploadImage(evt, this); });
}); $.on(input, 'click', function(e) {
$.after(input, fileInput); if (e.shiftKey) {
} return this.nextSibling.click();
if (name === 'name') { }
$.on(input, 'blur', function() { });
this.value = this.value.replace(/[^a-z-_0-9]/ig, "_"); $.on(fileInput, 'change', MascotTools.uploadImage);
if ((this.value !== "") && !/^[a-z]/i.test(this.value)) { $.after(input, fileInput);
return alert("Mascot names must start with a letter."); break;
} case 'name':
editMascot[this.name] = this.value; $.on(input, 'blur', function() {
return MascotTools.change(editMascot); this.value = this.value.replace(/[^a-z-_0-9]/ig, "_");
}); if ((this.value !== "") && !/^[a-z]/i.test(this.value)) {
} else { return alert("Mascot names must start with a letter.");
$.on(input, 'blur', function() { }
editMascot[this.name] = this.value; editMascot[this.name] = this.value;
return MascotTools.change(editMascot); return MascotTools.change(editMascot);
}); });
break;
default:
$.on(input, 'blur', function() {
editMascot[this.name] = this.value;
return MascotTools.change(editMascot);
});
} }
break; break;
case "number": case "number":
@ -12250,19 +12280,51 @@
innerHTML: "<div class=optionlabel>" + item[0] + "</div><div class=option><input type=" + item[2] + " class=field name='" + name + "' placeholder='" + item[0] + "' value='" + value + "'></div>" innerHTML: "<div class=optionlabel>" + item[0] + "</div><div class=option><input type=" + item[2] + " class=field name='" + name + "' placeholder='" + item[0] + "' value='" + value + "'></div>"
}); });
}, },
uploadImage: function(evt, el) { uploadImage: function() {
var file, reader; var file, fileURL, img,
_this = this;
file = evt.target.files[0]; if (!(this.files && (file = this.files[0]))) {
reader = new FileReader(); return;
reader.onload = function(evt) { }
var val; if (MascotTools.URL) {
URL.revokeObjectURL(MascotTools.URL);
}
img = $.el('img');
img.onload = function() {
var cv, height, s, width;
val = evt.target.result; s = 400;
el.previousSibling.value = val; width = img.width, height = img.height;
return editMascot.image = val; if (width <= s) {
MascotTools.setImage(fileURL);
_this.previousElementSibling.value = fileURL;
return;
}
cv = $.el('canvas');
cv.height = height = s / width * height;
cv.width = width = s;
cv.getContext('2d').drawImage(img, 0, 0, width, height);
URL.revokeObjectURL(fileURL);
return cv.toBlob(function(blob) {
var fileURL;
MascotTools.URL = fileURL = URL.createObjectURL(MascotTools.file = blob);
MascotTools.setImage(fileURL);
return _this.previousElementSibling.value = fileURL;
});
}; };
return reader.readAsDataURL(file); MascotTools.URL = fileURL = URL.createObjectURL(MascotTools.file = file);
return img.src = fileURL;
},
setImage: function(fileURL) {
var reader;
reader = new FileReader();
reader.onload = function() {
return editMascot.image = reader.result;
};
return reader.readAsDataURL(MascotTools.file);
}, },
save: function(mascot) { save: function(mascot) {
var image, name; var image, name;

View File

@ -12070,9 +12070,8 @@
innerHTML: "<img>" innerHTML: "<img>"
}), }),
change: function(mascot) { change: function(mascot) {
var el; var el, img;
el = this.el.firstElementChild;
if (Conf['Mascot Position'] === 'default') { if (Conf['Mascot Position'] === 'default') {
$.rmClass(doc, 'mascot-position-above-post-form'); $.rmClass(doc, 'mascot-position-above-post-form');
$.rmClass(doc, 'mascot-position-bottom'); $.rmClass(doc, 'mascot-position-bottom');
@ -12088,9 +12087,34 @@
} else if (!Conf['Silhouettize Mascots']) { } else if (!Conf['Silhouettize Mascots']) {
$.rmClass(doc, 'silhouettize-mascots'); $.rmClass(doc, 'silhouettize-mascots');
} }
el = $.el('img');
$.on(el, 'error', MascotTools.error);
el.src = Array.isArray(mascot.image) ? Style.lightTheme ? mascot.image[1] : mascot.image[0] : mascot.image; el.src = Array.isArray(mascot.image) ? Style.lightTheme ? mascot.image[1] : mascot.image[0] : mascot.image;
$.off(img = this.el.firstElementChild, 'error', MascotTools.error);
$.replace(img, el);
return Style.mascot.textContent = "#mascot img {\nheight: " + (mascot.height && isNaN(parseFloat(mascot.height)) ? mascot.height : mascot.height ? parseInt(mascot.height, 10) + 'px' : 'auto') + ";\nwidth: " + (mascot.width && isNaN(parseFloat(mascot.width)) ? mascot.width : mascot.width ? parseInt(mascot.width, 10) + 'px' : 'auto') + ";\n}\n#mascot {\nmargin: " + (mascot.vOffset || 0) + "px " + (mascot.hOffset || 0) + "px;\n}\n.sidebar-large #mascot {\nleft: " + (mascot.center ? 25 : 0) + "px;\nright: " + (mascot.center ? 25 : 0) + "px;\n}\n.mascot-position-above-post-form.post-form-style-fixed #mascot {\n-webkit-transform: translateY(-" + (QR.nodes ? QR.nodes.el.getBoundingClientRect().height : 0) + "px);\n}"; return Style.mascot.textContent = "#mascot img {\nheight: " + (mascot.height && isNaN(parseFloat(mascot.height)) ? mascot.height : mascot.height ? parseInt(mascot.height, 10) + 'px' : 'auto') + ";\nwidth: " + (mascot.width && isNaN(parseFloat(mascot.width)) ? mascot.width : mascot.width ? parseInt(mascot.width, 10) + 'px' : 'auto') + ";\n}\n#mascot {\nmargin: " + (mascot.vOffset || 0) + "px " + (mascot.hOffset || 0) + "px;\n}\n.sidebar-large #mascot {\nleft: " + (mascot.center ? 25 : 0) + "px;\nright: " + (mascot.center ? 25 : 0) + "px;\n}\n.mascot-position-above-post-form.post-form-style-fixed #mascot {\n-webkit-transform: translateY(-" + (QR.nodes ? QR.nodes.el.getBoundingClientRect().height : 0) + "px);\n}";
}, },
error: function() {
var ctx, el,
_this = this;
if (MascotTools.imageError) {
this.src = MascotTools.imageError;
}
el = $.el('canvas', {
width: 248,
height: 100
});
ctx = el.getContext('2d');
ctx.font = "50px " + Conf['Font'];
ctx.fillStyle = "#" + Style.colorToHex((Themes[Conf['theme']] || Themes['Yotsuba B'])['Text']);
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText("Mascot 404", 124, 50);
return el.toBlob(function(blob) {
return _this.src = MascotTools.imageError = URL.createObjectURL(blob);
});
},
toggle: function() { toggle: function() {
var enabled, i, len, mascot, name, string; var enabled, i, len, mascot, name, string;
@ -12145,41 +12169,47 @@
case "text": case "text":
div = this.input(item, name); div = this.input(item, name);
input = $('input', div); input = $('input', div);
if (name === 'image') { switch (name) {
$.on(input, 'blur', function() { case 'image':
editMascot[this.name] = this.value; $.on(input, 'blur', function() {
return MascotTools.change(editMascot); if (MascotTools.URL === this.value) {
}); return MascotTools.change(editMascot);
fileInput = $.el('input', { } else if (MascotTools.URL) {
type: "file", URL.revokeObjectURL(MascotTools.URL);
accept: "image/*", delete MascotTools.URL;
title: "imagefile", }
hidden: "hidden" editMascot[this.name] = this.value;
}); return MascotTools.change(editMascot);
$.on(input, 'click', function(evt) { });
if (evt.shiftKey) { fileInput = $.el('input', {
return this.nextSibling.click(); type: "file",
} accept: "image/*",
}); title: "imagefile",
$.on(fileInput, 'change', function(evt) { hidden: "hidden"
return MascotTools.uploadImage(evt, this); });
}); $.on(input, 'click', function(e) {
$.after(input, fileInput); if (e.shiftKey) {
} return this.nextSibling.click();
if (name === 'name') { }
$.on(input, 'blur', function() { });
this.value = this.value.replace(/[^a-z-_0-9]/ig, "_"); $.on(fileInput, 'change', MascotTools.uploadImage);
if ((this.value !== "") && !/^[a-z]/i.test(this.value)) { $.after(input, fileInput);
return alert("Mascot names must start with a letter."); break;
} case 'name':
editMascot[this.name] = this.value; $.on(input, 'blur', function() {
return MascotTools.change(editMascot); this.value = this.value.replace(/[^a-z-_0-9]/ig, "_");
}); if ((this.value !== "") && !/^[a-z]/i.test(this.value)) {
} else { return alert("Mascot names must start with a letter.");
$.on(input, 'blur', function() { }
editMascot[this.name] = this.value; editMascot[this.name] = this.value;
return MascotTools.change(editMascot); return MascotTools.change(editMascot);
}); });
break;
default:
$.on(input, 'blur', function() {
editMascot[this.name] = this.value;
return MascotTools.change(editMascot);
});
} }
break; break;
case "number": case "number":
@ -12246,19 +12276,51 @@
innerHTML: "<div class=optionlabel>" + item[0] + "</div><div class=option><input type=" + item[2] + " class=field name='" + name + "' placeholder='" + item[0] + "' value='" + value + "'></div>" innerHTML: "<div class=optionlabel>" + item[0] + "</div><div class=option><input type=" + item[2] + " class=field name='" + name + "' placeholder='" + item[0] + "' value='" + value + "'></div>"
}); });
}, },
uploadImage: function(evt, el) { uploadImage: function() {
var file, reader; var file, fileURL, img,
_this = this;
file = evt.target.files[0]; if (!(this.files && (file = this.files[0]))) {
reader = new FileReader(); return;
reader.onload = function(evt) { }
var val; if (MascotTools.URL) {
URL.revokeObjectURL(MascotTools.URL);
}
img = $.el('img');
img.onload = function() {
var cv, height, s, width;
val = evt.target.result; s = 400;
el.previousSibling.value = val; width = img.width, height = img.height;
return editMascot.image = val; if (width <= s) {
MascotTools.setImage(fileURL);
_this.previousElementSibling.value = fileURL;
return;
}
cv = $.el('canvas');
cv.height = height = s / width * height;
cv.width = width = s;
cv.getContext('2d').drawImage(img, 0, 0, width, height);
URL.revokeObjectURL(fileURL);
return cv.toBlob(function(blob) {
var fileURL;
MascotTools.URL = fileURL = URL.createObjectURL(MascotTools.file = blob);
MascotTools.setImage(fileURL);
return _this.previousElementSibling.value = fileURL;
});
}; };
return reader.readAsDataURL(file); MascotTools.URL = fileURL = URL.createObjectURL(MascotTools.file = file);
return img.src = fileURL;
},
setImage: function(fileURL) {
var reader;
reader = new FileReader();
reader.onload = function() {
return editMascot.image = reader.result;
};
return reader.readAsDataURL(MascotTools.file);
}, },
save: function(mascot) { save: function(mascot) {
var image, name; var image, name;

View File

@ -95,7 +95,7 @@ Linkify =
return return
makeRange: (startNode, endNode, startOffset, endOffset) -> makeRange: (startNode, endNode, startOffset, endOffset) ->
range = document.createRange(); range = document.createRange()
range.setStart startNode, startOffset range.setStart startNode, startOffset
range.setEnd endNode, endOffset range.setEnd endNode, endOffset
range range

View File

@ -17,8 +17,6 @@ MascotTools =
innerHTML: "<img>" innerHTML: "<img>"
change: (mascot) -> change: (mascot) ->
el = @el.firstElementChild
if Conf['Mascot Position'] is 'default' if Conf['Mascot Position'] is 'default'
$.rmClass doc, 'mascot-position-above-post-form' $.rmClass doc, 'mascot-position-above-post-form'
$.rmClass doc, 'mascot-position-bottom' $.rmClass doc, 'mascot-position-bottom'
@ -34,7 +32,10 @@ MascotTools =
else unless Conf['Silhouettize Mascots'] else unless Conf['Silhouettize Mascots']
$.rmClass doc, 'silhouettize-mascots' $.rmClass doc, 'silhouettize-mascots'
el.src = el = $.el 'img'
$.on el, 'error', MascotTools.error
el.src =
if Array.isArray mascot.image if Array.isArray mascot.image
if Style.lightTheme if Style.lightTheme
mascot.image[1] mascot.image[1]
@ -43,8 +44,26 @@ MascotTools =
else else
mascot.image mascot.image
$.off img = @el.firstElementChild, 'error', MascotTools.error
$.replace img, el
Style.mascot.textContent = """<%= grunt.file.read('src/General/css/mascot.css') %>""" Style.mascot.textContent = """<%= grunt.file.read('src/General/css/mascot.css') %>"""
error: ->
@src = MascotTools.imageError if MascotTools.imageError
el = $.el 'canvas',
width: 248
height: 100
ctx = el.getContext('2d')
ctx.font = "50px #{Conf['Font']}"
ctx.fillStyle = "#" + Style.colorToHex (Themes[Conf['theme']] or Themes['Yotsuba B'])['Text']
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.fillText "Mascot 404", 124, 50
el.toBlob (blob) =>
@src = MascotTools.imageError = URL.createObjectURL blob
toggle: -> toggle: ->
string = g.MASCOTSTRING string = g.MASCOTSTRING
enabled = Conf[string] enabled = Conf[string]
@ -140,40 +159,43 @@ MascotTools =
div = @input item, name div = @input item, name
input = $ 'input', div input = $ 'input', div
if name is 'image' switch name
$.on input, 'blur', -> when 'image'
editMascot[@name] = @value $.on input, 'blur', ->
MascotTools.change editMascot if MascotTools.URL is @value
return MascotTools.change editMascot
else if MascotTools.URL
URL.revokeObjectURL MascotTools.URL
delete MascotTools.URL
editMascot[@name] = @value
MascotTools.change editMascot
fileInput = $.el 'input', fileInput = $.el 'input',
type: "file" type: "file"
accept: "image/*" accept: "image/*"
title: "imagefile" title: "imagefile"
hidden: "hidden" hidden: "hidden"
$.on input, 'click', (evt) -> $.on input, 'click', (e) ->
if evt.shiftKey if e.shiftKey
@.nextSibling.click() @nextSibling.click()
$.on fileInput, 'change', (evt) -> $.on fileInput, 'change', MascotTools.uploadImage
MascotTools.uploadImage evt, @
$.after input, fileInput $.after input, fileInput
if name is 'name' when 'name'
$.on input, 'blur', ->
@value = @value.replace /[^a-z-_0-9]/ig, "_"
if (@value isnt "") and !/^[a-z]/i.test @value
return alert "Mascot names must start with a letter."
editMascot[@name] = @value
MascotTools.change editMascot
$.on input, 'blur', -> else
@value = @value.replace /[^a-z-_0-9]/ig, "_" $.on input, 'blur', ->
if (@value isnt "") and !/^[a-z]/i.test @value editMascot[@name] = @value
return alert "Mascot names must start with a letter." MascotTools.change editMascot
editMascot[@name] = @value
MascotTools.change editMascot
else
$.on input, 'blur', ->
editMascot[@name] = @value
MascotTools.change editMascot
when "number" when "number"
div = @input item, name div = @input item, name
@ -230,17 +252,36 @@ MascotTools =
className: "mascotvar" className: "mascotvar"
innerHTML: "<div class=optionlabel>#{item[0]}</div><div class=option><input type=#{item[2]} class=field name='#{name}' placeholder='#{item[0]}' value='#{value}'></div>" innerHTML: "<div class=optionlabel>#{item[0]}</div><div class=option><input type=#{item[2]} class=field name='#{name}' placeholder='#{item[0]}' value='#{value}'></div>"
uploadImage: (evt, el) -> uploadImage: ->
file = evt.target.files[0] return unless @files and file = @files[0]
URL.revokeObjectURL MascotTools.URL if MascotTools.URL
img = $.el 'img'
img.onload = =>
s = 400
{width, height} = img
if width <= s
MascotTools.setImage fileURL
@previousElementSibling.value = fileURL
return
cv = $.el 'canvas'
cv.height = height = s / width * height
cv.width = width = s
cv.getContext('2d').drawImage img, 0, 0, width, height
URL.revokeObjectURL fileURL
cv.toBlob (blob) =>
MascotTools.URL = fileURL = URL.createObjectURL MascotTools.file = blob
MascotTools.setImage fileURL
@previousElementSibling.value = fileURL
MascotTools.URL = fileURL = URL.createObjectURL MascotTools.file = file
img.src = fileURL
setImage: (fileURL) ->
reader = new FileReader() reader = new FileReader()
reader.onload = ->
reader.onload = (evt) -> editMascot.image = reader.result
val = evt.target.result reader.readAsDataURL MascotTools.file
el.previousSibling.value = val
editMascot.image = val
reader.readAsDataURL file
save: (mascot) -> save: (mascot) ->
{name, image} = mascot {name, image} = mascot
@ -296,7 +337,6 @@ MascotTools =
reader = new FileReader() reader = new FileReader()
reader.onload = (e) -> reader.onload = (e) ->
try try
imported = JSON.parse e.target.result imported = JSON.parse e.target.result
catch err catch err