Textpattern CMS support forum
You are not logged in. Register | Login | Help
- Topics: Active | Unanswered
Re: New sections tab, multi-edit control block
Btw, the categories panel is broken.
The IDs are used to link the .multi-option blocks to the edit_method options. The IDs are named after the values. Since they don’t match, the categories panel doesn’t work.
These changes would require that the scripts functionality is changed too in some form. Which is why I was suggesting the random ID thing. Since you have an random ID consistently present, the ID can be broken apart correctly.
Offline
Re: New sections tab, multi-edit control block
Gocom wrote:
Btw, the categories panel is broken.
Yikes. OK than. Code suggestions?
The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.
Hire Txp Builders – finely-crafted code, design and Txp
Offline
Offline
Re: New sections tab, multi-edit control block
Gocom wrote:
I will send a patch soon. It will contain some other optimizations too to the multi-edit jQuery plugin. Wait for half an hour or so.
Legend, thanks.
The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.
Hire Txp Builders – finely-crafted code, design and Txp
Offline
Re: New sections tab, multi-edit control block
Stef, please take a look:
Index: textpattern.js
===================================================================
--- textpattern.js (revision 3886)
+++ textpattern.js (working copy)
@@ -143,13 +143,13 @@
/**
* Multi-edit functions
* @param string|obj method
- * @param obj options
+ * @param obj opt
* @since 4.5.0
*/
-jQuery.fn.txpMultiEditForm = function(method, options)
+jQuery.fn.txpMultiEditForm = function(method, opt)
{
- var args = {}, opt;
+ var args = {};
var defaults = {
'checkbox' : 'input[name="selected[]"][type=checkbox]',
@@ -166,26 +166,23 @@
if ($.type(method) !== 'string')
{
- options = method;
+ opt = method;
method = null;
}
else
{
- args = options;
+ args = opt;
}
- opt = options;
-
this.closest('form').each(function() {
var $this = $(this), form = {}, public = {}, private = {};
-
+
if ($this.data('_txpMultiEdit'))
{
form = $this.data('_txpMultiEdit');
opt = $.extend(form.opt, opt);
}
-
else
{
opt = $.extend(defaults, opt);
@@ -212,6 +209,11 @@
'value' : null,
'html' : null
}, options);
+
+ if (!settings.value)
+ {
+ return public;
+ }
var option = form.editMethod.find('option').filter(function() {
return $(this).attr('value') === settings.value;
@@ -247,7 +249,7 @@
return public;
};
-
+
/**
* Selects rows based on supplied arguments. Only one of the filters applies at time.
* @param array index Select based on row's index.
@@ -255,7 +257,7 @@
* @param array value [value1, value2, value3, ...]
* @param bool checked Set matched checked or unchecked. FALSE to uncheck.
*/
-
+
public.select = function(options)
{
var settings = $.extend({
@@ -264,58 +266,58 @@
'value' : null,
'checked' : true
}, options);
-
+
var obj = $this.find(form.pattern);
-
+
if (settings.value !== null)
{
obj = obj.filter(function() {
return $.inArray($(this).attr('value'), settings.value) !== -1;
});
}
-
+
else if (settings.index !== null)
{
obj = obj.filter(function(index) {
return $.inArray(index, settings.index) !== -1;
});
}
-
+
else if (settings.range !== null)
{
obj = obj.slice(settings.range[0], settings.range[1]);
}
-
+
obj.prop('checked', settings.checked).change();
return public;
};
-
+
/**
* Binds checkboxes
*/
-
+
private.bindRows = function()
{
form.rows = $this.find(opt.row);
form.boxes = $this.find(form.pattern);
return private;
};
-
+
/**
* Highlights selected rows
*/
-
+
private.highlight = function()
{
form.boxes.filter(':checked').closest(opt.highlighted).addClass(opt.selectedClass);
form.boxes.filter(':not(:checked)').closest(opt.highlighted).removeClass(opt.selectedClass);
return private;
};
-
+
/**
* Extends click region to whole row
*/
-
+
private.extendedClick = function()
{
if (opt.rowClick)
@@ -328,9 +330,9 @@
}
obj.live('click', function(e) {
-
+
var self = ($(e.target).is(form.pattern) || $(this).is(form.pattern));
-
+
if (!self && (e.target != this || $(this).is('a, :input') || $(e.target).is('a, :input')))
{
return;
@@ -347,72 +349,53 @@
{
return;
}
-
+
private.bindRows();
-
+
var checked = box.prop('checked');
-
+
if (self)
{
checked = !checked;
}
-
- if (form.lastCheck)
+
+ if (e.shiftKey && form.lastCheck)
{
+ var start = form.boxes.index(box);
var end = form.boxes.index(form.lastCheck);
+
+ public.select({
+ 'range' : [Math.min(start, end), Math.max(start, end)+1],
+ 'checked' : !checked
+ });
}
-
+ else if (!self)
+ {
+ box.prop('checked', !checked).change();
+ }
+
if (checked === false)
{
- if (e.shiftKey && form.lastCheck)
- {
- var start = form.boxes.index(box);
-
- public.select({
- 'range' : [Math.min(start, end), Math.max(start, end)+1]
- });
- }
-
- else if (!self)
- {
- box.prop('checked', true).change();
- }
-
form.lastCheck = box;
}
-
else
{
- if (e.shiftKey && form.lastCheck)
- {
- var start = form.boxes.index(box);
-
- public.select({
- 'range' : [Math.min(start, end), Math.max(start, end)+1],
- 'checked' : false
- });
- }
- else if (!self)
- {
- box.prop('checked', false).change();
- }
-
form.lastCheck = null;
}
});
-
+
return private;
};
-
+
/**
* Tracks row checks
*/
-
+
private.checked = function()
{
form.boxes.live('change', function(e) {
var box = $(this);
-
+
if (box.prop('checked'))
{
$(this).closest(opt.highlighted).addClass(opt.selectedClass);
@@ -424,14 +407,14 @@
form.selectAll.prop('checked', false);
}
});
-
+
return private;
};
-
+
/**
* Handles edit method selecting
*/
-
+
private.changeMethod = function()
{
form.button.hide();
@@ -482,14 +465,29 @@
{
private.bindRows().highlight().extendedClick().checked().changeMethod().sendForm();
- $this.find('.multi-option:not(.multi-step)').each(function() {
- public.addOption({
- 'label' : null,
- 'html' : $(this).contents(),
- 'value' : $(this).attr('id').substring(13)
+ (function() {
+ var multiOptions = $this.find('.multi-option:not(.multi-step)');
+
+ form.editMethod.find('option[value!=""]').each(function() {
+ var value = $(this).val();
+
+ var option = multiOptions.filter(function() {
+ return $(this).hasClass('multi-option-'+value);
+ });
+
+ if (option.length > 0)
+ {
+ public.addOption({
+ 'label' : null,
+ 'html' : option.eq(0).contents(),
+ 'value' : $(this).val()
+ });
+ }
});
- }).remove();
+ multiOptions.remove();
+ })();
+
form.selectAll.live('change', function(e) {
public.select({
'checked' : $(this).prop('checked')
Index: lib/txplib_html.php
===================================================================
--- lib/txplib_html.php (revision 3886)
+++ lib/txplib_html.php (working copy)
@@ -876,11 +876,10 @@
* @param string $dir Sorting direction
* @param string $crit Search criterion
* @param string $search_method Search method
- * @param string $id_suffix Added to the HTML id attribute; useful if more than one similar control placed per page
* @return string HTML
*/
- function multi_edit($options, $event=null, $step=null, $page='', $sort='', $dir='', $crit='', $search_method='', $id_suffix='')
+ function multi_edit($options, $event=null, $step=null, $page='', $sort='', $dir='', $crit='', $search_method='')
{
$html = $methods = array();
$methods[''] = gTxt('with_selected_option');
@@ -905,8 +904,7 @@
if (isset($option['html']))
{
- $html[$value] = '<div class="multi-option" id="multi-option-'.
- txpspecialchars($value).($id_suffix ? '-'.txpspecialchars($id_suffix) : '').'">'.$option['html'].'</div>';
+ $html[$value] = '<div class="multi-option multi-option-'.txpspecialchars($value).'">'.$option['html'].'</div>';
}
}
else
It basically changes the thing to work with classes instead of IDs. This solves all the collisions issues. Instead of the JavaScript picking .multi-options it uses the actual <option> elements to trace the steps from markup. When 4.6 and HTML5 lands, those classes could be changed to data- attributes even simplifying the logic even more.
Other changes are some basic cleanup and small fixes. Main thing is that it now prevents hooking with addOption() method to the default empty option (by accident) as that would just cause a loop of confirmation dialogs if anything. It also merges two almost identical condition blocks used for shift+click. Just reverses the booleans in props and likes, leading to much shorter code in that scenario.
Last edited by Gocom (2012-07-01 22:49:23)
Offline
Re: New sections tab, multi-edit control block
If you are wondering why the diff is as big as it is, is because I removed my auto-indents. In Textpattern’s source empty lines aren’t leveled, so I decided to remove those extra indentations to match the general styling.
Last edited by Gocom (2012-07-01 22:57:23)
Offline
Re: New sections tab, multi-edit control block
Works like a dream. Awesome work, as always sir. I missed the nightly build window by 11 minutes because I was playing with it for too long and admiring your code :-)
The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.
Hire Txp Builders – finely-crafted code, design and Txp
Offline