source: dynamicfieldsplugin/trunk/dynfields/htdocs/layout.js

Last change on this file was 17871, checked in by Ryan J Ollos, 3 years ago

2.6.0dev: Fix textarea layout with Trac 1.0.x

Refs #8971.

  • Property svn:executable set to *
File size: 6.2 KB
Line 
1/*
2 * Layout 'class'
3 */
4var Layout = function (name) {
5  this.name = name;
6
7  // Selector for all field tds/ths
8  this.selector = '';
9
10  // Return the given field name's td/th element
11  this.get_tx = function (field) {};
12
13  // Return the given td/th element's field name
14  this.get_field = function (tx) {};
15
16  // Reorder the fields
17  this.order_fields = function (fields) {};
18
19  // Returns true if the field needs its own row
20  this.needs_own_row = function (field) {
21    var element = document.getElementById('field-' + field);
22    return element !== null && element.tagName.toLowerCase() === 'textarea';
23  };
24
25  var saved_field_order = {};
26  var prev_fields = null;
27
28  // Update the field layout
29  this.update = function () {
30    var this_ = this;
31    var name = this.name;
32
33    // save original field order
34    if (!(name in saved_field_order)) {
35      saved_field_order[name] = [];
36      jQuery(this.selector).each(function (i, e) {
37        var field = this_.get_field($(this));
38        if (field)
39          saved_field_order[name].push(field);
40      });
41    }
42
43    // get visible and hidden fields
44    var visible = [];
45    var hidden = [];
46    jQuery.each(saved_field_order[name], function (i, field) {
47      var tx = this_.get_tx(field);
48      if (tx.hasClass('dynfields-hide')) {
49        hidden.push(field);
50      } else {
51        visible.push(field);
52      }
53    });
54
55    // get new field order
56    var new_fields = jQuery.merge(visible, hidden); // warning: side-effects!
57
58    // order the fields
59    if (JSON.stringify(new_fields) !== JSON.stringify(prev_fields)) {
60      this.order_fields(new_fields);
61      prev_fields = new_fields;
62    }
63  };
64};
65
66var dynfields_group = function(values, n, callback) {
67  var groups = [];
68  var buf = [];
69  jQuery.each(values, function(index, name) {
70    if (callback(name)) {
71      if (buf.length !== 0) {
72        groups.push(buf.slice(0, n));
73        buf = [];
74      }
75      groups.push([name, true]);
76    } else {
77      buf.push(name);
78      if (buf.length === n) {
79        groups.push(buf.slice(0, n));
80        buf = [];
81      }
82    }
83  });
84  if (buf.length !== 0) {
85    groups.push(buf.slice(0, n));
86  }
87  return groups;
88};
89
90
91/*
92 * Inputs Layout implementation
93 */
94var inputs_layout = new Layout('inputs');
95
96// selector
97inputs_layout.selector = '#properties td[class!=fullrow]:parent';
98
99// get_tx
100inputs_layout.get_tx = function (field) {
101  return jQuery('#field-' + field).closest('td');
102};
103
104// get_field
105inputs_layout.get_field = function (td) {
106  var name = td.attr('data-dynfields-name');
107  if (!name) {
108    var input = td.find(':input:first');
109    name = input.length !== 0 ? input[0].id.slice(6) : '<missing>';
110    td.attr('data-dynfields-name', name);
111  }
112  return name !== '<missing>' ? name : '';
113};
114
115inputs_layout.order_fields = function (new_fields) {
116  var this_ = this;
117  var properties = jQuery('#properties');
118  var target_row = properties.find('textarea[name=field_description]')
119                             .closest('tr');
120  var cells = {};
121  var headers = {};
122  var fullrows = {};
123  jQuery.each(new_fields, function(idx, name) {
124    var cell = this_.get_tx(name);
125    cells[name] = cell;
126    headers[name] = cell.prev('th');
127    // colspan is checked for Trac 1.0.x compatibility.
128    fullrows[name] = cell.hasClass('fullrow') || cell.attr('colspan') === '3';
129  });
130  var groups = dynfields_group(new_fields, 2,
131                               function(name) { return fullrows[name] });
132  jQuery.each(groups, function(idx, group) {
133    var col1 = group[0];
134    var col2 = group[1];
135    var cell1 = cells[col1];
136    var header1 = headers[col1];
137    cell1.removeClass('col2');
138    cell1.addClass('col1');
139    header1.removeClass('col2');
140    header1.addClass('col1');
141    var row = jQuery('<tr>').append(headers[col1], cell1);
142    if (col2 !== true) {
143      var cell2, header2;
144      if (col2) {
145        cell2 = cells[col2];
146        header2 = headers[col2];
147        cell2.removeClass('col1');
148        header2.removeClass('col1');
149      } else {
150        cell2 = jQuery('<td>');
151        header2 = jQuery('<th>');
152      }
153      header2.addClass('col2');
154      cell2.addClass('col2');
155      row.append(header2, cell2);
156    }
157    target_row.after(row);
158    target_row = row;
159  });
160  properties.find('> table > tbody > tr')
161        .not('#dynfields-show-link')
162        .each(function() {
163    var row = $(this);
164    var headers = row.children('th');
165    if (headers.length === 0 || !jQuery.trim(headers.text()))
166      row.remove();
167  });
168};
169
170
171/*
172 * Header Layout implementation
173 */
174var header_layout = new Layout('header');
175
176// selector
177header_layout.selector = '#ticket .properties th:parent';
178
179// get_tx
180header_layout.get_tx = function (field) {
181  return jQuery('#h_' + field);
182};
183
184// get_field
185header_layout.get_field = function (th) {
186  var name = th.attr('data-dynfields-name');
187  if (!name) {
188    var name = th.length !== 0 ? th[0].id.slice(2) : '<missing>';
189    th.attr('data-dynfields-name', name);
190  }
191  return name !== '<missing>' ? name : '';
192};
193
194header_layout.order_fields = function (new_fields) {
195  var this_ = this;
196  var cells = {};
197  var headers = {};
198  var fullrows = {};
199  jQuery.each(new_fields, function(idx, name) {
200    var header = this_.get_tx(name);
201    var cell = header.next('td');
202    headers[name] = header;
203    cells[name] = cell;
204    fullrows[name] = cell.attr('colspan') === '3';
205  });
206  var groups = dynfields_group(new_fields, 2,
207                               function(name) { return fullrows[name] });
208  var tbody = jQuery('#ticket table.properties > tbody');
209  var target_row;
210  jQuery.each(groups, function(idx, group) {
211    var col1 = group[0];
212    var col2 = group[1];
213    var row = jQuery('<tr>').append(headers[col1], cells[col1]);
214    if (col2 !== true) {
215      var header2, cell2;
216      if (col2) {
217        header2 = headers[col2];
218        cell2 = cells[col2];
219      } else {
220        cell2 = jQuery('<td>');
221        header2 = jQuery('<th>');
222      }
223      row.append(header2, cell2);
224    }
225    if (target_row === undefined) {
226      tbody.prepend(row);
227    } else {
228      target_row.after(row);
229    }
230    target_row = row;
231  });
232  tbody.children('tr').each(function() {
233    var row = $(this);
234    var headers = row.children('th');
235    if (headers.length === 0 || !jQuery.trim(headers.text()))
236      row.remove();
237  });
238};
Note: See TracBrowser for help on using the repository browser.