jquery.portal.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /**
  2. * portal - jQuery EasyUI
  3. *
  4. * Licensed under the GPL:
  5. * http://www.gnu.org/licenses/gpl.txt
  6. *
  7. * Copyright 2010 stworthy [ stworthy@gmail.com ]
  8. *
  9. * Dependencies:
  10. * draggable
  11. * panel
  12. *
  13. */
  14. (function($){
  15. /**
  16. * initialize the portal
  17. */
  18. function init(target){
  19. $(target).addClass('portal');
  20. var table = $('<table border="0" cellspacing="0" cellpadding="0"><tr></tr></table>').appendTo(target);
  21. var tr = table.find('tr');
  22. var columnWidths = [];
  23. var totalWidth = 0;
  24. $(target).find('>div').each(function(){ // each column panel
  25. var column = $(this);
  26. totalWidth += column.outerWidth();
  27. columnWidths.push(column.outerWidth());
  28. var td = $('<td class="portal-column-td"></td>').appendTo(tr)
  29. column.addClass('portal-column').appendTo(td);
  30. column.find('>div').each(function(){ // each portal panel
  31. var p = $(this).addClass('portal-p').panel({
  32. doSize:false,
  33. cls:'portal-panel'
  34. });
  35. makeDraggable(target, p);
  36. });
  37. });
  38. for(var i=0; i<columnWidths.length; i++){
  39. columnWidths[i] /= totalWidth;
  40. }
  41. $(target).bind('_resize', function(){
  42. var opts = $.data(target, 'portal').options;
  43. if (opts.fit == true){
  44. setSize(target);
  45. }
  46. return false;
  47. });
  48. return columnWidths;
  49. }
  50. function setSize(target){
  51. var t = $(target);
  52. var opts = $.data(target, 'portal').options;
  53. if (opts.fit){
  54. var p = t.parent();
  55. opts.width = p.width();
  56. opts.height = p.height();
  57. }
  58. if (!isNaN(opts.width)){
  59. if ($.boxModel == true){
  60. t.width(opts.width - (t.outerWidth() - t.width()));
  61. } else {
  62. t.width(opts.width);
  63. }
  64. } else {
  65. t.width('auto');
  66. }
  67. if (!isNaN(opts.height)){
  68. if ($.boxModel == true){
  69. t.height(opts.height - (t.outerHeight() - t.height()));
  70. } else {
  71. t.height(opts.height);
  72. }
  73. } else {
  74. t.height('auto');
  75. }
  76. var hasScroll = t.find('>table').outerHeight() > t.height();
  77. var width = t.width();
  78. var columnWidths = $.data(target, 'portal').columnWidths;
  79. var leftWidth = 0;
  80. // calculate and set every column size
  81. for(var i=0; i<columnWidths.length; i++){
  82. var p = t.find('div.portal-column:eq('+i+')');
  83. var w = Math.floor(width * columnWidths[i]);
  84. if (i == columnWidths.length - 1){
  85. w = width - leftWidth - (hasScroll == true ? 28 : 10);
  86. }
  87. if ($.boxModel == true){
  88. p.width(w - (p.outerWidth()-p.width()));
  89. } else {
  90. p.width(w);
  91. }
  92. leftWidth += p.outerWidth();
  93. // resize every panel of the column
  94. p.find('div.portal-p').panel('resize', {width:p.width()});
  95. }
  96. }
  97. /**
  98. * set draggable feature for the specified panel
  99. */
  100. function makeDraggable(target, panel){
  101. var spacer;
  102. panel.panel('panel').draggable({
  103. handle:'>div.panel-header>div.panel-title',
  104. proxy:function(source){
  105. var p = $('<div class="portal-proxy">proxy</div>').insertAfter(source);
  106. p.width($(source).width());
  107. p.height($(source).height());
  108. p.html($(source).html());
  109. p.find('div.portal-p').removeClass('portal-p');
  110. return p;
  111. },
  112. onStartDrag:function(e){
  113. $(this).hide();
  114. spacer = $('<div class="portal-spacer"></div>').insertAfter(this);
  115. setSpacerSize($(this).outerWidth(), $(this).outerHeight());
  116. },
  117. onDrag:function(e){
  118. var p = findPanel(e, this);
  119. if (p){
  120. if (p.pos == 'up'){
  121. spacer.insertBefore(p.target);
  122. } else {
  123. spacer.insertAfter(p.target);
  124. }
  125. setSpacerSize($(p.target).outerWidth());
  126. } else {
  127. var c = findColumn(e);
  128. if (c){
  129. if (c.find('div.portal-spacer').length == 0){
  130. spacer.appendTo(c);
  131. setSize(target);
  132. setSpacerSize(c.width());
  133. }
  134. }
  135. }
  136. },
  137. onStopDrag:function(e){
  138. $(this).css('position', 'static');
  139. $(this).show();
  140. spacer.hide();
  141. $(this).insertAfter(spacer);
  142. spacer.remove();
  143. setSize(target);
  144. var opts = $.data(target, 'portal').options;
  145. opts.onStopDrag.call();
  146. }
  147. });
  148. /**
  149. * find which panel the cursor is over
  150. */
  151. function findPanel(e, source){
  152. var result = null;
  153. $(target).find('div.portal-p').each(function(){
  154. var pal = $(this).panel('panel');
  155. if (pal[0] != source){
  156. var pos = pal.offset();
  157. if (e.pageX > pos.left && e.pageX < pos.left + pal.outerWidth()
  158. && e.pageY > pos.top && e.pageY < pos.top + pal.outerHeight()){
  159. if (e.pageY > pos.top + pal.outerHeight() / 2){
  160. result = {
  161. target:pal,
  162. pos:'down'
  163. };
  164. } else {
  165. result = {
  166. target:pal,
  167. pos:'up'
  168. }
  169. }
  170. }
  171. }
  172. });
  173. return result;
  174. }
  175. /**
  176. * find which portal column the cursor is over
  177. */
  178. function findColumn(e){
  179. var result = null;
  180. $(target).find('div.portal-column').each(function(){
  181. var pal = $(this);
  182. var pos = pal.offset();
  183. if (e.pageX > pos.left && e.pageX < pos.left + pal.outerWidth()){
  184. result = pal;
  185. }
  186. });
  187. return result;
  188. }
  189. /**
  190. * set the spacer size
  191. */
  192. function setSpacerSize(width, height){
  193. if ($.boxModel == true){
  194. spacer.width(width - (spacer.outerWidth() - spacer.width()));
  195. if (height){
  196. spacer.height(height - (spacer.outerHeight() - spacer.height()));
  197. }
  198. } else {
  199. spacer.width(width);
  200. if (height){
  201. spacer.height(height);
  202. }
  203. }
  204. }
  205. }
  206. function json2str(o) {
  207. var arr = [];
  208. var fmt = function(s) {
  209. if (typeof s == 'object' && s != null) return json2str(s);
  210. return /^(string|number)$/.test(typeof s) ? "'" + s + "'" : s;
  211. }
  212. for (var i in o) arr.push("'" + i + "':" + fmt(o[i]));
  213. return '{' + arr.join(',') + '}';
  214. }
  215. $.fn.portal = function(options, param){
  216. if (typeof options == 'string'){
  217. return $.fn.portal.methods[options](this, param);
  218. }
  219. options = options || {};
  220. return this.each(function(){
  221. var state = $.data(this, 'portal');
  222. if (state){
  223. $.extend(state.options, options);
  224. } else {
  225. state = $.data(this, 'portal', {
  226. options: $.extend({}, $.fn.portal.defaults, $.fn.portal.parseOptions(this), options),
  227. columnWidths: init(this)
  228. });
  229. }
  230. if (state.options.border){
  231. $(this).removeClass('portal-noborder');
  232. } else {
  233. $(this).addClass('portal-noborder');
  234. }
  235. setSize(this);
  236. });
  237. };
  238. $.fn.portal.methods = {
  239. options: function(jq){
  240. return $.data(jq[0], 'portal').options;
  241. },
  242. resize: function(jq, param){
  243. return jq.each(function(){
  244. if (param){
  245. var opts = $.data(this, 'portal').options;
  246. if (param.width) opts.width = param.width;
  247. if (param.height) opts.height = param.height;
  248. }
  249. setSize(this);
  250. });
  251. },
  252. getPanels: function(jq, columnIndex){
  253. var c = jq; // the panel container
  254. if (columnIndex){
  255. c = jq.find('div.portal-column:eq(' + columnIndex + ')');
  256. }
  257. var panels = [];
  258. c.find('div.portal-p').each(function(){
  259. panels.push($(this));
  260. });
  261. return panels;
  262. },
  263. add: function(jq, param){ // param: {panel,columnIndex}
  264. return jq.each(function(){
  265. var c = $(this).find('div.portal-column:eq(' + param.columnIndex + ')');
  266. var p = param.panel.addClass('portal-p');
  267. p.panel('open');
  268. p.panel('panel').addClass('portal-panel').appendTo(c);
  269. makeDraggable(this, p);
  270. p.panel('resize', {width:c.width()});
  271. });
  272. },
  273. remove: function(jq, panel){
  274. return jq.each(function(){
  275. var panels = $(this).portal('getPanels');
  276. for(var i=0; i<panels.length; i++){
  277. var p = panels[i];
  278. if (p[0] == $(panel)[0]){
  279. p.panel('destroy');
  280. }
  281. }
  282. });
  283. },
  284. getLayout: function(jq){
  285. var portal = $(jq).portal('getPanels');
  286. var portalColumnTd = $(jq).find('.portal-column-td');
  287. var portalLayout="{";
  288. var t = 0;
  289. for(var i = 0; i < portalColumnTd.length;i++){
  290. var panel="\""+i+"\":[";
  291. var colomLength = $(portalColumnTd[i]).find('.portal-panel').length;
  292. for(var j = 0; j < colomLength;j++){
  293. panel += json2str(portal[t].panel('options'))+",";
  294. t++;
  295. }
  296. panel = panel.substring(0,panel.length-1)+"]";
  297. portalLayout += panel+",";
  298. }
  299. if(portalLayout.substring(0,portalLayout.length-1) == ""){
  300. portalLayout = portalLayout+"}";
  301. }else{
  302. portalLayout = portalLayout.substring(0,portalLayout.length-1)+"}";
  303. }
  304. return portalLayout;
  305. },
  306. getPanelForTitle:function(jq,title){
  307. var portal = $(jq).portal('getPanels');
  308. var panel;
  309. $.each(portal,function(i,v){
  310. if(v.panel('options').title == title) {
  311. panel = v;
  312. return;
  313. }
  314. });
  315. return panel;
  316. }
  317. };
  318. $.fn.portal.parseOptions = function(target){
  319. var t = $(target);
  320. return {
  321. width: (parseInt(target.style.width) || undefined),
  322. height: (parseInt(target.style.height) || undefined),
  323. border: (t.attr('border') ? t.attr('border') == 'true' : undefined),
  324. fit: (t.attr('fit') ? t.attr('fit') == 'true' : undefined)
  325. };
  326. };
  327. $.fn.portal.defaults = {
  328. width:'auto',
  329. height:'auto',
  330. border:true,
  331. fit:false,
  332. onStopDrag:function(){
  333. }
  334. };
  335. })(jQuery);