var ARTICLE_ID = 0; var BASE_URL = "http://edgwareroad.org/edit/" var edgeArticle = window.edgeArticle = []; var loadArticle = function(id) { // console.log("load article fired"); $.getJSON("/edit/article/json/", { 'id': id }, function(json) { // console.log(json); for (var i=0; i < json.length; i++) { new Canvas({}, json[i]); } startPoller(); }); } //is used by the poller to call itself 1 second in the future. not sure why im doing this. FIXME: function name at least? function delayedRecursion(time) { // console.log("delayed recursion called" + time); POLLER = setTimeout(startPoller, time); } function startPoller() { // console.log("poller called"); $.getJSON("/edit/poll_changes/", { 'article_id': ARTICLE_ID, 'rev_no': REVISION_NO, 'uuid': UUID }, function(data) { if (data.ok == 'ok') { delayedRecursion(1000); } else { REVISION_NO = data.rev_id; clearTimeout(POLLER); delayedRecursion(1000); var arr = data.revs; for (var a in arr) { if (arr.hasOwnProperty(a)) { handleRevision(arr[a]); } } } }); } function addHistoryObject(data) { var e = $('
').addClass("historyItem").data("data", data).hide(); var userHtml = "edit by " + data.username + ""; var userLine = $('
').addClass("historyUser").html(userHtml).appendTo(e); $('.historyItems').prepend(e); e.fadeIn(); } $('.historyUser').live("click", function() { var parent = $(this).parent(); if (parent.children('.historyData').length > 0 && parent.children('.historyData').is(":visible")) { parent.children(".historyData").slideUp(); } else { var data = parent.data('data'); data['page_no'] = getCanvasById(data.page_id).index + 1; var html = tmpl("tmpl_historyData", data); $('
').addClass('historyData').html(html).hide().appendTo(parent).slideDown(); } }); //Refer to editor/models.py -> Revisions function handleRevision(json) { // console.log(json); var canvas = json.prop == 'new_page' ? {} : getCanvasById(json.page_id); addHistoryObject(json); switch (json.prop) { case "new_page": var j = JSON.parse(json.new_val); new Canvas({}, j); break; case "move_page": var page_id = json.box_id; var c = getCanvasById(page_id); c.movePage(json.new_val - 1, true); break; case "delete_page": var c = getCanvasById(json.new_val); c.deleteme(true); break; case "new_box": if (json.box_type == 'image') { var j = JSON.parse(json.new_val); new ImageBox(canvas, j.resource, j); break; } else if (json.box_type == 'text') { var j = JSON.parse(json.new_val); new TextBox(canvas, j); break; } else { break; } case "delete_box": var box = canvas.getBox(json); box.jq.hide().remove(); break; case "image_resize": var box = canvas.getBox(json); var img = JSON.parse(json.new_val); box.resize({'width': img.width, 'height': img.height}, false); box.jq.find("img").attr("src", img.path); break; case "image_crop": var box = canvas.getBox(json); var img = JSON.parse(json.new_val); box.resize({'width': img.width, 'height': img.height}, false); box.jq.find('.edgeImage').attr("src", img.path); break; default: var box = canvas.getBox(json); if (json.prop == 'html') { box.jq.find('.textbox_canvas_content').html(json.new_val); } else { var d = {}; var noPxArr = ['opacity', 'z-index', 'background', 'border-color', 'border-style']; if ($.inArray(noPxArr, json.prop)) { var val = json.new_val; } else { var val = toPx(json.new_val); } d[json.prop] = val; //dont try and animate properties like 'transparent', it will fail. if (d[json.prop] == 'transparent' || json.old_val == 'transparent') { box.jq.css(d); } else { box.jq.animate(d, "fast"); } break; } } return true; } $(document).ready(function() { if ($.browser.msie) { alert("Sorry, this does not currently work in Internet Explorer."); window.location.href = "/"; return false; } if (ARTICLE_ID != 0) { loadArticle(ARTICLE_ID); } else { c = new Canvas(); } /* edgeCanvas = new Canvas(); edgeBin = new Bin(); $('#newTextBox').click(function() { var index = edgeCanvas.textBoxes.length; var t = new TextBox(index, edgeCanvas); t.create(); }); */ $('.newTextBox').tooltip(); $('#newPage').click(function(e) { e.preventDefault(); c = new Canvas(); }); $('.prevPage').click(function() { edgeBin.prevPage(); }); $('.nextPage').click(function() { edgeBin.nextPage(); }); $('.searchBin').keyup(function() { edgeBin.searchString($(this).val()); }); }); function getCanvasById(id) { for (var e in edgeArticle) { if (edgeArticle.hasOwnProperty(e)) { if (edgeArticle[e].id == id) { return edgeArticle[e]; } } } return false; } var Canvas = function(opts, json) { var that = this; var defaults = { 'index': edgeArticle.length, 'id': 0, 'height': ARTICLE_HEIGHT, 'width': ARTICLE_WIDTH, 'parentID': 'canvasContainer' } var o = $.extend(defaults, opts); if (typeof json != 'undefined') { o.id = json.id; } this.index = o.index; this.parent = $('#' + o.parentID); if (o.id == 0) { $.getJSON("/edit/new_page/", { 'article_id': ARTICLE_ID, 'uuid': UUID }, function(data) { that.id = data.id; }); } else { this.id = o.id; } var that = this; this.textBoxes = []; this.imageBoxes = []; this.jq = { }; this.height = o.height; this.width = o.width; edgeArticle.push(that); this.init(); if (typeof json != 'undefined') { this.loadFromJSON(json); } else { } return this; } Canvas.prototype.getBox = function(json) { if (json.box_type == 'image') { for (var i in this.imageBoxes) { if (this.imageBoxes.hasOwnProperty(i)) { if (this.imageBoxes[i].id == json.box_id) { return this.imageBoxes[i]; } } } return false; } else { for (var t in this.textBoxes) { if (this.textBoxes.hasOwnProperty(t)) { if (this.textBoxes[t].id == json.box_id) { return this.textBoxes[t]; } } } return false; } return false; } Canvas.prototype.init = function() { var that = this; var heightPx = toPx(that.height); var widthPx = toPx(that.width); var json = { 'index': that.index } var html = tmpl("tmpl_canvas", json); this.parent.append(html); this.jq = $('#' + 'canvas' + that.index.toString()); this.jq.css({'height': heightPx, 'width': widthPx}); this.jq.find('.ruler_vert').draggable({ snap: '.box', containment: 'parent', axis: 'x' }); this.jq.find('.ruler_horiz').draggable({ snap: '.box', containment: 'parent', axis: 'y' }); this.jq.droppable({accept:'.resource, .newTextBox', drop: function(ev, ui) { var box = $(this).getBox().jq; c = edgeArticle[$(this).attr('data-index')]; if ($(ui.draggable).attr('class') == 'resource ui-draggable') { r = edgeBin.allResources[$(ui.draggable).attr("data-index")]; if (r.mime == 'image') { var top = $(this).position().top; var left = $(this).position().left; var height = parseInt(r.height) / 2; // console.log("heightFOO: " + height); var width = parseInt(r.width) / 2; highest_index = getHighestIndex(c.jq); new_index = parseInt(highest_index) + 1; // console.log('index: ' + new_index); i = new ImageBox(c, r, {css: {'z-index': "" + new_index, 'top':toPx((ev.pageY - top) - height), 'left': toPx((ev.pageX - left) - width)}}); } else if (r.mime == 'audio' || r.mime == 'video') { that.addMedia(r); } } else { var elem = $(ui.draggable); var top = $(this).position().top; var left = $(this).position().left; if (elem.hasClass('arabic')) { t = new TextBox(c, {'html': '

انقر على مربع التحرير

', 'css': {'direction': 'rtl'}}); } else { t = new TextBox(c); } width = parseInt(t.jq.css('width') / 2); height = parseInt(t.jq.css('height') / 2); t.setCSS({'top':toPx((ev.pageY - top) - height), 'left': toPx((ev.pageX - left) - width)}); highest_index = getHighestIndex(c.jq); new_index = parseInt(highest_index) + 1; t.setCSS({'z-index': new_index}); } // console.log('dropper'); } }); return this; } Canvas.prototype.addMedia = function(resource) { var that = this; $.getJSON("/edit/add_media/", { resource_id: resource.id, page_id: that.id }, function(response) { that.addMediaIcon(resource); }); } Canvas.prototype.addMediaIcon = function(resource) { var typ = resource.mime; var media_box = this.jq.find('.audio_video'); $('').addClass('media_icon').addClass(typ + '_icon').attr("src", "/static/images/icons/" + typ + ".png").attr("title", resource.title).data("resource", resource).appendTo(media_box); } Canvas.prototype.loadFromJSON = function(json) { // alert(JSON.stringify(json)); // GLOBALFOO = json; var imageBoxes = json.imageBoxes; var textBoxes = json.textBoxes; var videos = json.videos; var audios = json.audios; // alert(audios.length); var that = this; for (var i=0; i < imageBoxes.length; i++) { var resource = imageBoxes[i].resource; var b = new ImageBox(that, resource, imageBoxes[i]); // that.imageBoxes.append(b); } for (var t=0; t < textBoxes.length; t++) { var b = new TextBox(that, textBoxes[t]); // that.textBoxes.append(b); } for (var v=0; v < videos.length; v++) { var video = videos[v]; that.addMediaIcon(video); } for (var a=0; a < audios.length; a++) { var audio = audios[a]; that.addMediaIcon(audio); } } Canvas.prototype.toObj = function() { var that = this; var obj = { 'imageBoxes': that.imageBoxes, 'textBoxes': that.textBoxes, } return obj; // console.log(json); } //this function is not used. FIXME: remove Canvas.prototype.save = function() { var that = this; var url = "/editor/canvas/save/"; $.getJSON(url, { json: JSON.stringify(that.toObj()), id: that.id }, function() { alert("saved"); }); } Canvas.prototype.appendBox = function(box) { this.jq.append(box.jq); if (box instanceof TextBox) { this.textBoxes.push(box); } else if (box instanceof ImageBox) { this.imageBoxes.push(box); } return this; } Canvas.prototype.movePage = function(newOrder, dontSave) { var that = this; if (typeof(dontSave) === 'undefined') { dontSave = false; } var currentIndex = this.jq.index('.canvas'); if (newOrder == 0) { this.jq.remove().insertBefore($('.canvas').eq(0)); } else if (newOrder < currentIndex) { var prevCanvas = $('.canvas').eq(newOrder - 1); this.jq.remove().insertAfter(prevCanvas); } else { var prevCanvas = $('.canvas').eq(newOrder); this.jq.remove().insertAfter(prevCanvas); } reorderEdgeArticle(); if (!dontSave) { var url = "/edit/move_page/"; $.getJSON(url, { 'id': that.id, 'new_order': newOrder + 1, 'uuid': UUID }, function(response) { // console.log(response); }); } } Canvas.prototype.deleteme = function(dontSave) { var that = this; this.jq.remove(); edgeArticle.splice(that.index,1); reorderEdgeArticle(); if (typeof(dontSave) == 'undefined') { dontSave = false; } if (!dontSave) { var url = "/edit/delete_page/"; $.getJSON(url, { 'id': that.id }, function(response) { // console.log(response); }); } } function reorderEdgeArticle() { edgeArticle.sort(function(a,b) { var aIndex = a.jq.index('.canvas'); var bIndex = b.jq.index('.canvas'); return aIndex - bIndex; }); $('.canvas').each(function() { var thisIndex = $(this).index('.canvas'); $(this).attr("data-index", thisIndex); var c = $(this).children().eq(0).getCanvas(); c.index = thisIndex; }); } function getHighestIndex(canvas) { page_boxes = canvas.find('.box'); if (page_boxes.length == 0) { return 0; } else { page_boxes = $(page_boxes).sort(compareZIndex); highest = $(page_boxes[0]).css('z-index'); return highest; } } function getLowestIndex(canvas) { page_boxes = canvas.find('.box'); page_boxes = $(page_boxes).sort(compareZIndex); length = page_boxes.length - 1; lowest = $(page_boxes[length]).css('z-index'); return lowest; } function reSortBoxes (canvas) { var page_boxes = canvas.find('.box'); page_boxes = $(page_boxes).sort(compareZIndex); // console.log(page_boxes); for (var i=0; i < page_boxes.length; i++) { var boxObj = $(page_boxes[i]).find('*').getBox(); boxObj.setCSS({'z-index': page_boxes.length - i}); } } function compareZIndex(a, b) { return parseInt($(b).css('z-index')) - parseInt($(a).css('z-index')); // console.log('gjugg'); // console.log($(b).css('z-index')); // console.log('mugg'); } /* >>> t = new TextBox(0); t.index; 0 @constructor @class TextBox TextBox class @property {Int} id Id of the box in the back-end. If the id is set to 0, it calls the db and sets the id in the create() method. @property {String} html The raw html of the contents of the text box. @property {Object} css Key value pairs representing the css for the text box. @property {Object} resource The resource in the database this box is based on. For text-boxes, it is not really used, but may be good to have anyway. @property {jQuery Object} jq Object representing text box on page. So you can do things like t.jq.css({'background', '#000'}); to change the background color of TextBox t to black. */ var TextBox = function(canvas, json, index) { this.index = index || canvas.textBoxes.length; this.id = 0; this.html = ''; this.css = { }; this.resource = { }; this.jq = {}; this.canvas = canvas; this.create(json); }; /* Call this function to create a new Text Box - if passed json, the TextBox is instantiated from the JSON, else it uses defaults. >>> t.create(); t.jq.length == 1; true */ TextBox.prototype.create = function(json) { var that = this; var defaults = { 'id': 0, 'html': '

Click to edit textbox

', 'resource_id': 0, 'css': { 'direction': 'ltr', 'height': '300px', 'width': '300px', 'background-color': '#ffffff', 'border-style': 'dotted', 'border-width': '1px', 'border-color': '#000000', 'top': '100px', 'left': '100px', 'padding-top': '0px', 'padding-left': '0px', 'padding-right': '0px', 'padding-bottom': '0px', 'opacity': '1', 'z-index': '1', 'border-radius': '0px' } }; var opts = $.extend(true, defaults, json); // console.log(opts); this.id = opts.id; this.html = opts.html; this.css = opts.css; if (this.id == 0) { // Create new TextBox in db: var optsString = JSON.stringify(opts); // console.log(this.id); $.getJSON("/edit/textbox/new/", {'json': optsString, 'page_id': that.canvas.id, 'uuid': UUID}, function(response) { var id = response.id; that.id = id; that.jq.attr("data-id", id); // REVISION_NO = response.rev_id; }); } var elem = this.init(); this.jq = elem; this.canvas.appendBox(that); // edgeCanvas.textBoxes.push(this) }; /* This method is called by create(); it should generally not be called from the outside. Here is where the actual element is created and event handlers added. >>> t.init(); t.jq.attr("data-index"); 0 */ TextBox.prototype.init = function() { var that = this; var e = $('
'); e.html(tmpl('tmpl_textbox', {'html': that.html})).attr("data-id", that.id).attr("data-index", that.index).css(that.css).addClass("box").addClass("textBox"); /* Workaround for strange webkit behaviour */ if (e.css("position") == "relative" || e.css("position") == '') { e.css("position", "absolute"); } // console.log(e.css("position")); // GLOB = e.css("position"); // e.append($('
').addClass("boxText")); e.draggable({ snap: '.box, .ruler', snapMode: 'outer', containment: 'parent', stop: function(event, ui) { var top = parseInt($(this).position().top).toString(); var left = parseInt($(this).position().left).toString(); that.setCSS({'top': top, 'left': left}); /* var id = $(this).attr("data-id"); var css = { 'id': id, 'top': top, 'left': left } $.get(url, css, function(response) { }); var i = parseInt($(this).attr("data-index")); */ // var thisBox = edgeCanvas.textBoxes[i]; // thisBox.updateCSS(css); } }).resizable({ // containment: '#' + that.canvas.jq.attr("id"), containment: that.canvas.jq, handles: 'nw, ne, se, sw, n, s, w, e', stop: function(event, ui) { var top = parseInt($(this).position().top).toString(); var left = parseInt($(this).position().left).toString(); var height = $(this).height().toString(); var width = $(this).width().toString(); that.setCSS({'height': height, 'width': width, 'top': top, 'left': left}); /* var id = $(this).attr("data-id"); var json = { 'id': id, 'height': height, 'width': width }; var i = parseInt($(this).attr("data-index")); var thisBox = edgeCanvas.textBoxes[i]; */ // thisBox.updateCSS(css); } }); return e; }; /* Called by setCSS to send the ajax call to the back-end to update the Css - if called from the outside, it will send the request to the back-end, but not update client-side. >>> t.updateCSS({'background': '#000'}); t.jq.css("background-color"); '#000000' */ TextBox.prototype.updateCSS = function(css) { css.id = this.id; css.uuid = UUID; // console.log(css); // isAjaxActive = true; $.getJSON("/edit/textbox/update_css/", css, function(response) { if (response.status == 1) { // REVISION_NO = response.rev_id; return true; } else { return false; } // isAjaxActive = false; }); }; /* Call this from the outside to update CSS both client and server-side. css can be any number of key value pairs of css properties to update. >>> t.setCSS({'padding-bottom': '10px', 'padding-top': '15px'}); t.jq.css("padding-bottom") "10px" */ TextBox.prototype.setCSS = function(css, callServer) { /* for (var c in css) { if (css.hasOwnProperty(c)) { this.css[c] = css[c]; } } */ this.jq.css(css); var srv = callServer == undefined ? true : callServer; if (srv) { this.updateCSS(css); } }; TextBox.prototype.setHTML = function(html) { // console.log(html); var that = this; $.getJSON("/edit/textbox/set_html/", {'html': html, 'id': that.id, 'uuid': UUID}, function(response) { if (response.status == 1) { // REVISION_NO = response.rev_id; return true; } else { return false; } }); } TextBox.prototype.deleteme = function() { var that = this; this.jq.remove(); $.get("/edit/textbox/delete/", { 'id': that.id, 'uuid': UUID }, function(response) { // REVISION_NO = response; }); } /* refer TextBox -- except here resource is this damned resource object that image boxes need. */ var ImageBox = function(canvas, resource, json) { var that = this; this.index = canvas.imageBoxes.length; this.id = 0; this.css = { }; this.resource = resource; this.jq = {}; this.css.width = toPx(that.resource.width); this.css.height = toPx(that.resource.height); this.canvas = canvas; this.create(json); }; ImageBox.prototype.create = function(json) { var that = this; var defaults = { 'id': 0, 'html': tmpl('tmpl_imagebox', {}), 'resource_id': that.resource.id, 'page_id': that.canvas.id, 'css': { 'height': that.css.height, 'width': that.css.width, 'border-style': 'solid', 'border-width': '0px', 'border-color': '#000000', 'z-index': '1', 'top': '100px', 'left': '100px', 'opacity': '1' } }; var opts = $.extend(true, defaults, json); this.id = opts.id; this.html = opts.html; this.css = opts.css; // console.log(opts.css); if (this.id == 0) { // Create new TextBox in db: var jsonString = JSON.stringify(opts); $.getJSON("/edit/imagebox/new/", {'json': jsonString, 'uuid': UUID}, function(response) { var id = response.id; that.id = id; that.jq.attr("data-id", id); // REVISION_NO = response.rev_id; }); } this.init(); // var elem = this.init(); }; //TextBox.prototype.init = function() { // var that = this; // var e = $('
'); // e.html(that.html).attr("data-id", that.id).attr("data-index", that.index).css(that.css).addClass("box").addClass("textBox"); // e.append($('
').addClass("boxText")); ImageBox.prototype.init = function() { var that = this; var e = $('
'); e.attr('data-index', that.index.toString()).attr('data-id', that.id).addClass('box').addClass("imageBox"); e.css(that.css); e.html(that.html); var img = $('').addClass("edgeImage").attr("src", that.resource.resized).attr('width', that.resource.width).attr('height', that.resource.height); e.append(img); this.jq = e; this.canvas.appendBox(that); this.addEventHandlers(); } ImageBox.prototype.addEventHandlers = function() { var that = this; var e = this.jq; e.draggable({ snap: '.box, .ruler', snapMode: 'outer', containment: 'parent', stop: function(event, ui) { var top = parseInt($(this).position().top).toString(); var left = parseInt($(this).position().left).toString(); that.setCSS({'top': top, 'left': left}); } }).resizable({ containment: that.canvas.jq, handles: 'nw, se, ne, sw, n, s, w, e', aspectRatio: true, resize: function (event, ui) { var height = $(this).height().toString(); var width = $(this).width().toString(); $(this).find('.edgeImage').attr("width", width); $(this).find('.edgeImage').attr("height", height); }, stop: function(event, ui) { var top = parseInt($(this).position().top).toString(); var left = parseInt($(this).position().left).toString(); var height = $(this).height().toString(); var width = $(this).width().toString(); that.resize({'height': height, 'width': width}); that.setCSS({'top': top, 'left': left}); } }); } ImageBox.prototype.getHtml = function() { } ImageBox.prototype.fromJson = function() { } ImageBox.prototype.updateCSS = function(css) { css.id = this.id; css.uuid = UUID; $.getJSON("/edit/imagebox/update_css/", css, function(response) { if (response.status == 1) { // REVISION_NO = response.rev_id; return true; } else { return false; } }); }; ImageBox.prototype.setCSS = function(css, doUpdate) { var update = doUpdate == undefined ? true : doUpdate; this.jq.css(css); if (update) { this.updateCSS(css); } return this; }; ImageBox.prototype.resize = function(dimensions) { var that = this; this.setCSS({ 'width': toPx(dimensions.width), 'height': toPx(dimensions.height) }, false); this.jq.find('.edgeImage').attr("width", dimensions.width); this.jq.find('.edgeImage').attr("height", dimensions.height); dimensions.id = this.id; dimensions.uuid = UUID; if (arguments[1] == false) { return true; } $.getJSON("/edit/imagebox/resize/", dimensions, function(response) { // console.log(response); if (response.status == 1) { var path = $.trim(response.path); that.jq.find('.edgeImage').attr("src", path); // REVISION_NO = response.rev_id; return true; } else { return false; } }); }; ImageBox.prototype.deleteme = function() { var that = this; this.jq.remove(); $.get("/edit/imagebox/delete/", {'id': that.id, 'uuid': UUID}, function(response) { // REVISION_NO = response; }); } /* @constructor @class Bin Bin class to deal with loading various categories into a bin to pick from into your own bin @property {Array} resources Resource objects that belong to this bin. @divid {String} Id of DOM node. @jq {jQuery Object} Jquery object representing Bin */ var Bin = function() { this.resources = []; this.divid = 'bin'; var that = this; this.size = 6; this.start_index = 0; this.jq = $('#' + that.divid); this.allResources = []; }; Bin.prototype.loadCategory = function(catid, type) { var that = this; this.jq.find('.resource').remove(); this.resources = []; $.getJSON("/edit/category/json/", {'id': catid, 'type': type}, function(json) { var resources = json.resources; for (r in resources) { if (resources.hasOwnProperty(r)) { thisResource = new Resource(resources[r], r); that.resources.push(thisResource); } } that.allResources = that.resources; that.init(); }); }; /* This function is a very good idea. You would send a json object with parameters to the back-end to filter results by, allowing search to get a lot better. Bin.prototype.loadResources = function(url, params) { var that = this; this.jq.find('.resource').remove(); this.resources = []; } */ Bin.prototype.searchString = function(str) { var that = this; this.resources = []; // console.log(that.allResources); for (var i = 0; i < that.allResources.length; i++) { var r = that.allResources[i]; r.hide(); if ((r.title.toLowerCase().indexOf(str.toLowerCase()) != -1) || (r.description.toLowerCase().indexOf(str.toLowerCase()) != -1)) { this.resources.push(r); // console.log(r); r.show(); } } this.init(); } Bin.prototype.init = function() { var that = this; this.start_index = 0; for (var i=0; i < this.resources.length; i++) { if (i >= this.size) { this.resources[i].hide(); } else { this.resources[i].show(); } } var end_index = that.resources.length < that.size ? that.resources.length : that.size; that.jq.find('.prevPage').hide(); that.jq.find('.nextPage').show(); that.jq.find('.totalResources').html(that.resources.length.toString()); that.jq.find('.start_index').html('1'); that.jq.find('.end_index').html(end_index.toString()); } Bin.prototype.nextPage = function() { var that = this; var curr_index = this.start_index + this.size; var end_index = curr_index + this.size > that.resources.length ? that.resources.length : curr_index + that.size; for (var i = this.start_index; i < end_index; i++) { if (i < curr_index) { this.resources[i].hide(); } else { this.resources[i].show(); } } this.start_index = curr_index; // console.log(that.start_index + that.size); if (this.start_index + this.size >= this.resources.length) { this.jq.find('.nextPage').hide(); } this.jq.find('.prevPage').show(); this.jq.find('.start_index').html((curr_index + 1).toString()); this.jq.find('.end_index').html(end_index.toString()); } Bin.prototype.prevPage = function() { var that = this; var curr_start = this.start_index; var end_index = this.start_index + this.size > this.resources.length ? this.resources.length - 1 : (this.start_index + this.size) - 1; for (var j = 0; j < this.resources.length; j++) { this.resources[j].hide(); } for (var i = end_index; i > this.start_index - this.size; i--) { // console.log(end_index); if (i > this.start_index) { // this.resources[i].hide(); } else { this.resources[i].show(); } } this.start_index = curr_start - this.size; if (this.start_index <= 0) { this.start_index = 0; this.jq.find('.prevPage').hide(); } this.jq.find('.nextPage').show(); this.jq.find('.start_index').html((that.start_index + 1).toString()); this.jq.find('.end_index').html(curr_start.toString()); } /* @constructor @class MyBin Class to deal with personal bins. @property {String} name Name user assigns to bin to be uniquely identifiable @property {Int} creator User id of user who created this bin. Might be useful to determine permissions. CURRENTLY NOT USED. */ var MyBin = function() { this.resources = []; this.divid = 'mybin'; var that = this; this.jq = $('#' + that.divid); this.id = 0; this.name = ''; this.creator = 0; } /* Method to load bin from json */ MyBin.prototype.load = function(json) { } /* Method to save bin to the database */ MyBin.prototype.save = function() { } /* CURRENTLY NOT USED. */ var MyResource = function(json, index) { this.index = index; this.id = json.id; this.divid = 'myresource' + this.index.toString(); this.type = json.type; this.file = json.file; this.description = json.description; this.tags = json.tags; this.mime = json.mime; //inaccurately called 'mime' - this is either image, text, audio or video, as a string. this.icon = json.icon; this.added = json.added; this.addToBin(); } MyResource.prototype.addToBin = function() { } var Resource = function(json, index) { this.index = index; this.id = json.id; this.media_id = json.media_id; this.divid = "resource" + this.index.toString(); this.type = json.type; this.file = json.file; this.title = json.title; this.description = json.description; this.tags = json.tags; this.mime = json.mime; this.icon = json.icon; this.added = json.added; this.width = json.width; this.height = json.height; this.tooltip = "" + this.title + "
" + this.description + ""; this.resized = $.trim(json.resized); this.displayed = true; this.addToBin(); this.hide = function() { this.displayed = false; this.jq.hide(); } this.show = function() { this.displayed = true; this.jq.show(); } }; Resource.prototype.addToBin = function() { var that = this; var e = this.getBinElem(); edgeBin.jq.find('.binResources').append(e); this.jq = $('#' + that.divid); this.addEventHandlers(); }; Resource.prototype.getBinElem = function() { var that = this; var e = $('
'); e.html(that.getBinHtml()); e.attr("id", that.divid); e.attr("data-index", that.index.toString()); e.attr("data-id", that.id.toString()); e.attr("title", that.tooltip); e.addClass("resource"); e.css({'display': 'none'}); return e; }; Resource.prototype.getBinHtml = function() { var that = this; var html = "foo"; return html }; Resource.prototype.addEventHandlers = function() { var that = this; this.jq.tooltip(); var mim2tmpl = { 'image': "tmpl_resource_image", 'video': "tmpl_resource_av", 'audio': "tmpl_resource_av", 'text': "tmpl_resource_doc" } this.jq.hover(function() { var tmpl_id = mim2tmpl[that.mime]; var html = tmpl(tmpl_id, {}); that.jq.append(html); }, function() { that.jq.find(".resourceMenu").remove(); }); /* this.jq.dblclick(function() { // console.log("foo"); var e = that.jq.clone().attr("id", that.jq.attr("id").replace("resource", "myresource")); console.log(e); $('#userBin').append(e); }); */ this.jq.draggable({ revert: true, helper: 'clone'}); }; function toPx(i) { if (typeof i == 'string' && i.charAt(0) == '#') { return i; } var inty = parseInt(i); if (inty != NaN) { var str = inty.toString() + "px"; return str; } else { return str + "px"; } } jQuery.fn.getResource = function() { var jq = this.parents('.resource'); var resourceIndex = parseInt(jq.attr("data-index")); return edgeBin.resources[resourceIndex]; } jQuery.fn.getCanvas = function() { var index = parseInt(this.parents('.canvas').attr("data-index")); return edgeArticle[index]; } jQuery.fn.getBox = function() { var boxJq = this.parents('.box'); var boxIndex = parseInt(boxJq.attr("data-index")); var canvasIndex = boxJq.parents('.canvas').attr("data-index"); if (boxJq.hasClass("textBox")) { return edgeArticle[canvasIndex].textBoxes[boxIndex]; } else if (boxJq.hasClass("imageBox")) { return edgeArticle[canvasIndex].imageBoxes[boxIndex]; } else { return false; } } /* function getCanvasByElem(e) { var index = parseInt(e.parents('.canvas').attr("data-index")); return edgeArticle[index]; } function getBoxByElem(e) { var boxJq = e.parents('.box'); var boxIndex = parseInt(boxJq.attr("data-index")); var canvasIndex = boxJq.parents('.canvas').attr("data-index"); if (boxJq.hasClass("textBox")) { return edgeArticle[canvasIndex].textBoxes[boxIndex]; } else if (boxJq.hasClass("imageBox")) { return edgeArticle[canvasIndex].imageBoxes[boxIndex]; } else { return false; } } */ function loadArticle(json) { for (j in json) { if (json.hasOwnProperty(j)) { new Canvas({}, json[j]); } } } /* window.onload = function() { }; */ $(document).ready(function(){ $(".newTextBox").draggable({ revert: true, helper: 'clone'}); }); /* $(".box").live("dblclick", function(){ // $ ('.save_text').hide(); // element = $(this).find('.textbox_canvas_content'); // replaceDiv( element[0] ); // box = $(element).getBox().jq; // box.draggable( 'disable' ); // box.resizable( 'disable' ); // $(element).parent().siblings('.save_text').show(); }); */ var editor; function removeEditor(element) { if ( !editor ) return; $(element).toggle(); box = $(element).getBox(); box.setHTML(editor.getData()); box.jq.draggable( 'enable' ); box.jq.resizable( 'enable' ); // Destroy the editor. editor.destroy(); editor = null; text_edit_mode = false; box.jq.css('z-index', this_org_z); } function replaceDiv( div ) { if ( editor ) editor.destroy(); // CKEDITOR.plugins.add('mysave',{ // init:function(a){ // var cmd = a.addCommand('mysave',{exec:CKsaveAjax}) // a.ui.addButton('MySave',{ // label:'Save', // command:'mysave', // icon:this.path+"images/save.png" // }) // } // }) // console.log(div); // alert($(div).attr('classname')); height = parseInt($(div).css('height')); height = toPx(height); width = parseInt($(div).css('width')); width = toPx(width); editor = CKEDITOR.replace( div, { width: width, height: height, toolbar : 'Basic', uiColor : '#9AB8F3', resize_enabled: false, toolbarStartupExpanded: false, skin: 'v2' }); } /* height = parseInt($(div).css('height')) - 6; height = toPx(height); width = parseInt($(div).css('width')) - 6; width = toPx(width); editor = CKEDITOR.replace( div, { height: height, toolbar : 'Basic', uiColor : '#9AB8F3', resize_enabled: false, toolbarStartupExpanded: false, skin: 'v2' }); } $(".box").live("mouseover", function(){ // if (!editor) // $(this).find(".textbox_canvas_toolbox").show(); }); $(".box").live("mouseout", function(){ // $(this).find(".textbox_canvas_toolbox").hide(); }); */ function cropImage(c) { crop_url = '/edit/imagebox/crop/?x1=' + c.x + '&y1=' + c.y + '&x2=' + c.x2 + '&y2=' + c.y2 + '&width=' + c.w + '&height=' + c.h + '&id=' + this_imagebox_id + '&uuid=' + UUID; crop_dimensions = c; }; text_edit_mode = false; $(".box").live("click", function(e){ if (text_edit_mode) { return false; } e.preventDefault(); var top = parseInt($(this).css('top')); var left = parseInt($(this).css('left')); var box = $(this).find('*').getBox().jq; var boxObj = $(this).find('*').getBox(); if ($(".properties").length == 0) { // console.log($(this).attr('class')) if ($(this).hasClass("textBox")) { $('body').append(tmpl('tmpl_textbox_properties', {})); } else if ($(this).hasClass("imageBox")) { $('body').append(tmpl('tmpl_imagebox_properties', {})); } var canvas = $(this).getCanvas().jq; canvas_top = parseInt(canvas.offset().top); canvas_left = parseInt(canvas.offset().left); $(".properties").css('top', toPx((e.pageY))); $(".properties").css('left', toPx((e.pageX))); } else { $(".properties").remove(); //BAD HACK: removes the nudge binder if present. Got to be a better way to do this -- potentially bind to document using a custom nudge event, but not sure. $(document).unbind("keydown"); //This should click itself, to then display properties wherever it is clicked, but it does not work:( // $(this).trigger("click"); } // i.setCSS({'top':toPx((ev.pageY - top) - height), 'left': toPx((ev.pageX - left) - width)}); current_val = box.css('background-color'); // console.log('current val: ' + current_val) $('.properties').find('.backgroundColorSelector div').css('background-color', current_val); $(".properties").find('.backgroundColorSelector').ColorPicker({ color: current_val, onShow: function (colpkr) { $(colpkr).fadeIn(500); return false; }, onHide: function (colpkr) { $(colpkr).fadeOut(500); boxObj.setCSS({'background-color': '#' + GLOBAL_HEX}); return false; }, onChange: function (hsb, hex, rgb) { $('.properties').find('.backgroundColorSelector div').css('background-color', '#' + hex); box.css('background-color', '#' + hex); GLOBAL_HEX = hex; }, onBeforeShow: function () { current_val = box.children('div').css('background-color'); $(this).ColorPickerSetColor(current_val); } }); var current_val = box.css('border-right-color'); $('.properties').find('.borderColorSelector div').css('background-color', current_val); $(".properties").find('.borderColorSelector').ColorPicker({ color: current_val, onShow: function (colpkr) { $(colpkr).fadeIn(500); return false; }, onHide: function (colpkr) { $(colpkr).fadeOut(500); boxObj.setCSS({'border-color': '#' + GLOBAL_HEX}); return false; }, onChange: function (hsb, hex, rgb) { $('.properties').find('.borderColorSelector div').css('background-color', '#' + hex); box.css('border-color', '#' + hex); GLOBAL_HEX = hex; } }); var current_val = parseInt(box.css('padding')); $(".properties").find(".change_padding").slider({ range: "max", min: 0, max: 40, value: current_val, slide: function(event, ui) { i = parseInt(box.attr('data-index')); height = parseInt(box.css('height')) width = parseInt(box.css('width')) // console.log(height + " - " + width) org_padding = parseInt(box.css('padding')) padding = org_padding - ui.value; boxObj.setCSS({'padding-top': ui.value, 'padding-right': ui.value, 'padding-bottom': ui.value, 'padding-left': ui.value}, false) boxObj.setCSS({'height': height + (2 * padding), 'width': width + (2 * padding)}, false) }, stop: function(event, ui) { i = parseInt(box.attr('data-index')); height = parseInt(box.css('height')) width = parseInt(box.css('width')) // console.log(height + " - " + width) org_padding = parseInt(box.css('padding')) padding = org_padding - ui.value; boxObj.setCSS({'padding-top': ui.value, 'padding-right': ui.value, 'padding-bottom': ui.value, 'padding-left': ui.value}) boxObj.setCSS({'height': height + (2 * padding), 'width': width + (2 * padding)}) } }); var current_val = parseInt(box.css('border-right-width')); $(".properties").find(".change_border").slider({ range: "max", min: 0, max: 5, value: current_val, slide: function(event, ui) { boxObj.setCSS({'border-width': ui.value}, false) }, stop: function(event, ui) { boxObj.setCSS({'border-width': ui.value}) } }); var current_val = 10 * box.css('opacity'); $(".properties").find(".change_opacity").slider({ range: "max", min: 2, max: 10, value: current_val, slide: function(event, ui) { boxObj.setCSS({'opacity': ui.value / 10}, false); }, stop: function(event, ui) { thisBox = $(this).getBox(); boxObj.setCSS({'opacity': ui.value / 10}); } }); $(".background_transparent").bind("click", function(e){ e.preventDefault(); boxObj.setCSS({'background-color': 'transparent'}); }); var current_val = box.css('border-style'); // $(".borderStyle").append(''); var current_border_style = box.css('border-left-style'); $('select option[value*=' + current_border_style + ']').attr('selected','true'); $(".borderStyle").bind("change", function(e){ var val = $(this).val(); boxObj.setCSS({'border-style': val}); }); $(".crop_imagebox").bind("click", function(e){ e.preventDefault(); text_edit_mode = true; box.resizable( 'disable' ); $(canvas).append(tmpl('tmpl_imagebox_crop', {})); canvas_top = parseInt(canvas.offset().top); canvas_left = parseInt(canvas.offset().left); box_top = box.css('top'); box_left = box.css('left'); crop_box_top = parseInt(box_top) + parseInt(box.css('height')) + 5; crop_box_left = parseInt(box_left); $(".imagebox_crop").css('top', crop_box_top); $(".imagebox_crop").css('left', crop_box_left); image = box.find('.edgeImage'); this_imagebox_id = box.attr('data-id'); jcrop = $.Jcrop(image, {onSelect: cropImage}, function(){ }); $('.properties').remove(); $(".do_crop_imagebox").bind("click", function(e){ e.preventDefault(); box.resizable( 'enable' ); // console.log(url); $.getJSON(crop_url, { 'article_id': ARTICLE_ID }, function(data) { // console.log(data.path); new_top = parseInt(box_top) + crop_dimensions.y; new_left = parseInt(box_left) + crop_dimensions.x; boxObj.setCSS({'width': crop_dimensions.w, 'height': crop_dimensions.h}, false); boxObj.setCSS({'top': new_top, 'left': new_left}); jcrop.destroy(); box.find('.edgeImage').attr("width", crop_dimensions.w); box.find('.edgeImage').attr("height", crop_dimensions.h); box.find('.edgeImage').attr('src', data.path); $('.imagebox_crop').remove(); text_edit_mode = false; REVISION_NO = data.rev_id; }); }); $(".cancel_crop_imagebox").bind("click", function(e){ e.preventDefault(); jcrop.destroy(); $('.imagebox_crop').remove(); box.resizable( 'enable' ); text_edit_mode = false; }); }); $(".nudge_box").bind("click", function(e){ e.preventDefault(); $(document).bind("keydown", function(event) { // console.log(event.keyCode); if (event.keyCode == '38') { event.preventDefault(); var top = box.css('top'); if (parseInt(top) > 1) { boxObj.setCSS({'top': toPx(parseInt(top) - 1)}); // console.log('up?'); } } if (event.keyCode == '40') { event.preventDefault(); var top = box.css('top'); var height = box.outerHeight(); var lower_edge = parseInt(top) + parseInt(height); var canvas_height = canvas.css('height'); // console.log('canvas_height:' + canvas_height); // console.log('box lower:' + lower_edge); if (lower_edge < parseInt(canvas_height)) { boxObj.setCSS({'top': toPx(parseInt(top) + 1)}); // console.log('down?'); } } if (event.keyCode == '39') { event.preventDefault(); var left = box.css('left'); var width = box.outerWidth(); var right_edge = parseInt(left) + parseInt(width); canvas_width = canvas.css('width'); if (right_edge < parseInt(canvas_width)) { boxObj.setCSS({'left': toPx(parseInt(left) + 1)}); } } if (event.keyCode == '37') { event.preventDefault(); left = box.css('left'); if (parseInt(left) > 0) { boxObj.setCSS({'left': toPx(parseInt(left) - 1)}); } } }); }); $(".edit_textbox").bind("click", function(e){ e.preventDefault(); $('.save_text').hide(); $('.properties').hide(); this_org_z = box.css('z-index'); box.css('z-index', '1000'); element = box.find('.textbox_canvas_content'); replaceDiv( element[0] ); boxObj = $(element).getBox(); // console.log(boxObj); box = boxObj.jq; if (box.css("direction") == 'rtl') { setTimeout(function() { $($('iframe').get(0).contentDocument).find('html').attr("dir", "rtl") }, 500); } $('iframe').attr("allowtransparency", "false"); box.draggable('disable'); box.resizable('disable'); text_edit_mode = true; $(element).parent().siblings('.save_text').show(); }); $(".z-index-add").bind("click", function(e){ e.preventDefault(); var canvas = box.parents('.canvas'); highest_index = getHighestIndex(canvas); // console.log(highest_index); var new_index = highest_index + 1; boxObj.setCSS({'z-index': new_index}); reSortBoxes(canvas); }); $(".z-index-sub").bind("click", function(e){ e.preventDefault(); canvas = box.parents('.canvas'); lowest_index = getLowestIndex(canvas); new_index = lowest_index - 1; boxObj.setCSS({'z-index': new_index}); reSortBoxes(canvas); }); $(".delete_box").bind("click", function(e){ e.preventDefault(); if (confirm("are you sure you wish to permanently delete this box from this page?")) { $(".properties").remove(); boxObj.deleteme(); } }); }); $(".canvas").live("mousemove", function(e){ var left = parseInt($(this).position().left) + parseInt($(this).css('margin-left')); var top = parseInt($(this).position().top) + parseInt($(this).css('margin-top')); // console.log(top); var pageCoords = "( " + (e.pageX - left) + ", " + (e.pageY - top) + " )"; $('#coordinates').html(pageCoords); }); $(".canvas").live("mouseout", function(e){ $('#coordinates').html(''); }); /* $(document).click(function(event) { if ( !$(event.target).hasClass('.box') && !$(event.target).hasClass('properties')) { // $(".textbox_properties").hide(); } }); */ $(document).ready(function() { $(document).ajaxStart(function(){ $('#ajaxBusy').css("background", "#f00"); }).ajaxStop(function(){ $('#ajaxBusy').css("background", "#0f0"); }); }); //LIVE Click Handlers: $('.image_rotate').live("click", function(e) { var r = $(this).getResource(); var id = r.id; var url = "/edit/image/rotate/" + id + "/"; window.open(url); }); $('.download_doc').live("click", function(e) { var r = $(this).getResource(); var path = r.file; var base_url = "http://" + window.location.hostname window.open(base_url + path); }); $('.printMe').live("click", function(e) { var page = $(this).getCanvas(); var page_id = page.id; // var url = BASE_URL + "page_pdf/?p=" + page_id + "&a=" + ARTICLE_ID; var url = BASE_URL + "print_article/?id=" + ARTICLE_ID; window.open(url); }); $(function() { $('.viewFrontend').live("click", function(e) { window.open(FRONTEND_URL); e.preventDefault(); e.stopPropagation(); }); }); $('.upload_srts').live("click", function(e) { var r = $(this).getResource(); var media_id = r.media_id; var type = r.mime == 'video' ? 'video' : 'audio'; if (media_id == 0) { alert("sorry, there was some problem with converting this audio / video, ID: " + r.id); } else { var adminUrl = "/admin/editor/" + type + "/" + r.media_id.toString(); window.open(adminUrl); } }); $('.play_media').live("click", function(e) { var r = $(this).getResource(); var filePath = r.file; var base_url = "http://" + window.location.hostname; window.open(base_url + filePath); }); $('.toggle_handle').live("click", function() { var $that = $(this); var page = $(this).parents('.canvas'); page.find('.ruler').each(function() { if ($(this).is(":visible")) { $(this).fadeOut("fast"); } else { $(this).fadeIn("fast"); }; }); }); $('.delete_page').live("click", function(e) { var canvas = $(this).getCanvas(); if (confirm("Are you sure you want to delete this page?")) { canvas.deleteme(); } }); $('.move_page_up').live("click", function(e) { var canvas = $(this).getCanvas(); var currIndex = canvas.jq.index(".canvas"); if (currIndex == 0) { return false; } var newIndex = currIndex - 1; canvas.movePage(newIndex); }); $('.move_page_down').live("click", function(e) { var canvas = $(this).getCanvas(); var currIndex = canvas.jq.index(".canvas"); var newIndex = currIndex + 1; canvas.movePage(newIndex); });