Skip to content
This repository has been archived by the owner on Apr 8, 2019. It is now read-only.

Commit

Permalink
New page editor layout model
Browse files Browse the repository at this point in the history
  • Loading branch information
phuong_vu committed Oct 9, 2013
1 parent 489f972 commit 3a88d1f
Show file tree
Hide file tree
Showing 9 changed files with 304 additions and 186 deletions.
4 changes: 2 additions & 2 deletions portal/web/src/main/java/org/gatein/portal/package-info.java
Expand Up @@ -26,8 +26,8 @@
@Script(src = "javascripts/jquery-ui-1.10.3.custom.js"),
@Script(src = "javascripts/underscore.js"),
@Script(src = "javascripts/backbone.js"),
@Script(src = "javascripts/page-model.js"),
@Script(src = "javascripts/page-editor.js")})
@Script(src = "javascripts/layout-model.js"),
@Script(src = "javascripts/layout-view.js")})
package org.gatein.portal;

import juzu.Application;
Expand Down
@@ -0,0 +1,191 @@
(function() {
/**
*
*/
var LayoutComponent = Backbone.Model.extend({
initialize : function() {
this.set({
_parent : null,
draggable : false,
droppable : false
});
},
isAllowDropping : function(dragObj) {
return false;
},
getType : function() {
return 'LayoutComponent';
},
getId : function() {
return this.get('id') || this.cid;
},
getParent : function() {
return this.get('_parent');
},
getRoot : function() {
var parent = this, root;
do {
root = parent;
parent = parent.getParent();
} while (parent);
return root;
},
getIndex : function() {
if (this.getParent()) {
return this.getParent().indexOf(this);
} else {
return -1;
}
}
});

/**
*
*/
var Application = LayoutComponent.extend({
initialize : function() {
LayoutComponent.prototype.initialize.call(this);
this.set({
draggable : true
});
},
getType : function() {
return 'Application';
}
});

/**
*
*/
var Container = LayoutComponent.extend({
initialize : function() {
LayoutComponent.prototype.initialize.call(this);
this.set({
draggable : true,
droppable : true,

// Should not access directly to those internal attributes
_childrens : new Backbone.Collection(),
// Allow type 'Application' and 'Container'to be dropped
_childTypes : [ Application.prototype.getType(), 'Container' ]
});

var _this = this;
this.get('_childrens').on('add', function(child) {
_this.trigger('addChild.eXo.Container', child, _this);
});
this.get('_childrens').on('remove', function(child) {
_this.trigger('removeChild.eXo.Container', child, _this);
});
},

isChildSupported : function(dragObj) {
// Check for supported types
if (dragObj && $.isFunction(dragObj.getType)) {
var type = $.trim(dragObj.getType());
return this.get('droppable') && $.inArray(type, this.get('_childTypes')) != -1;
} else {
return false;
}
},
getType : function() {
return 'Container';
},

/**
* methods on childrens
*/
//
addChild : function(child, idx) {
child = typeof child == 'string' ? this.getChild(child) : child;

if (child && this.isChildSupported(child)) {
var _this = this;
this.listenTo(child, 'addChild.eXo.Container', function(addedChild, container) {
_this.trigger('addChild.eXo.Container', addedChild, container);
});
this.listenTo(child, 'removeChild.eXo.Container', function(addedChild, container) {
_this.trigger('removeChild.eXo.Container', addedChild, container);
});

if (child.getParent() != null) {
child.getParent().removeChild(child, true);
}
child.set('_parent', this);
this.get('_childrens').add(child, {
at : idx
});
}

return this;
},
//
removeChild : function(child, silent) {
child = typeof child == 'string' ? this.getChild(child) : child;

if (child && child.getParent() === this) {
child.set('_parent', null);
this.get('_childrens').remove(child, {'silent' : silent});
this.stopListening(child);
}
return this;
},
getChild : function(id) {
return this.get('_childrens').get(id);
},
indexOf : function(child) {
child = typeof child == 'string' ? this.getChild(child) : child;
return this.get('_childrens').indexOf(child);
},
at : function(idx) {
return this.get('_childrens').at(idx);
},
getDescendant : function(id) {
var child = this.getChild(id);
if (!child) {
var cont = this.get('_childrens').find(function(elem) {
if ($.isFunction(elem.getDescendant)) {
return elem.getDescendant.call(elem, id);
}
});
cont != null && (child = cont.getChild(id));
}
return child;
},

//
addChildType : function(childType) {
var type = $.trim(childType);
var types = this.get('_childTypes');

if ($.inArray(type, types) == -1) {
types.put(type);
this.trigger('addChildType.eXo.Container', type);
}
return this;
},
//
removeChildType : function(childType) {
var type = $.trim(childType);
var types = this.get('_childTypes');
var idx = $.inArray(type, types);

if (idx != -1) {
types.splice(idx, 1);
this.trigger('removeChildType.eXo.Container', type);
}
return this;
}
});

var layoutDef = {
'LayoutComponent' : LayoutComponent,
'Application' : Application,
'Container' : Container
};
if (typeof window.require === "function" && window.require.amd) {
return layoutDef;
} else {
return $.extend(window, layoutDef);
}
})();
@@ -0,0 +1,61 @@
(function() {
var LayoutView = Backbone.View.extend({
el : '.editing',

initialize : function() {
var editing = this.$el.hasClass("editing");
var view = this;

if (editing) {
this.$( ".sortable" ).sortable({
placeholder: "portlet-placeholder",
revert: true,
update : function(event, ui) {
var cont = view.model.getDescendant(this.id);
var prev = $(ui.item).prev('.portlet');
var idx = prev.length ? $('#' + cont.getId() + ' > .portlet').index(prev.get(0)) + 1 : 0;

cont.addChild(ui.item.attr('id'), idx);
}
});
}

this.listenTo(this.model, 'addChild.eXo.Container', this.onAddChild);
this.listenTo(this.model, 'removeChild.eXo.Container', this.onRemoveChild);
},

onAddChild : function(child, container) {
var $app = $('#' + child.getId());
var prev = container.at(child.getIndex() - 1);
if (prev) {
$app.insertAfter($('#' + prev.getId()));
} else {
var $cont = $('#' + container.getId());
$cont.prepend($app);
}
},

onRemoveChild : function(child, container) {
var $app = $('#' + child.getId());
$app.remove();
}
});

$(function() {
var root = $('.editing');
var url = root.attr('data-editURL');

var container = new Container();
$('.sortable').each(function() {
var cont = new Container({id : this.id});

$(this).children('.portlet').each(function() {
var app = new Application({'id' : this.id});
cont.addChild(app);
});
container.addChild(cont);
});

window.layoutView = new LayoutView({model : container});
});
})();

This file was deleted.

This file was deleted.

Expand Up @@ -33,15 +33,15 @@
@RunWith(QUnitRunner.class)
@QUnitResources("src/test/resources/assets")
@RunAsClient
public class EditorJSTestCase {
public class LayoutEditorTest {

@Deployment
public static Archive<?> createDeployment() {
return ShrinkWrap.create(WebArchive.class, "test.war")
.as(ExplodedImporter.class).importDirectory("src/main/resources").as(GenericArchive.class);
}

@QUnitTest("testJS/editorTest.html")
@QUnitTest("testJS/LayoutEditorTest.html")
public void moveAppTest() {
// empty body - only the annotations are used
}
Expand Down
Expand Up @@ -23,8 +23,8 @@
<script type="text/javascript" src="../org/gatein/portal/assets/javascripts/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="../org/gatein/portal/assets/javascripts/underscore.js"></script>
<script type="text/javascript" src="../org/gatein/portal/assets/javascripts/backbone.js"></script>
<script type="text/javascript" src="../org/gatein/portal/assets/javascripts/page-model.js"></script>
<script type="text/javascript" src="editorTest.js"></script>
<script type="text/javascript" src="../org/gatein/portal/assets/javascripts/layout-model.js"></script>
<script type="text/javascript" src="LayoutEditorTest.js"></script>
</head>
<body>
<h1 id="qunit-header">QUnit Test Suite</h1>
Expand Down

0 comments on commit 3a88d1f

Please sign in to comment.