jive-sdk
Version:
Node.js SDK for Jive Software to assist with the development of add-ons
2,737 lines • 91.6 kB
JavaScript
window.GalleryList = Backbone.Model.extend({
defaults: {
galleryIDs: []
},
useAppData : true,
appDataKey: function() {
return "gallery_list";
},
appDataFields:function () {
return ["gallery_list"];
},
initialize: function() {
},
parse:function(content) {
//there should be only one user
for (var userId in content) {
//there should be only one data
for (var dataId in content[userId]) {
if (dataId && dataId.indexOf('gallery_list') == 0) {
var content = JSON.parse(content[userId][dataId]);
this.set('galleryIDs', content.galleryIDs);
}
}
}
//// ????
for(var i in content) {
this.set(i, content[i]);
}
this.trigger("parsed", this.get("galleryIDs") );
},
add: function( galleryID ) {
var ids = this.get("galleryIDs");
console.log("current", ids);
if ( $.inArray(galleryID, ids) < 0 ) {
ids.push( galleryID );
}
console.log("after", ids);
},
subtract: function( galleryID ) {
var ids = this.get("galleryIDs");
ids.splice(ids.indexOf(galleryID), 1);
}
});
;window.GalleryModel = Backbone.Model.extend({
defaults: {
title: '',
imgIDs: '',
preview: '',
created: 0,
parentList: null
},
useAppData : true,
appDataKey: function() {
if(this.isNew()) {
var create_ts = new Date().getTime();
return $.trim( "gallery_" + create_ts );
} else {
return this.get('id');
}
},
appDataFields:function () {
return [this.get('id')];
},
initialize: function() {
},
parse:function(content) {
//there should be only one user
for (var userId in content) {
//there should be only one data
for (var dataId in content[userId]) {
if (dataId && dataId.indexOf('gallery_') == 0) {
var content = JSON.parse(content[userId][dataId]);
this.set('id', dataId);
this.set('title', content.title);
this.set('imageIDs', content.imageIDs);
this.set('preview', content.preview);
this.set('created', content.created);
}
}
}
//// ????
for(var i in content) {
this.set(i, content[i]);
}
this.trigger("parsed", this );
},
save: function(key, value, options) {
if( this.isNew() ) {
this.set('created', new Date().getTime());
}
//super call
Backbone.Model.prototype.save.call(this, key, value, options);
},
destroy: function(passedData, callback) {
var imgs = (this.get('imgIDs') == '' ? [] : this.get('imgIDs') );
//Delete each image that was in the gallery.
$.each(imgs, function(index, val) {
var data = {imageId: val};
var galleryEntryModel = new GalleryEntry();
galleryEntryModel.destroy( data, function() {
console.log("Destroyed image '" + val + "' in GalleryModel.destroy");
});
});
Backbone.Model.prototype.destroy.call(this);
}
});
;window.GalleryEntry = Backbone.Model.extend({
initialize: function() {
},
fetch:function() {
// override fetch to delegate to submodels for thumb and full source
this.fetchThumb();
this.fetchSource();
},
fetchThumb: function( callback ) {
var imageId = this.get("id");
var thumb = new GalleryImage({id:"thumb_"+ imageId});
var self = this;
thumb.bind("parsed", function( thumbImage ) {
self.trigger("fetchedThumbnail", thumbImage );
if ( callback ) {
callback( thumbImage );
}
});
thumb.fetch();
},
fetchSource: function(callback) {
var imageId = this.get("id");
var full = new GalleryImage({id:"image_"+ imageId});
var self = this;
full.bind("parsed", function( fullImage ) {
self.trigger("fetchedFullSource", fullImage );
if ( callback ) {
callback( fullImage );
}
});
full.fetch();
},
save: function( data, callback ) {
// cascading save (thumbnail first, full image next)
var thumb = new GalleryImage();
thumb.set( {
"id" : "thumb_" + data.imageId,
"src": data.previewSrc,
"width": data.width,
"height": data.height
} );
var onThumbSave = function () {
var fullImage = new GalleryImage();
fullImage.set( {
"id" : "image_" + data.imageId,
"src": data.fullSrc,
"width": data.width,
"height": data.height
} );
fullImage.bind("saved", function() {
callback( data.imageId );
});
fullImage.save();
};
thumb.bind("saved", onThumbSave );
thumb.save();
},
destroy: function( data, callback ) {
// cascading save (thumbnail first, full image next)
var thumb = new GalleryImage();
thumb.set( {
"id" : "thumb_" + data.imageId,
"src": data.previewSrc,
"width": data.width,
"height": data.height
} );
var fullImage = new GalleryImage();
fullImage.set( {
"id" : "image_" + data.imageId,
"src": data.fullSrc,
"width": data.width,
"height": data.height
} );
var onThumbDestroy = function () {
fullImage.destroy();
};
thumb.bind("destroy", onThumbDestroy );
fullImage.bind("saved", function() {
callback( data.imageId );
});
thumb.destroy();
}
});;window.GalleryImage = Backbone.Model.extend({
defaults: {
width: '',
height: 0,
src: '',
created: 0
},
useAppData : true,
appDataKey: function() {
return this.get('id');
},
getImageKey: function() {
return this.get('id');
},
appDataFields:function () {
return [this.get('id')];
},
initialize: function() {
},
parse:function(content) {
//there should be only one user
for (var userId in content) {
//there should be only one data
for (var dataId in content[userId]) {
if (dataId && dataId.indexOf( this.getImageKey() ) == 0) {
var content = JSON.parse(content[userId][dataId]);
this.set('id', dataId);
this.set('width', content.width);
this.set('height', content.height);
this.set('src', content.src);
this.set('created', content.created);
}
}
}
//// ????
for(var i in content) {
this.set(i, content[i]);
}
this.trigger("parsed", this );
},
save: function(key, value, options) {
if( this.isNew() ) {
this.set('created', new Date().getTime());
}
//super call
Backbone.Model.prototype.save.call(this, key, value, options);
},
destroy: function(key, value, options) {
Backbone.Model.prototype.destroy.call(this, key, value, options);
}
});
;function ImageProcessor() {
// private
var imgWidth = 90,
imgHeight = 90,
zindex = 0;
var getDimensions = function(maxWidth, maxHeight, width, height ) {
var neww, newh = 0;
var rw = width / maxWidth; // width and height are maximum thumbnail's bounds
var rh = height / maxHeight;
if (rw > rh)
{
newh = height / rw;
neww = maxWidth;
}
else
{
neww = width / rh;
newh = maxHeight;
}
return {
width: neww,
height: newh
};
};
var compareWidthHeight = function (width, height) {
var diff = [];
if(width > height) {
diff[0] = width - height;
diff[1] = 0;
} else {
diff[0] = 0;
diff[1] = height - width;
}
return diff;
};
//Black & White image effect
//by Marco Lisci - http://badsharkco.com/
var grayscale = function(context) {
var imgd = context.getImageData(0, 0, imgWidth, imgHeight);
var pix = imgd.data;
for (var i = 0, n = pix.length; i < n; i += 4) {
var grayscale = pix[i ] * .3 + pix[i+1] * .59 + pix[i+2] * .11;
pix[i ] = grayscale;
pix[i+1] = grayscale;
pix[i+2] = grayscale;
}
context.putImageData(imgd, 0, 0);
};
//canvas-blur effect
//by Matt Riggott - http://www.flother.com/
var blurry = function(context, image, diff) {
var i, x, y,
blureffect = 4;
context.globalAlpha = 0.1;
for (i = 1; i <= blureffect; i++) {
for (y = -blureffect/2; y <= blureffect/2; y++) {
for (x = -blureffect/2; x <= blureffect/2; x++) {
context.drawImage(image, diff[0]/2, diff[1]/2, image.width-diff[0], image.height-diff[1], x, y, imgWidth, imgHeight);
}
}
}
context.globalAlpha = 1.0;
};
var addNoise = function(ctx, alpha) {
var imageData = ctx.getImageData(0,0, ctx.canvas.width, ctx.canvas.height);
var pixels = imageData.data;
var alpha1 = 1 - alpha;
// Pick the best array length
var rl = Math.round(ctx.canvas.width * 3.73);
var randoms = new Array(rl);
// Pre-calculate random pixels
for (var i = 0; i < rl; i++) {
randoms[i] = Math.random() * alpha + alpha1;
}
// Apply random pixels
for (var i = 0, il = pixels.length; i < il; i += 4) {
pixels[i] = (pixels[i] * randoms[i % rl]) | 0;
}
ctx.putImageData(imageData, 0, 0);
};
var mkImage = function(image, width, height, effect, croping ) {
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext('2d');
//default resize variable
var diff = [0, 0];
if(croping == 'crop') {
//get resized width and height
diff = compareWidthHeight(image.width, image.height);
}
//draw canvas image
ctx.drawImage(image, diff[0]/2, diff[1]/2, image.width-diff[0], image.height-diff[1], 0, 0, width, height);
//addNoise( ctx, 0.2 );
//apply effects if any
if(effect == 'grayscale') {
grayscale(ctx);
} else if(effect == 'blurry') {
blurry(ctx, image, diff);
} else {}
return canvas.toDataURL("image/jpeg", 0.95);
};
var getPreviewImage = function(image) {
var effect = $('input[name=effect]:checked').val();
var croping = $('input[name=croping]:checked').val();
var dimensions = getDimensions(90, 90, image.width, image.height );
return {
width: dimensions.width,
height: dimensions.height,
url: mkImage(image, dimensions.width, dimensions.height, effect, croping )
};
};
var getSourceImage = function(image) {
var effect = $('input[name=effect]:checked').val();
var croping = $('input[name=croping]:checked').val();
var dimensions = getDimensions(350, 350, image.width, image.height );
return {
width: dimensions.width,
height: dimensions.height,
url: mkImage(image, dimensions.width, dimensions.height, effect, croping )
};
};
var randomNum = function(maxVal) {
var maxRandomVal = maxVal ? maxVal : 1000000;
return Math.floor(Math.random()*maxRandomVal);
};
var convertToKBytes = function(number) {
return (number / 1024).toFixed(1);
};
//convert datauri to blob
var dataURItoBlob = function(dataURI) {
var BlobBuilder = window.WebKitBlobBuilder || window.MozBlobBuilder || window.BlobBuilder;
//skip if browser doesn't support BlobBuilder object
if(typeof BlobBuilder === "undefined") {
$('#err').html('Ops! There have some limited with your browser! <br/>New image produced from canvas can\'t be upload to the server...');
return dataURI;
}
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a blob, and you're done
var bb = new BlobBuilder();
bb.append(ab);
return bb.getBlob(mimeString);
};
var buildImage = function( fileName, base64, successCallback ) {
return $('<img/>')
.load(function() {
//when image fully loaded
var thumb = getPreviewImage(this);
var full = getSourceImage(this);
console.log(thumb, full);
var imgData = {};
imgData.imageId = randomNum();
imgData.thumbSrc = thumb.url;
imgData.fullSrc = full.url;
imgData.imageWidth = full.width;
imgData.imageHeight = full.height;
imgData.fileName = fileName.substr(0, fileName.lastIndexOf('.')); //subtract file extension
if ( successCallback ) {
successCallback( imgData );
}
})
.attr('src', base64 );
};
var readFile = function(file, startedCallback, successCallback, errorCallback) {
if( (/image/i).test(file.type) ) {
//define FileReader object
var reader = new FileReader();
startedCallback( file );
//init reader onload event handlers
reader.onload = function(e) {
$('<img/>')
.load(function() {
//when image fully loaded
var thumb = getPreviewImage(this);
var full = getSourceImage(this);
console.log(thumb, full);
var imgData = {};
imgData.imageId = randomNum();
imgData.thumbSrc = thumb.url;
imgData.fullSrc = full.url;
imgData.imageWidth = full.width;
imgData.imageHeight = full.height;
imgData.fileName = file.name.substr(0, file.name.lastIndexOf('.')); //subtract file extension
imgData.fileOriSize = convertToKBytes(file.size);
imgData.fileUploadSize = convertToKBytes(dataURItoBlob(thumb.url).size); //convert new image URL to blob to get file.size
successCallback( file, imgData );
})
.attr('src', e.target.result);
};
//begin reader read operation
reader.readAsDataURL(file);
} else {
//some message for wrong file format
errorCallback(file, '*Selected file format not supported!');
}
};
return {
readFile: readFile,
buildImage: buildImage
};
};window.GalleryPreviewView = (function() {
function getImageUrl(relativeUrl, proxied) {
var gadgetURL = _args()["url"];
var baseURL= gadgetURL.replace(/[a-zA-Z0-9_]+\.xml(\?.*)?/,"");
return proxied ? gadgets.io.getProxyUrl(baseURL + relativeUrl) : baseURL + relativeUrl;
}
return Backbone.View.extend({
events:{
},
generatePreview:function ( imgContainerDom, title, numImages ) {
// uses 3 canvases
function makeStaticSlide(image, $thumbNails, title, numImgs) {
var playGraphic = new Image();
playGraphic.src = getImageUrl("images/play-graphic.png", true);
var embedBgImg = new Image();
embedBgImg.src = getImageUrl("images/background_wood.jpg", true);
/////////////////////////////////
var imgObj = new Image();//necessary to get actual height / width
imgObj.src = $(image).attr("src");
var actualWidth = imgObj.width;
var actualHeight = imgObj.height;
imgObj = null; //To cleanup data from image.
var baseHeight = numImgs == 1 ? 240 : 180;
var baseWidth = 240;
var imageWidth, imageHeight;
var ratio = actualWidth / actualHeight;
if (actualHeight > actualWidth ) {
imageHeight = baseHeight;
imageWidth = imageHeight * ratio;
} else {
imageWidth = baseWidth;
imageHeight = imageWidth * 1/ratio;
}
//For the case where we have > 1 image and the width > height, make sure we didn't make the height too large
//This is needed due to the fact that the above code is for embedding rectangles inside squares, not inside rectangles
if (imageHeight > baseHeight) {
var ratio2 = baseHeight / imageHeight;
imageHeight *= ratio2;
imageWidth *= ratio2;
}
var excessWidth = baseWidth - imageWidth;
var excessHeight = baseHeight - imageHeight;
// var imageWidth = 240, imageHeight = numImgs == 1 ? 240 : 180; //if 1 image, expand to fill
var titleAreaHeight = 40;
var borderWidth = 10, thumbBorderWidth = 13;
var thumbWidth = 50, thumbHeight = 50;
var titleAreaY = Math.max(titleAreaHeight + borderWidth, imageHeight + excessHeight / 2 - titleAreaHeight + borderWidth);
var topLevelCanvas = $('<canvas></canvas>')[0];
var thumbnailCanvas = $('<canvas></canvas>')[0];
var titleCanvas = $('<canvas></canvas>')[0];
topLevelCanvas.width = baseWidth + 2*borderWidth;
topLevelCanvas.height = topLevelCanvas.width;
thumbnailCanvas.width = baseWidth;
thumbnailCanvas.height = thumbHeight;
titleCanvas.width = baseWidth;
titleCanvas.height = titleAreaHeight;
// draw topLevelCanvas background
var topLevelContext = topLevelCanvas.getContext('2d');
topLevelContext.drawImage(embedBgImg, 0, 0, topLevelCanvas.width, topLevelCanvas.height);
// draw thumbnails
var thumbnailContext = thumbnailCanvas.getContext('2d');
var tnLeft = 0;
$thumbNails.each(function(index, thumbNailImg) {
if ( index <=3 ) { //Draw at most 4 images.
thumbnailContext.drawImage(thumbNailImg, tnLeft, 0, thumbWidth, thumbHeight);
tnLeft += (thumbWidth + thumbBorderWidth);
}
});
var imageData = thumbnailContext.getImageData(0, 0, thumbnailCanvas.width, thumbnailCanvas.height);
topLevelContext.putImageData(imageData, borderWidth, borderWidth + baseHeight + borderWidth);
//Draw main image with transparency as specified by Amy
//Must do it this way, putImageData function doesn't work with transparency
topLevelContext.globalAlpha=0.8;
topLevelContext.drawImage(image, borderWidth + excessWidth / 2, borderWidth + excessHeight / 2, imageWidth, imageHeight);
//Draw transparent title area
topLevelContext.globalAlpha=0.4;
topLevelContext.fillStyle="black";
topLevelContext.fillRect(borderWidth, titleAreaY, baseWidth, titleAreaHeight); //Draw the title bar
//Draw the title text
var maxTitleLength = 20;
var wasAbbreviated = false;
var oldTitleLen = title.length;
if (title.length > maxTitleLength) {
wasAbbreviated = true;
}
title = title.slice(0, Math.min(maxTitleLength, title.length)); //limit to 20 chars.
if (wasAbbreviated) {
title += "...";
} else {
for (var i = 0; i < (maxTitleLength - oldTitleLen); i++)
title += " ";
title += " ";
}
title += " (" + numImgs +")";
var fontSize = 14;
topLevelContext.globalAlpha = 1.0;
topLevelContext.font = fontSize + "px Georgia";
topLevelContext.fillStyle="#ffffff";
topLevelContext.fillText(title, borderWidth*2, titleAreaY + titleAreaHeight/2 + fontSize/2);
return topLevelCanvas.toDataURL("image/jpeg");
}
var firstImg = imgContainerDom.find("img").first();
return makeStaticSlide(firstImg[0], imgContainerDom.find("img").slice(1), title, numImages);
},
generateListEntry:function ( imgContainerDom ) {
function makeStaticSlide(image) {
/////////////////////////////////
var imgObj = new Image();//necessary to get actual height / width
imgObj.src = $(image).attr("src");
var actualWidth = imgObj.width;
var actualHeight = imgObj.height;
imgObj = null; //To cleanup data from image.
var baseHeight = 120;
var baseWidth = 120;
var imageWidth, imageHeight;
var ratio = actualWidth / actualHeight;
if (actualHeight > actualWidth ) {
imageHeight = baseHeight;
imageWidth = imageHeight * ratio;
} else {
imageWidth = baseWidth;
imageHeight = imageWidth/ratio;
}
//For the case where we have > 1 image and the width > height, make sure we didn't make the height too large
//This is needed due to the fact that the above code is for embedding rectangles inside squares, not inside rectangles
if (imageHeight > baseHeight) {
var ratio2 = baseHeight / imageHeight;
imageHeight *= ratio2;
imageWidth *= ratio2;
}
var excessWidth = baseWidth - imageWidth;
var excessHeight = baseHeight - imageHeight;
var borderWidth = 10;
var topLevelCanvas = $('<canvas></canvas>')[0];
topLevelCanvas.width = baseWidth + 2*borderWidth;
topLevelCanvas.height = topLevelCanvas.width;
var rotatedCanvas = $('<canvas></canvas>')[0];
rotatedCanvas.width = baseWidth + 2*borderWidth;
rotatedCanvas.height = rotatedCanvas.width;
var adj = baseHeight * 0.05;
var rotatedContext = rotatedCanvas.getContext('2d');
rotatedContext.globalAlpha=0.4;
rotatedContext.rotate(-0.1);
rotatedContext.lineWidth = 1;
rotatedContext.strokeStyle = 'red';
rotatedContext.rect((borderWidth + excessWidth / 2)-adj, (borderWidth + excessHeight / 2)+adj, imageWidth, imageHeight);
rotatedContext.drawImage(image, (borderWidth + excessWidth / 2)-adj, (borderWidth + excessHeight / 2)+adj, imageWidth-1, imageHeight-1);
rotatedContext.stroke();
rotatedContext.globalAlpha=1.0;
debugger;
var imageData = rotatedContext.getImageData(0, 0, rotatedCanvas.width, rotatedCanvas.height);
// draw topLevelCanvas background
var topLevelContext = topLevelCanvas.getContext('2d');
topLevelContext.fillStyle="blue";
topLevelContext.fillRect(0,0, baseWidth, baseHeight); //Draw the title bar
topLevelContext.putImageData(imageData, 0,0);
topLevelContext.drawImage(image, borderWidth + excessWidth / 2, borderWidth + excessHeight / 2, imageWidth, imageHeight);
topLevelContext.lineWidth = 1;
topLevelContext.strokeStyle = 'red';
topLevelContext.rect((borderWidth + excessWidth / 2), (borderWidth + excessHeight / 2), imageWidth, imageHeight);
topLevelContext.stroke();
return topLevelCanvas.toDataURL("image/jpeg");
}
var firstImg = imgContainerDom.find("img").first();
return makeStaticSlide(firstImg[0]);
}
});
})();;window.GalleryListItemView = Backbone.View.extend({
events:{
},
initialize:function () {
},
render:function () {
var gallery = this.model;
$(this.el).html(
$(_.template(this.options.container.getTemplate('#GalleryListItem'), {
"title" : gallery.get("title"),
"galleryID" : gallery.get("id"),
"listSrc" : gallery.get("list")
} ) )
);
return this.el;
},
createNewGallery : function() {
Backbone.history.navigate('gallery-create', true);
return false;
}
});
;window.GalleryListView = Backbone.View.extend({
events:{
"click #btn_create_an_album" : "createNewGallery"
},
initialize:function () {
this.collection = new GalleryList();
},
render:function () {
},
createNewGallery : function() {
Backbone.history.navigate('gallery-create', true);
return false;
},
renderNoGalleries: function() {
$(this.el).html(_.template(this.options.container.getTemplate('#GalleryListNone') ) );
},
renderGalleries: function() {
$(this.el).html(_.template(this.options.container.getTemplate('#GalleryList')));
},
renderGallery: function( gallery ) {
var galleryListItemView = new GalleryListItemView( {model: gallery, container: this.options.container } );
var galleryListItemDom = galleryListItemView.render();
$(galleryListItemDom).attr("name", gallery.get('created'));
var dom = $(this.el);
var container = dom.find("#listcontent");
var galleries = dom.find("#listcontent > .j-album");
if (galleries.length <= 0) {
container.append( galleryListItemDom );
}
else { //Insert in order
var wasInserted = false;
for (var i = 0; i < galleries.length; i++) {
if ($(galleries[i]).attr("name") > gallery.get('created')) {
$(galleries[i]).before(galleryListItemDom);
wasInserted = true;
break;
}
}
if (! wasInserted ) {
container.append(galleryListItemDom);
}
}
return this.el;
}
});
;window.GalleryEditView = Backbone.View.extend({
didNotChangeImages: true,
events:{
"click #uploadbtn" : "triggerUpload",
"click #link_save" : "saveGallery",
"click #link_cancel" : "cancelEdit",
"change #upload" : "uploadFiles",
"drop #result" : "uploadFiles"
},
initialize:function (options) {
this.render();
this.imageProcessor = new ImageProcessor();
},
render:function () {
var dom = $(this.el);
var resultDom = dom.find("#result");
dom.html(_.template(this.options.container.getTemplate('#GalleryEdit')));
resultDom.sortable().disableSelection();
},
deactivateIE: function() {
var dom = $(this.el);
var ieUploadButton = dom.find("#ieUpload");
ieUploadButton.hide();
},
setupIE: function() {
debugger;
var dom = $(this.el);
var ieUploadButton = dom.find("#ieUpload");
dom.find("#upload-files").hide();
var base = gadgets.util.getUrlParameters()["url"].replace("/app.xml", "");
var imageto46 = gadgets.io.getProxyUrl(base + "/flashupload/bin/flashupload.swf?cachebust=" + Math.random());
var expressInstall = gadgets.io.getProxyUrl(base + "/flashupload/expressInstall.swf");
var version = "10.0.0";
$.fn.addFlashUpload = function() {
return this.each(function() {
var $this = $(this);
var uploadId = "flashUpload-" + $.fn.addFlashUpload.id++;
var width = $this.outerWidth();
var height = $this.outerHeight();
var position = $this.css("position");
// this span will get replaced by the Flash content
$this.attr("data-uploadid", uploadId).append('<span id="' + uploadId + '"></span>');
// be sure the parent (button) has relative/absolute positioning so that our Flash can sit on top
if (position !== "absolute" && position !== "relative") {
$this.css("position", "relative");
}
// pass in the uploadId to the Flash for it to pass back out on upload
var flashvars = {
uploadId: uploadId
};
// make transparent and able to access JavaScript
var params = {
wmode: "transparent",
allowscriptaccess: "always"
};
// position over the top of the button the Flash is inside of
var attributes = {
style: "position: absolute; z-index: 100; left: 0; right: 0; top: 0; bottom: 0;"
};
// embed the Flash
swfobject.embedSWF(imageto46, uploadId, width, height, version, expressInstall, flashvars, params, attributes);
});
};
$.fn.addFlashUpload.id = 1;
// handle the uploads and use jQuery's events to notify listeners of this button's upload
window.processBase64Encodings = function( fileName, fileData, uploadId ) {
$( "[data-uploadid=" + uploadId + "]" ).trigger( "upload", [ fileName, fileData ] );
};
//
ieUploadButton.addFlashUpload().bind( "upload", function( event, fileName, fileData ) {
var mime = fileName.split(".").pop();
if (mime === "jpg") mime = "jpeg";
var container = this.options.container;
var successCallback = function(imgData ) {
var galleryEntryView = new GalleryEntryView({ container: container });
var imgDom = galleryEntryView.render(imgData);
imgDom.prependTo("#result")
.hide()
.css({ 'z-index':self.zindex++ })
.show();
$("#link_save").show();
};
this.imageProcessor.buildImage( fileName, "data:image/" + mime + ";base64," + fileData, successCallback );
});
},
renderGallery: function( gallery ) {
var dom = $(this.el);
var title = gallery.get("title");
if ( title ) {
dom.find("#gallery_title").val(title);
} else {
dom.find("#gallery_title").val(this.prettyDate(new Date()) );
}
// load images
var ids = gallery.get("imgIDs");
if ( !ids || ids.length < 1 ) {
// nothing else to do if there are no images
return;
}
console.log("Prepping image id manifest", ids);
var galleryEntryMap = {};
var container = this.options.container;
// pre-seed the gallery entry doms
$.each( ids, function() {
var imageId = this;
var model = new GalleryEntry({id: imageId});
var view = new GalleryEntryView({model: model, container: container });
galleryEntryMap[imageId] = { view: view, model: model };
var entryDom = view.render();
dom.find("#result").append( entryDom );
});
// now load
$.each( ids, function() {
var imageId = this;
console.log("loading image id " + imageId );
var galleryEntry = galleryEntryMap[imageId];
var model = galleryEntry.model;
var view = galleryEntry.view;
model.bind("fetchedThumbnail", function(thumbImage) {
view.renderThumbnail(thumbImage);
});
model.bind("fetchedFullSource", function(fullImage) {
view.attachFullImageSource(fullImage);
});
model.fetch();
});
var that = this;
$(this.el).find("#result").sortable();
$(this.el).find("#result img").draggable();
// $(this.el).find("#trashcan_img").droppable({
// //accept: "#result img",
// tolerance: "touch",
// drop: function(event, ui) {
// //remove image from the DOM. Upon saving it will be removed
// ui.draggable.remove();
// },
// activate: function(event, ui) {
// $(that.el).find("#trashcan_img").hide();
// $(that.el).find("#trashcan_img_active").show();
// },
// deactivate: function(event, ui) {
// $(that.el).find("#trashcan_img_active").hide();
// $(that.el).find("#trashcan_img").show();
// }
//
// });
},
triggerUpload: function() {
$("#upload").click();
},
saveGallery: function() {
var dom = $(this.el);
var gallery = this.model;
var images = dom.find("#result img");
if ( images.length < 1 ) {
console.log("Nothing to save");
return;
}
//First pass, generate new IDs, set -1 if it didn't have one already (new image)
var imageIDs = [];
$.each( images, function() {
var image = $(this);
var imageID = image.attr("data-id") || -1; //-1 means we need to gen a new ID
imageIDs.push(imageID);
});
//Second pass--generate random IDs, checking that they don't exist already.
for (var i = 0; i < imageIDs.length; i++) {
if (imageIDs[i] === -1) {
do {
var newId = randomNum();
} while (imageIDs.indexOf(newId) >= 0);
imageIDs[i] = newId;
}
}
// save gallery images first
var container = this.options.container;
this.saveGalleryImages( images, imageIDs, function() {
var title = dom.find("#gallery_title").val();
var previewView = new GalleryPreviewView({ container: container });
$.each( images, function() {
var i = $(this);
var t = $("<img>").attr("src", i.attr("data-fullsrc"));
$("#secret").append(t);
});
window.setTimeout( function() {
var previewSrc = previewView.generatePreview($("#secret"), title, images.length);
var listSrc = previewView.generateListEntry($("#secret"));
gallery.set( {
"title": title,
"imgIDs": imageIDs,
"preview": previewSrc,
"list": listSrc
} );
// tell the gallery model to save itself
gallery.save();
}, 150);
});
},
saveGalleryImages: function(images, imageIDs, successCallback) {
var savedCount = 0;
var destroyCount = 0;
var gallery = this.model;
var oldIDs = gallery.get('imgIDs') == "" ? [] : gallery.get('imgIDs');
//figure out difference between oldIDs and imageIDs in DOM (previous gallery state vs. new state)
var toDelete = [];
var toUpload = [];
var that = this;
//Go through the new IDs, and mark for upload if they're not in the old IDs
$.each(imageIDs, function(index, imgId) {
if (oldIDs.indexOf(imgId) < 0) {
toUpload.push(
{
id: imgId,
dom: $(that.el).find("#result").find("[data-id=" + imgId + "]")[0]
}); //place new ID (may be generated) and img element in array
}
});
//Go through the old IDs, and mark for deletion if they're not in the new IDs
$.each(oldIDs, function(index, imgId) {
if (imageIDs.indexOf(imgId) < 0 ) {
toDelete.push({ id: imgId }); //for deleting, just push ID
}
});
//Callback so that images are deleted sequentially after saving.
var deleteImagesAfterSaving = function() {
if (toDelete.length == 0) {
successCallback();
}
$.each( toDelete, function(index, value) {
destroyCount++;
var data = {
imageId : value.id
};
var callback = function( theID ) {
console.log("Destroyed image id " + theID + " source");
};
var galleryEntryModel = new GalleryEntry();
galleryEntryModel.destroy( data, callback );
if ( destroyCount == toDelete.length ) {
console.log("Done destroying " + destroyCount);
successCallback();
}
})
};
if (toUpload.length == 0) { //Don't make a save request if there are no images to upload
deleteImagesAfterSaving();
} else {
$.each( toUpload, function(index, value) {
var image = $(value.dom);
var data = {
previewSrc: image.attr("src"),
fullSrc : image.attr("data-fullsrc"),
width : image.attr("data-width"),
height : image.attr("data-height"),
imageId : value.id
};
var callback = function( imageId ) {
console.log("Saved image id " + imageId + " source");
savedCount++;
if ( savedCount == toUpload.length) {
console.log("Done saving " + savedCount);
deleteImagesAfterSaving();
}
};
var galleryEntryModel = new GalleryEntry();
galleryEntryModel.save( data, callback ); //Callback = delete imgs in toDelete
});
}
},
cancelEdit: function() {
Backbone.history.navigate('gallery-edit-cancel', true);
},
uploadFiles: function(event) {
var self = this;
if (event.originalEvent && event.originalEvent.dataTransfer && event.originalEvent.dataTransfer.files) {
event.preventDefault();
var files = event.originalEvent.dataTransfer.files;
} else {
var files = event.target.files;
}
this.didNotChangeImages = false;
var startedCallback = function(file) {
$("#link_save").hide();
};
var successCallback = function(file, imgData ) {
var galleryEntryView = new GalleryEntryView({ container: self.options.container });
var imgDom = galleryEntryView.render(imgData);
imgDom.prependTo("#result")
.hide()
.css({ 'z-index':self.zindex++ })
.show();
$("#link_save").show();
};
var errorCallback = function(file, error) {
alert(error);
};
if(files && typeof FileReader !== "undefined") {
//process each files only if browser is supported
for(var i=0; i<files.length; i++) {
this.imageProcessor.readFile(
files[i],
startedCallback,
successCallback,
errorCallback
);
}
} else {
// hmm??
// xxx todo -- a good error!
debugger;
}
},
prettyDate: function(date) {
function pad(number) {
var r = String(number);
if ( r.length === 1 ) {
r = '0' + r;
}
return r;
}
//It makes me cry that this isn't provided by javascript
function getPrettyMonth(m) {
switch (m) {
case 0: return "Jan.";
case 1: return "Feb.";
case 2: return "Mar.";
case 3: return "Apr.";
case 4: return "May";
case 5: return "June";
case 6: return "July";
case 7: return "Aug.";
case 8: return "Sep.";
case 9: return "Oct.";
case 10: return "Nov.";
case 11: return "Dec.";
}
return ""; //fail
}
function getPrettyTime(h, m) {
return ( (h % 12 == 0) ? "12" : ( h % 12 ) ) + ":" + pad(m) + (h < 12 ? " AM" : " PM");
}
return getPrettyMonth(date.getMonth())
+ ' ' + date.getDate()
+ ', ' + date.getFullYear()
+ ' ' + getPrettyTime( date.getHours(), date.getMinutes());
}
});
;window.GalleryEntryView = Backbone.View.extend({
events:{
},
render:function (imgData) {
if ( !imgData ) {
// render a blank entry
var imageId = this.model.get("id");
imgData = {
"thumbSrc" : app.getProxiedUrl("/images/ajax_loader_large.gif"),
"imageId" : imageId,
"fileName" : "",
"fullSrc" : "",
"imageWidth" : "90",
"imageHeight" : "90"
};
$(this.el).html( _.template(this.options.container.getTemplate('#GalleryEntry'), imgData ) );
this.imgDom = $(this.el).find("img");
} else {
// render according to imgData
this.imgDom = $(_.template(this.options.container.getTemplate('#GalleryEntry'), imgData ));
$(this.el).html( this.imgDom );
}
return this.imgDom;
},
renderThumbnail: function( thumb ) {
var previewSrc = thumb.get("src");
var width = thumb.get("width");
var height = thumb.get("height");
this.imgDom.attr("src", previewSrc);
this.imgDom.attr("data-width", width);
this.imgDom.attr("data-height", height);
return this.imgDom;
},
attachFullImageSource: function( fullImage ) {
var fullSrc = fullImage.get("src");
this.imgDom.attr("data-fullsrc", fullSrc);
}
});
;window.GalleryViewer = Backbone.View.extend({
events:{
"click #close" : "close"
},
initialize:function () {
},
close: function() {
osapi.jive.core.container.closeApp();
},
render:function () {
var gallery = this.model;
var dom = $(this.el);
dom.html(_.template(this.options.container.getTemplate('#GalleryViewer'), {
"title": gallery.get("title")
} ) );
var ids = gallery.get("imgIDs");
var sourceToProcessQueue = new Array();
var loadCount = 0;
var loaded = function( loadCount) {
if ( loadCount < ids.length ) {
return;
}
console.log(loadCount, "versus", ids.length );
console.log("Loaded " + loadCount++);
$(".j-loading").hide();
$(".slideshow").show();
gadgets.window.adjustWidth();
$('.slideshow').cycle({
next : "#next", // JQuery selector for "next" control
pause: 1, // Pause transitions when mouse is over the image
prev : "#previous", // JQuery selector for "previous" control
speed: 100, // Time to complete a cycle (ms)
timeout: 5000, // Time between cycles (ms)
pager: "#pager",
pagerAnchorBuilder: function(idx, slide) {
// return selector string for existing anchor
return '#pager li:eq(' + idx + ') a';
}
});
window.setTimeout( function() {
$.each( sourceToProcessQueue, function() {
var fn = this;
fn();
});
}, 2000 );
};
console.log("Prepping image id manifest", ids);
var galleryEntryMap = {};
var containerHeight = dom.find(".slideshow").css("height").replace('px','');
var containerWidth = dom.find(".slideshow").css("width").replace('px','');
// pre-seed the gallery entry doms
var container = this.options.container;
$.each( ids, function() {
var imageId = this;
var model = new GalleryEntry({id: imageId });
var view = new GalleryEntryView({model: model, container: container });
galleryEntryMap[imageId] = { view: view, model: model };
var entryDom = view.render();
entryDom.hide();
var thumb = entryDom.clone().css("width",50).css("height", 50).show();
dom.find(".slideshow").append( entryDom );
var li = $("<li></li>");
var a = $("<a href='#'></a>");
li.append( a.append( thumb ) );
dom.find("#pager").append( li );
});
// now load
$.each( ids, function() {
var imageId = this;
console.log("loading image id " + imageId );
var galleryEntry = galleryEntryMap[imageId];
var model = galleryEntry.model;
var view = galleryEntry.view;
model.fetchThumb( function(thumbImage) {
var dom = view.renderThumbnail(thumbImage);
$("#pager img[data-id=" + imageId + "]")
.attr("src", thumbImage.get("src"));
dom.css("width", thumbImage.get("width") * 1.5 );
dom.css("height", thumbImage.get("height") * 1.5 );
var containerHeight = $(".slideshow").css("height").replace('px','');
var containerWidth = $(".slideshow").css("width").replace('px','');
var imgWidth = dom.css("width").replace('px','');
var imgHeight = dom.css("height").replace('px','');
var deltaWidth = containerWidth - imgWidth;
var deltaHeight = containerHeight - imgHeight;
dom.css("margin-left", deltaWidth / 2);
dom.css("margin-top", deltaHeight / 2);
loadCount++;
loaded(loadCount);
sourceToProcessQueue.push( function() {
model.fetchSource( function( source ) {
console.log("loaded image id " + imageId );
var fullSrc = source.get("src");
var imgDom = $(".slideshow img[data-id=" + imageId + "]");
imgDom.show();
imgDom.attr("src", fullSrc);
});
});
});
});
return this.el;
}
});;function Container() {
return {
mostRecentSize:{ width:0, height:0 },
props: {},
appContext: {},
getValue:function (object, prop) {
if (!(object && object[prop])) return null;
return _.isFunction(object[prop]) ? object[prop]() : object[prop];
},
sync:function (method, model, options) {
if (model.useAppData /* && model.appDataKey && model.appDataFields */) {
// Ensure that we have the appropriate request data.
if (!options.data && model && (method == 'create' || method == 'update')) {
var data = model.toJSON();
var key = model.appDataKey();
var obj = {};
obj[key] = JSON.stringify(data);
osapi.appdata.update({
data:obj,
userId:'@me',
escapeType:opensocial.EscapeType.NONE
}).execute(function (response) {
if (response.error) {
console.log("update error", response.error);
if (options.error) {
options.error( response.error);
}
} else {
console.log("update response", response);
model.set('id', key);
if (options.postSuccess) {
options.postSuccess(model);
}
model.trigger("saved");
}
});
} else if (method == 'read') {
var payload = {
userId:'@me',
fields:model.appDataFields(),
escapeType:opensocial.EscapeType.NONE
};
osapi.appdata.get(payload).execute(function (response) {
if (response.error) {
console.log("fetch error", response.error);
if (options.error) {
options.error( response.error );
}
}
else {
model.parse(response);
if (options.postSuccess) {
options.postSuccess(model);
}
}
});
} else if (method == 'delete') {
var payload = {
keys:model.appDataFields(),
userId:'@me'
};
console.log("to remove", payload);
osapi.appdata['delete'](payload).execute(function (response) {
if (response.error) {
console.log("delete error", response.error);
if (options.error) {
options.error(response.error);
}
}
else {
if (options.postSuccess) {
options.postSuccess(model);
}
model.trigger("deleted");
}
});
}
} else {
// a call to some resource local to the app?
var base = gadgets.util.getUrlParameters()['url'];
base = base.substring(0, base.lastIndexOf('/'));
var href = base + this.getValue(model, 'url') + "?ts=" + new Date().getTime();
var payload = { 'href':href, 'format':'json', 'authz':null }; // xxx AUTHZ is unsigned for now!!! REMOVE THIS HACK WHEN GOING AGAINST REAL SERVICE
if (model.headers) {
payload.headers = this.getValue(model, 'headers');
}
payload.callback = function (data) {
if (data.status == 200 || data.status == 204) {
model.parse(data.content);
if (options.postSuccess) {
options.postSuccess(model, data);
}
} else {
var resp;
if (data.content && data.content.jiveFault) {
resp = data.content;
} else {
resp = {"jiveFault":{"stackTrace":"", "errorMessage":data.status, "errorCode":"UNKNOWN_ERROR", "requestId":"", "blocking":false}};
}
options.error(model, resp);
}
};
if ((method == "read" && model.postForRead) || method == 'create') {
osapi.http.post(payload).execute(payload.callback);
} else if (method == "read") {
osapi.http.get(payload).execute(payload.callback);
} else {
alert('Unsupported method');
}
}
},
loadExperience:function () {
var container = this;
$.get(gadgets.io.getProxyUrl(gadgets.util.getUrlParameters()['url'].replace(/(\/app.xml)|(\/gadget.xml)/, '/templates.html')) + "&nocache=1",
function(templates) {
container.$templates = $(templates);
$('body').append(templates);
var experience = container.appContext.defaultRoute || 'main';
Backbone.history.navigate( experience, true );
});
},
getTemplate: function(selector) {
return this.$templates.filter(selector).html();
},
httpPost:function (options) {
var base = gadgets.util.getUrlParameters()['url'];
base = base.substring(0, base.lastIndexOf('/'));
var payload = {
'href':base + this.getValue(options, 'url'),
'format':'json',
'authz':'signed'
};
if (options.headers) {
payload.headers = this.getValue(options, 'headers');
}
if (options.data) {
payload.body = JSON.stringify(this.getValue(options, 'data'));
}
osapi.http.post(payload).execute(function (data) {
if (data.status == 200 || data.status == 204) {
options.success(data.content);
} else {
var resp;
if (data.content && data.content.jiveFault) {
resp = data.content;
} else {
resp = {"jiveFault":{"stackTrace":"", "errorMessage":data.status, "errorCode":"UNKNOWN_ERROR", "requestId":"", "blocking":false}};
}
//TODO: Generic Error Handling
if (options.error) {
options.error(resp);
}
}
});
},
httpGet:function (options) {
var base = gadgets.util.getUrlParameters()['url'];
base = base.substring(0, base.lastIndexOf('/'));
var payload = {
'href':base + this.getValue(options, 'url'),
'format':'json',
'authz':'signed'
};
if (options.headers) {
payload.headers = this.getValue(options, 'headers');
}
osapi.http.get(payload).execute(function (data) {
if (data.status == 200 || data.status == 204) {
options.success(data.content);
} else {
var resp;
if (data.content && data.content.jiveFault) {
resp = data.content;
} else {
resp = {"jiveFault":{"stackTrace":"", "errorMessage":data.status, "errorCode":"UNKNOWN_ERROR", "requestId":"", "blocking":false}};
}
//TODO: Generic Error Handling
if (options.error) {
options.error(resp);
}
}
});
},
getProxyUrl:function (url) {
return gadgets.io.getProxyUrl(url) + "&nocache=" + gadgets.util.getUrlParameters()['nocache'];
},
close:function (closeEvents) {
if (closeEvents) {
osapi.jive.core.container.closeApp({data:{events:closeEvents}});
} else {
osapi.jive.core.container.closeApp();
}
},
getViewerId:function () {
return opensocial.data.getDataContext().getDataSet('sbsContext').user.userID;
},
adjustSize:function () {
this.adjustWidth();
this.adjustHeight();
},
adjustWidth:function (opt_width) {
if (gadgets.window.adjustWidth) {
gadgets.window.adjustWidth(opt_width);
}
},
adjustHeight:function (opt_height) {
if (gadgets.window.adjustHeight) {
gadgets.window.adjustHeight(opt_height);
}
},
windowWidthHasChanged:function (opt_width) {
var thisWidth = parseInt(opt_width || gadgets.window.getWidth(), 0);
if (thisWidth == this.mostRecentSize.width)
return false;
this.mostRecentSize.width = thisWidth;
return true;
},
windowHeightHasChanged:function (opt_height) {
var thisHeight = parseInt(opt_height || gadgets.window.getHeight(), 0);
if (thisHeight == this.mostRecentSize.height)
return false;
this.mostRecentSize.height = thisHeight;
return true;
},
getUser:function (owner, callback) {
osapi.people.get({"userId": owner}).execute(callback);
},
setProps: function( props ) {
this.props = props;
},
getProps: function() {
return this.props;
},
setAppContext: function( context ) {
if ( context ) {
this.appContext = context;
}
},
getAppContext: function() {
return this.appContext;
}
};
}
;window.GalleryController = function(container, viewManager) {
this.viewManager = viewManager;
this.container = container;
this.galleryCreate = function () {
var galleryModel = new GalleryModel();
var galleryEditView = new GalleryEditView({model:galleryModel, container: this.container });
if ( !$.browser.msie ) {
galleryEditView.deactivateIE();
}
this.viewManager.showView(galleryEditView);
if ( $.browser.msie ) {
galleryEditView.setupIE();
}
galleryModel.bind("saved", function () {
var galleryID = galleryModel.get("id");
var galleryListModel = new GalleryList();
galleryListModel.bind("saved", function () {
Backbone.history.navigate('gallery-saved/' + galleryID, true);
});
galleryListModel.bind("parsed", function () {
galleryListModel.add(galleryID);
galleryListModel.save();
});
galleryListModel.fetch();
});
galleryEditView.renderGallery(galleryModel);
};
this.galleryEdit = function (galleryID) {
var galleryModel = new GalleryModel({id:galleryID});
var galleryEditView = new GalleryEditView({model:galleryModel, container: this.container });
if ( !$.browser.msie ) {
galleryEditView.deactivateIE();
}
viewManager.showView(galleryEditView);
if ( $.browser.msie ) {
galleryEditView.setupIE();
}
galleryModel.bind('parsed', function (gallery) {
galleryEditView.renderGallery(gallery);
});
galleryModel.bind("saved", function () {
var galleryListModel = new GalleryList();
galleryListModel.bind("saved", function () {
Backbone.history.navigate('gallery-saved/' + galleryID, true);
});
galleryListModel.bind("parsed", function () {
galleryListModel.add(galleryID);
galleryListModel.save();
});
galleryListModel.fetch();
});
galleryModel.fetch();
};
this.galleryDelete = function (galleryID) {
var galleryModel = new GalleryModel({id:galleryID});
galleryModel.bind("deleted", function () {
var galleryListModel = new GalleryList();
galleryListModel.bind("saved", function () {
Backbone.history.navigate('main', true);
});
galleryListModel.bind("parsed", function () {
galleryListModel.subtract(galleryID);
galleryListModel.save();
});
galleryListModel.fetch();
});
galleryModel.fetch( {
postSuccess: function(model) {
model.destroy();
},
error: function(model, response) {
console.log("Error fetching Gallery Model to be deleted", response);
}
});
};
this.galleryDrop = function (galleryID) {
var model = new GalleryModel({id:galleryID});
model.fetch({postSuccess:function () {
// xxxx todo move this
function getImageUrl(relativeUrl, proxied) {
var gadgetURL = _args()["url"];
var baseURL = gadgetURL.replace(/[a-zA-Z0-9_]+\.xml(\?.*)?/, "");
return proxied ? gadgets.io.getProxyUrl(baseURL + relativeUrl) : baseURL + relativeUrl;
}
osapi.jive.corev3.people.get({id:"@me"}).execute(function (result) {
var id = result.id;
var outgoing = {
display:{
"type":"image",
"previewImage":getImageUrl("images/1x1.GIF")
},
target:{
"type":"embed",
"view":"show",
"context":{
"galleryID":galleryID
}
}
};
osapi.jive.version.getVersionInfo().execute(function (data) {
osapi.jive.core.container.artifacts.create(outgoing, 'com.jivesoftware.inline.gallery.show',
function (markupResponse) {
var artifactMarkup = markupResponse.markup, error = markupResponse.error;
var artifactDom = $('<span>' + artifactMarkup + '</span>');
artifactDom.find('a').html('<img src="' + model.get("preview") + '"/>');
var html = artifactDom.html() + "<div>" + artifactMarkup + "</div>";
osapi.jive.core.container.editor().insert(html);
}, false, true);
});
});
}});
};
this.galleryView = function( galleryID ) {
var gallery = new GalleryModel({id:galleryID});
var view = new GalleryViewer({model: gallery, container: this.container });
var viewManager = this.viewManager;
gallery.bind("parsed", function(gallery) {
view.render();
viewManager.showView(view);
});
gallery.fetch();
};
}
;window.GalleryListController = function(container, viewManager) {
this.viewManager = viewManager;
this.container = container;
this.galleryList = function () {
var galleryListModel = new GalleryList();
var galleryListView = new GalleryListView({ container: this.container });
galleryListModel.bind('parsed', function (galleryIDs) {
if (!galleryIDs || galleryIDs.length < 1) {
galleryListView.renderNoGalleries();
}
else {
galleryListView.renderGalleries();
$.each(galleryIDs, function () {
var galleryID = this;
var gallery = new GalleryModel({id:galleryID});
gallery.bind('parsed', function (gallery) {
galleryListView.renderGallery(gallery);
});
gallery.fetch();
});
}
});
galleryListView.render();
this.viewManager.showView(galleryListView);
galleryListModel.fetch();
}
}
;function Router() {
var defaultRoutes = {
'main' : 'showMain',
'gallery-create' : 'galleryCreate',
'gallery-edit/:id' : 'galleryEdit',
'gallery-edit-cancel' : 'galleryEditCancel',
'gallery-delete/:id' : 'galleryDelete',
'gallery-drop/:id' : 'galleryDrop',
'gallery-select/:id' : 'galleryDrop',
'gallery-view/:id' : 'galleryView',
'gallery-saved/:id' : 'gallerySaved',
'close' : 'close',
'*actions' : 'defaultAction'
};
var container;
var AppRouter = Backbone.Router.extend({
showMain:function () {
this.galleryList();
},
galleryList: function() {
this.galleryListController.galleryList();
},
galleryCreate:function () {
this.galleryController.galleryCreate();
},
galleryEdit:function (galleryID) {
this.galleryController.galleryEdit(galleryID);
},
galleryEditCancel:function (galleryID) {
this.showMain();
},
galleryDelete:function (galleryID) {
this.galleryController.galleryDelete(galleryID);
},
gallerySaved:function (galleryID) {
this.showMain();
},
galleryDrop:function (galleryID) {
this.galleryController.galleryDrop(galleryID);
},
galleryView:function(galleryID ) {
this.galleryController.galleryView(galleryID);
},
close: function() {
osapi.jive.core.container.closeApp();
},
defaultAction:function () {
container.loadExperience();
}
});
var initialize = function (appContainer) {
var routes = defaultRoutes;
container = appContainer;
// override any routes according to context
var appContext = container.getAppContext();
if ( appContext ) {
var routeOverrides = appContext.routes;
if ( routeOverrides ) {
for (var key in routeOverrides) {
if (routeOverrides.hasOwnProperty(key)) {
var val = routeOverrides[key];
if ( val ) {
routes[key] = val;
}
}
}
}
}
var app_router = new AppRouter( {
routes: routes
});
var viewManager = new ViewManager();
app_router.galleryListController = new GalleryListController(container, viewManager);
app_router.galleryController = new GalleryController(container, viewManager);
Backbone.history.start();
};
return {
initialize:initialize
};
}
;function App() {
var container = new Container();
var initialize = function ( context ) {
if ( context ) {
container.setAppContext( context );
}
if ( container.initialize) {
container.initialize();
}
var router = new Router();
router.initialize(container);
};
Backbone.sync = function (method, model, options) {
container.sync(method, model, options);
};
Backbone.View.prototype.close = function () {
this.remove();
this.unbind();
if (this.onClose) {
this.onClose();
}
};
return {
initialize: initialize,
getAbsoluteUrl: function(path) {
return gadgets.util.getUrlParameters()['url'].replace(/(\/app.xml)|(\/gadget.xml)/, path);
},
getProxiedUrl: function(path) {
return gadgets.io.getProxyUrl(gadgets.util.getUrlParameters()['url'].replace(/(\/app.xml)|(\/gadget.xml)/, path)) + "&nocache=1";
}
};
};var jigPersistence = function( userId ) {
userId = userId || '@me';
var fetch = function( fields, success, error ) {
if ( fields.length < 1 ) {
var options = {
userId: userId,
escapeType: opensocial.EscapeType.NONE
};
} else {
var options = {
fields : fields,
userId: userId,
escapeType: opensocial.EscapeType.NONE
};
}
osapi.appdata.get( options ).execute(function(response) {
if (response.error) {
console.log( "fetch error", response.error );
if ( error ) error();
}
else {
if ( success ) success(response);
}
});
};
var remove = function( fields, success, error ) {
var options = {
keys : fields,
userId: '@me'
};
console.log( "to remove", options );
osapi.appdata['delete']( options ).execute(function(response) {
if (response.error) {
console.log( "delete error", response.error );
if ( error ) error();
}
else {
if ( success ) success(response);
}
});
};
var update = function( key, value, success, error ) {
var obj = {};
obj[key] = value;
osapi.appdata.update({
data : obj,
userId: '@me',
escapeType: opensocial.EscapeType.NONE
}).execute(function(response) {
if (response.error) {
console.log( "update error", response.error );
if ( error ) error();
} else {
console.log( "update response", response );
if ( success ) success();
}
});
};
this.save = function ( json, success, key ) {
update( key || "jig", json, success );
};
this.load = function( success, key) {
fetch( [key], function( response ) {
// get data for the first user (should be only one anyway)
var theData;
for( var user in response ) {
if(response.hasOwnProperty(user)) {
theData = response[user];
break;
}
}
for( var id in theData ) {
console.log( theData );
if (theData.hasOwnProperty(id) ) {
var raw = theData[key || "jig"];
if ( raw ) {
var json = JSON.parse( raw );
success( json );
return;
}
}
}
success(null);
});
};
};
;gadgets.util.registerOnLoadHandler(function() {
var didNotChangeImages = true;
var playGraphic = new Image();
$(document).ready(function() {
playGraphic.src = app.getProxiedUrl("/images/play-graphic.png");
/*****************************
Variables
*****************************/
var imgWidth = 90,
imgHeight = 90,
zindex = 0;
dropzone = $('#result'),
uploadBtn = $('#uploadbtn'),
defaultUploadBtn = $('#upload');
/*****************************
Events Handler
*****************************/
dropzone.on('dragover', function() {
//add hover class when drag over
dropzone.addClass('hover');
return false;
});
dropzone.on('dragleave', function() {
//remove hover class when drag out
dropzone.removeClass('hover');
return false;
});
dropzone.on('drop', function(e) {
//prevent browser from open the file when drop off
e.stopPropagation();
e.preventDefault();
dropzone.removeClass('hover');
//retrieve uploaded files data
var files = e.originalEvent.dataTransfer.files;
didNotChangeImages = false;
processFiles(files);
return false;
});
uploadBtn.on('click', function(e) {
e.stopPropagation();
e.preventDefault();
//trigger default file upload button
defaultUploadBtn.click();
});
defaultUploadBtn.on('change', function() {
//retrieve selected uploaded files data
var files = $(this)[0].files;
didNotChangeImages = false;
processFiles(files);
return false;
});
$("#link_save").click( saveGallery );
$("#link_clear").click( clearGallery );
$("#link_load").click( loadGallery );
$("#result").sortable();
$( "#result" ).disableSelection();
loadGallery();
/*****************************
internal functions
*****************************/
function clearGallery() {
didNotChangeImages = false;
$("#result img").remove();
}
function loadGallery() {
clearGallery();
didNotChangeImages = true;
var persistence = new jigPersistence();
// pre-seed the gallery
persistence.load( function(ids) {
console.log("Loaded image id manifest", ids);
if ( !ids ) {
return;
}
// pre seed the gallery dom
$.each( ids.images, function() {
var imageId = this;
var imgDom = $(document.createElement("img"));
imgDom.attr("src","http://apphosting.jivesoftware.com/apps/dev/jigtest/images/ajax_loader_large.gif").attr("data-id", imageId );
$("#result").append(imgDom);
});
console.log("Loaded image id manifest", ids);
$.each( ids.images, function() {
var imageId = this;
console.log("loading image id " + imageId );
persistence.load( function( thumb ) {
var imgDom = $("#result img[data-id=" + imageId + "]");
var previewSrc = thumb.imageSrc;
var width = thumb.width;
var height = thumb.height;
imgDom.attr("src", previewSrc);
imgDom.attr("data-width", width);
imgDom.attr("data-height", height);
// load source now
persistence.load( function( source ) {
var fullSrc = source.imageSrc;
imgDom.attr("data-fullsrc", fullSrc);
}, "jig_src_" + imageId );
}, "jig_thumb_" + imageId );
});
}, "jig_ids" );
}
function saveGallery() {
debugger;
var images = $("#result").find("img");
if ( images.length < 1 ) {
alert("Nothing to save");
return;
}
var persistence = new jigPersistence();
var savedCount = 0;
var saveManifest = function() {
// gather the ids
var galleryIdsJson = {
"images": []
};
$.each( images, function() {
var image = $(this);
var imageId = image.attr("data-id") || randomNum();
galleryIdsJson.images.push( imageId );
});
persistence.save( galleryIdsJson, function() {
console.log("Saved gallery image IDs");
}, "jig_ids");
};
var saved = function() {
if ( savedCount == images.length ) {
saveManifest();
alert("Done saving " + savedCount);
}
};
if ( didNotChangeImages ) {
saveManifest();
alert("Did not change images, maybe just order. Saving that.");
// did not change images, only persist the order
return;
}
$.each( images, function() {
var image = $(this);
var previewSrc = image.attr("src");
var fullSrc = image.attr("data-fullsrc");
var width = image.attr("data-width");
var height = image.attr("data-height");
var imageId = image.attr("data-id") || randomNum();
var thumbJson = {
"imageSrc": previewSrc,
"width": width,
"height": height
};
var fullJson = {
"imageSrc": fullSrc,
"width": width,
"height": height
};
persistence.save(thumbJson , function() {
console.log("Saved image id " + imageId + " thumb");
persistence.save(fullJson , function() {
console.log("Saved image id " + imageId + " source");
savedCount++;
saved();
}, "jig_src_" + imageId);
}, "jig_thumb_" + imageId);
});
}
//Bytes to KiloBytes conversion
function convertToKBytes(number) {
return (number / 1024).toFixed(1);
}
function compareWidthHeight(width, height) {
var diff = [];
if(width > height) {
diff[0] = width - height;
diff[1] = 0;
} else {
diff[0] = 0;
diff[1] = height - width;
}
return diff;
}
//convert datauri to blob
function dataURItoBlob(dataURI) {
var BlobBuilder = window.WebKitBlobBuilder || window.MozBlobBuilder || window.BlobBuilder;
//skip if browser doesn't support BlobBuilder object
if(typeof BlobBuilder === "undefined") {
$('#err').html('Ops! There have some limited with your browser! <br/>New image produced from canvas can\'t be upload to the server...');
return dataURI;
}
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a blob, and you're done
var bb = new BlobBuilder();
bb.append(ab);
return bb.getBlob(mimeString);
}
/*****************************
canvas filter function
*****************************/
//Black & White image effect
//by Marco Lisci - http://badsharkco.com/
var grayscale = function(context) {
var imgd = context.getImageData(0, 0, imgWidth, imgHeight);
var pix = imgd.data;
for (var i = 0, n = pix.length; i < n; i += 4) {
var grayscale = pix[i ] * .3 + pix[i+1] * .59 + pix[i+2] * .11;
pix[i ] = grayscale;
pix[i+1] = grayscale;
pix[i+2] = grayscale;
}
context.putImageData(imgd, 0, 0);
}
//canvas-blur effect
//by Matt Riggott - http://www.flother.com/
var blurry = function(context, image, diff) {
var i, x, y,
blureffect = 4;
context.globalAlpha = 0.1;
for (i = 1; i <= blureffect; i++) {
for (y = -blureffect/2; y <= blureffect/2; y++) {
for (x = -blureffect/2; x <= blureffect/2; x++) {
context.drawImage(image, diff[0]/2, diff[1]/2, image.width-diff[0], image.height-diff[1], x, y, imgWidth, imgHeight);
}
}
}
context.globalAlpha = 1.0;
}
/*****************************
Process FileList
*****************************/
var processFiles = function(files) {
if(files && typeof FileReader !== "undefined") {
//process each files only if browser is supported
for(var i=0; i<files.length; i++) {
readFile(files[i]);
}
} else {
}
}
/*****************************
Read the File Object
*****************************/
var readFile = function(file) {
if( (/image/i).test(file.type) ) {
//define FileReader object
var reader = new FileReader();
$("#link_save").hide();
//init reader onload event handlers
reader.onload = function(e) {
var image = $('<img/>')
.load(function() {
//when image fully loaded
var preview = getPreviewImage(this);
var src = getSourceImage(this);
console.log(preview, src);
createPreview(file, preview.url, src.url, src.width, src.height );
})
.attr('src', e.target.result);
$("#link_save").show();
};
//begin reader read operation
reader.readAsDataURL(file);
$('#err').text('');
} else {
//some message for wrong file format
$('#err').text('*Selected file format not supported!');
}
}
var mkImage = function(image, width, height, effect, croping ) {
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext('2d');
//default resize variable
var diff = [0, 0];
if(croping == 'crop') {
//get resized width and height
diff = compareWidthHeight(image.width, image.height);
}
//draw canvas image
ctx.drawImage(image, diff[0]/2, diff[1]/2, image.width-diff[0], image.height-diff[1], 0, 0, width, height);
//apply effects if any
if(effect == 'grayscale') {
grayscale(ctx);
} else if(effect == 'blurry') {
blurry(ctx, image, diff);
} else {}
return canvas.toDataURL("image/jpeg");
}
/*****************************
Get New Canvas Image URL
*****************************/
var getDimensions = function(maxWidth, maxHeight, width, height ) {
var neww, newh = 0;
var rw = width / maxWidth; // width and height are maximum thumbnail's bounds
var rh = height / maxHeight;
if (rw > rh)
{
newh = height / rw;
neww = maxWidth;
}
else
{
neww = width / rh;
newh = maxHeight;
}
return {
width: neww,
height: newh
};
}
var getPreviewImage = function(image) {
var effect = $('input[name=effect]:checked').val();
var croping = $('input[name=croping]:checked').val();
var dimensions = getDimensions(90, 90, image.width, image.height );
return {
width: dimensions.width,
height: dimensions.height,
url: mkImage(image, dimensions.width, dimensions.height, effect, croping )
};
}
var getSourceImage = function(image) {
var effect = $('input[name=effect]:checked').val();
var croping = $('input[name=croping]:checked').val();
var dimensions = getDimensions(500, 500, image.width, image.height );
return {
width: dimensions.width,
height: dimensions.height,
url: mkImage(image, dimensions.width, dimensions.height, effect, croping )
};
}
/*****************************
Draw Image Preview
*****************************/
var createPreview = function(file, newURL, srcURL, width, height ) {
//populate jQuery Template binding object
var imageObj = {};
imageObj.imageId = randomNum();
imageObj.filePath = newURL;
imageObj.fullSrc = srcURL;
imageObj.imageWidth = width;
imageObj.imageHeight = height;
imageObj.fileName = file.name.substr(0, file.name.lastIndexOf('.')); //subtract file extension
imageObj.fileOriSize = convertToKBytes(file.size);
imageObj.fileUploadSize = convertToKBytes(dataURItoBlob(newURL).size); //convert new image URL to blob to get file.size
//extend filename
var effect = $('input[name=effect]:checked').val();
if(effect == 'grayscale') {
imageObj.fileName += " (Grayscale)";
} else if(effect == 'blurry') {
imageObj.fileName += " (Blurry)";
}
//append new image through jQuery Template
var randvalue = Math.floor(Math.random()*31)-15; //random number
var img = $("#imageTemplate").tmpl(imageObj).prependTo("#result")
.hide()
.css({
'z-index': zindex++
})
.show();
if(isNaN(imageObj.fileUploadSize)) {
$('.imageholder span').last().hide();
}
}
//file upload via original byte sequence
var processFileInIE = function(file) {
var imageObj = {};
var extension = ['jpg', 'jpeg', 'gif', 'png'];
var filepath = file.value;
if (filepath) {
//get file name
var startIndex = (filepath.indexOf('\\') >= 0 ? filepath.lastIndexOf('\\') : filepath.lastIndexOf('/'));
var filedetail = filepath.substring(startIndex);
if (filedetail.indexOf('\\') === 0 || filedetail.indexOf('/') === 0) {
filedetail = filedetail.substring(1);
}
var filename = filedetail.substr(0, filedetail.lastIndexOf('.'));
var fileext = filedetail.slice(filedetail.lastIndexOf(".")+1).toLowerCase();
//check file extension
if($.inArray(fileext, extension) > -1) {
//append using template
$('#err').text('');
imageObj.filepath = filepath;
imageObj.filename = filename;
var randvalue = Math.floor(Math.random()*31)-15;
$("#imageTemplate").tmpl(imageObj).prependTo( "#result" )
.hide()
.css({
'z-index': zindex++
})
.show();
$('#result').find('figcaption span').hide();
} else {
$('#err').text('*Selected file format not supported!');
}
}
}
});
function randomNum(maxVal) {
var maxRandomVal = maxVal ? maxVal : 1000000;
return Math.floor(Math.random()*maxRandomVal);
}
});
;function ViewManager() {
return {
showView:function (view) {
if (!this.currentView || view != this.currentView) {
if (this.currentView)
this.currentView.close();
this.currentView = view;
// console.log("view", view.el );
$("#main-content").html(this.currentView.el);
}
}
};
};(function() {
if (!window.console){console={log:function(s){}}};
var routes = {
'gallery-select/:id' : 'galleryDrop'
};
var appContext = {
routes: routes
};
window.app = new App();
app.initialize(appContext);
})();