403 lines
12 KiB
JavaScript
403 lines
12 KiB
JavaScript
//
|
||
// The Antville Project
|
||
// http://code.google.com/p/antville
|
||
//
|
||
// Copyright 2001-2007 by The Antville People
|
||
//
|
||
// Licensed under the Apache License, Version 2.0 (the ``License'');
|
||
// you may not use this file except in compliance with the License.
|
||
// You may obtain a copy of the License at
|
||
//
|
||
// http://www.apache.org/licenses/LICENSE-2.0
|
||
//
|
||
// Unless required by applicable law or agreed to in writing, software
|
||
// distributed under the License is distributed on an ``AS IS'' BASIS,
|
||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
// See the License for the specific language governing permissions and
|
||
// limitations under the License.
|
||
//
|
||
// $Revision$
|
||
// $LastChangedBy$
|
||
// $LastChangedDate$
|
||
// $URL$
|
||
//
|
||
|
||
this.handleMetadata("contentLength");
|
||
this.handleMetadata("contentType");
|
||
this.handleMetadata("description");
|
||
this.handleMetadata("fileName");
|
||
this.handleMetadata("height");
|
||
this.handleMetadata("thumbnailHeight");
|
||
this.handleMetadata("thumbnailName");
|
||
this.handleMetadata("thumbnailWidth");
|
||
this.handleMetadata("origin");
|
||
this.handleMetadata("width");
|
||
|
||
Image.THUMBNAILWIDTH = 100;
|
||
|
||
Image.KEYS = ["name", "created", "modified", "origin", "description",
|
||
"contentType", "contentLength", "width", "height", "thumbnailName",
|
||
"thumbnailWidth", "thumbnailHeight", "fileName", "site"];
|
||
|
||
Image.remove = function() {
|
||
this.removeFiles();
|
||
this.setTags(null);
|
||
this.remove();
|
||
return;
|
||
}
|
||
|
||
Image.getFileExtension = function(type) {
|
||
switch (type) {
|
||
//case "image/x-icon":
|
||
//return ".ico";
|
||
case "image/gif":
|
||
return ".gif";
|
||
case "image/jpeg":
|
||
case "image/pjpeg":
|
||
return ".jpg";
|
||
case "image/png":
|
||
case "image/x-png":
|
||
return ".png";
|
||
}
|
||
return null;
|
||
}
|
||
|
||
Image.prototype.constructor = function(data) {
|
||
// Images.Default is using the constructor on code compilation
|
||
if (typeof session !== "undefined") {
|
||
this.creator = session.user;
|
||
this.touch();
|
||
}
|
||
if (data) {
|
||
for each (var key in Image.KEYS) {
|
||
this[key] = data[key];
|
||
}
|
||
}
|
||
this.created = new Date;
|
||
return this;
|
||
}
|
||
|
||
Image.prototype.getPermission = function(action) {
|
||
var defaultGrant = this._parent.getPermission("main");
|
||
switch (action) {
|
||
case ".":
|
||
case "main":
|
||
return true;
|
||
case "delete":
|
||
return defaultGrant && this.creator === session.user ||
|
||
Membership.require(Membership.MANAGER) ||
|
||
User.require(User.PRIVILEGED);
|
||
case "edit":
|
||
return defaultGrant && this.creator === session.user ||
|
||
Membership.require(Membership.MANAGER) ||
|
||
User.require(User.PRIVILEGED) &&
|
||
this.parent_type !== "Layout" ||
|
||
this.parent === path.layout;
|
||
case "replace":
|
||
return defaultGrant && (User.require(User.PRIVILEGED) ||
|
||
Membership.require(Membership.MANAGER)) &&
|
||
(this.parent_type === "Layout" &&
|
||
this.parent !== path.layout);
|
||
}
|
||
return false;
|
||
}
|
||
|
||
Image.prototype.href = function(action) {
|
||
if (action !== "replace") {
|
||
if (this.parent_type === "Layout" && this.parent !== path.layout) {
|
||
return this.getUrl();
|
||
}
|
||
} else {
|
||
return res.handlers.images.href("create") + "?name=" + this.name;
|
||
}
|
||
return HopObject.prototype.href.apply(this, arguments);
|
||
}
|
||
|
||
Image.prototype.main_action = function() {
|
||
res.data.title = gettext("Image {0}", this.name);
|
||
res.data.body = this.renderSkinAsString("Image#main");
|
||
res.handlers.site.renderSkin("Site#page");
|
||
return;
|
||
}
|
||
|
||
Image.prototype.edit_action = function() {
|
||
if (req.postParams.save) {
|
||
try {
|
||
this.update(req.postParams);
|
||
// FIXME: To be removed if work-around for Helma bug #607 passes
|
||
//this.setTags(req.postParams.tags || req.postParams.tag_array);
|
||
res.message = gettext("The changes were saved successfully.");
|
||
res.redirect(this.href());
|
||
} catch (ex) {
|
||
res.message = ex;
|
||
app.log(ex);
|
||
}
|
||
}
|
||
res.data.action = this.href(req.action);
|
||
res.data.title = gettext("Edit image {0}", this.name);
|
||
res.data.body = this.renderSkinAsString("$Image#edit");
|
||
res.handlers.site.renderSkin("Site#page");
|
||
return;
|
||
}
|
||
|
||
Image.prototype.getFormValue = function(name) {
|
||
var self = this;
|
||
|
||
var getOrigin = function(str) {
|
||
var origin = req.postParams.file_origin || self.origin;
|
||
if (origin && origin.contains("://")) {
|
||
return origin;
|
||
}
|
||
return null;
|
||
}
|
||
|
||
if (req.isPost()) {
|
||
if (name === "file") {
|
||
return getOrigin();
|
||
}
|
||
return req.postParams[name];
|
||
}
|
||
switch (name) {
|
||
case "file":
|
||
return getOrigin();
|
||
case "maxWidth":
|
||
case "maxHeight":
|
||
return this[name] || 400;
|
||
case "tags":
|
||
return this.getTags();
|
||
}
|
||
return this[name] || req.queryParams[name];
|
||
}
|
||
|
||
Image.prototype.update = function(data) {
|
||
if (data.uploadError) {
|
||
app.log(data.uploadError);
|
||
// Looks like the file uploaded has exceeded the upload limit ...
|
||
throw Error(gettext("File size is exceeding the upload limit."));
|
||
}
|
||
|
||
if (!data.file_origin) {
|
||
if (this.isTransient()) {
|
||
throw Error(gettext("There was nothing to upload. Please be sure to choose a file."));
|
||
}
|
||
} else if (data.file_origin !== this.origin) {
|
||
var mime = data.file;
|
||
if (mime.contentLength < 1) {
|
||
mime = getURL(data.file_origin);
|
||
if (!mime) {
|
||
throw Error(gettext("Could not fetch the image from the given URL."));
|
||
}
|
||
}
|
||
|
||
var extension = Image.getFileExtension(mime.contentType);
|
||
if (!extension) {
|
||
throw Error(gettext("This type of file cannot be uploaded as image."));
|
||
}
|
||
|
||
this.origin = data.file_origin;
|
||
var mimeName = mime.normalizeFilename(mime.name);
|
||
this.contentLength = mime.contentLength;
|
||
this.contentType = mime.contentType;
|
||
|
||
if (!this.name) {
|
||
var name = File.getName(data.name) || mimeName.split(".")[0];
|
||
this.name = this.site.images.getAccessName(name);
|
||
}
|
||
|
||
var image = this.getConstraint(mime, data.maxWidth, data.maxHeight);
|
||
this.height = image.height;
|
||
this.width = image.width;
|
||
|
||
var thumbnail;
|
||
if (image.width > Image.THUMBNAILWIDTH) {
|
||
thumbnail = this.getConstraint(mime, Image.THUMBNAILWIDTH);
|
||
this.thumbnailWidth = thumbnail.width;
|
||
this.thumbnailHeight = thumbnail.height;
|
||
} else if (this.isPersistent()) {
|
||
this.getThumbnailFile().remove();
|
||
// NOTE: delete won't work here due to getter/setter methods
|
||
this.metadata.remove("thumbnailName");
|
||
this.metadata.remove("thumbnailWidth");
|
||
this.metadata.remove("thumbnailHeight");
|
||
}
|
||
|
||
// Make the image persistent before proceeding with writing files and
|
||
// setting tags (also see Helma bug #607)
|
||
this.isTransient() && this.persist();
|
||
|
||
var fileName = this.name + extension;
|
||
if (fileName !== this.fileName) {
|
||
// Remove existing image files if the file name has changed
|
||
this.removeFiles();
|
||
}
|
||
this.fileName = fileName;
|
||
thumbnail && (this.thumbnailName = this.name + "_small" + extension);
|
||
this.writeFiles(image.resized || mime, thumbnail && thumbnail.resized);
|
||
}
|
||
|
||
if (this.parent_type !== "Layout") {
|
||
this.setTags(data.tags || data.tag_array);
|
||
}
|
||
this.description = data.description;
|
||
this.touch();
|
||
return;
|
||
}
|
||
|
||
Image.prototype.tags_macro = function() {
|
||
return res.write(this.getFormValue("tags"));
|
||
}
|
||
|
||
Image.prototype.contentLength_macro = function() {
|
||
res.write((this.contentLength / 1024).format("###,###") + " KB");
|
||
return;
|
||
}
|
||
|
||
Image.prototype.url_macro = function() {
|
||
return res.write(this.getUrl());
|
||
}
|
||
|
||
Image.prototype.macro_macro = function() {
|
||
return HopObject.prototype.macro_macro.call(this, null,
|
||
this.parent.constructor === Layout ? "layout.image" : "image");
|
||
}
|
||
|
||
Image.prototype.thumbnail_macro = function(param) {
|
||
if (!this.thumbnailName) {
|
||
return this.render_macro(param);
|
||
}
|
||
param.src = this.getUrl(this.getThumbnailFile().getName());
|
||
param.title || (param.title = encode(this.description));
|
||
param.alt = encode(param.alt || param.title);
|
||
param.width = this.thumbnailWidth || String.EMPTY;
|
||
param.height = this.thumbnailHeight || String.EMPTY;
|
||
param.border = (param.border = 0);
|
||
html.tag("img", param);
|
||
return;
|
||
}
|
||
|
||
Image.prototype.render_macro = function(param) {
|
||
param.src = this.getUrl();
|
||
param.title || (param.title = encode(this.description));
|
||
param.alt = encode(param.alt || param.title);
|
||
param.width || (param.width = this.width);
|
||
param.height || (param.height = this.height);
|
||
param.border || (param.border = 0);
|
||
html.tag("img", param);
|
||
return;
|
||
}
|
||
|
||
Image.prototype.getFile = function(name) {
|
||
name || (name = this.fileName);
|
||
if (this.parent_type === "Layout") {
|
||
var layout = this.parent || res.handlers.layout;
|
||
return layout.getFile(name);
|
||
}
|
||
var site = this.parent || res.handlers.site;
|
||
return site.getStaticFile("images/" + name);
|
||
}
|
||
|
||
Image.prototype.getUrl = function(name) {
|
||
name || (name = this.fileName);
|
||
//name = encodeURIComponent(name);
|
||
if (this.parent_type === "Layout") {
|
||
var layout = this.parent || res.handlers.layout;
|
||
res.push();
|
||
res.write("layout/");
|
||
res.write(name);
|
||
return layout.site.getStaticUrl(res.pop());
|
||
}
|
||
var site = this.parent || res.handlers.site;
|
||
return site.getStaticUrl("images/" + name);
|
||
// FIXME: testing free proxy for images
|
||
/* var result = "http://www.freeproxy.ca/index.php?url=" +
|
||
encodeURIComponent(res.pop().rot13()) + "&flags=11111";
|
||
return result; */
|
||
}
|
||
|
||
Image.prototype.getThumbnailFile = function() {
|
||
return this.getFile(this.thumbnailName);
|
||
// || this.fileName.replace(/(\.[^.]+)?$/, "_small$1"));
|
||
}
|
||
|
||
Image.prototype.getJSON = function() {
|
||
return {
|
||
name: this.name,
|
||
origin: this.origin,
|
||
description: this.description,
|
||
contentType: this.contentType,
|
||
contentLength: this.contentLength,
|
||
width: this.width,
|
||
height: this.height,
|
||
thumbnailName: this.thumbnailName,
|
||
thumbnailWidth: this.thumbnailWidth,
|
||
thumbnailHeight: this.thumbnailHeight,
|
||
created: this.created,
|
||
creator: this.creator ? this.creator.name : null,
|
||
modified: this.modified,
|
||
modifier: this.modifier ? this.modifier.name : null,
|
||
}.toSource();
|
||
}
|
||
|
||
Image.prototype.getConstraint = function(mime, maxWidth, maxHeight) {
|
||
try {
|
||
var image = new helma.Image(mime.inputStream);
|
||
var factorH = 1, factorV = 1;
|
||
if (maxWidth && image.width > maxWidth) {
|
||
factorH = maxWidth / image.width;
|
||
}
|
||
if (maxHeight && image.height > maxHeight) {
|
||
factorV = maxHeight / image.height;
|
||
}
|
||
if (factorH !== 1 || factorV !== 1) {
|
||
var width = Math.ceil(image.width *
|
||
(factorH < factorV ? factorH : factorV));
|
||
var height = Math.ceil(image.height *
|
||
(factorH < factorV ? factorH : factorV));
|
||
image.resize(width, height);
|
||
if (mime.contentType.endsWith("gif")) {
|
||
image.reduceColors(256);
|
||
}
|
||
return {resized: image, width: image.width, height: image.height};
|
||
}
|
||
return {width: image.width, height: image.height};
|
||
} catch (ex) {
|
||
app.log(ex);
|
||
throw Error(gettext("Could not resize the image."));
|
||
}
|
||
}
|
||
|
||
Image.prototype.writeFiles = function(data, thumbnail) {
|
||
if (data) {
|
||
try {
|
||
// If data is a MimeObject (ie. has the writeToFile method)
|
||
// the image was not resized and thus, we directly write it to disk
|
||
var file = this.getFile();
|
||
if (data.saveAs) {
|
||
data.saveAs(file);
|
||
} else if (data.writeToFile) {
|
||
data.writeToFile(file.getParent(), file.getName());
|
||
}
|
||
if (thumbnail) {
|
||
thumbnail.saveAs(this.getThumbnailFile());
|
||
}
|
||
} catch (ex) {
|
||
app.log(ex);
|
||
throw Error(gettext("Could not save the image’s files on disk."));
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
Image.prototype.removeFiles = function() {
|
||
try {
|
||
this.getFile().remove();
|
||
var thumbnail = this.getThumbnailFile();
|
||
if (thumbnail) {
|
||
thumbnail.remove();
|
||
}
|
||
} catch (ex) {
|
||
app.log(ex);
|
||
throw Error(gettext("Could not remove the image's files from disk."));
|
||
}
|
||
return;
|
||
}
|