<__trans phrase="Manage [_1]" params="">
<__trans phrase=" src="images/indicator.white.gif" /> <__trans phrase="Loading...">
-listing-form" method="POST" action=""> " /> " /> " /> " />
_label" class="text short disabled" disabled="disabled" placeholder="<__trans phrase="[_1] label" params="">">
jQuery('div.indicator') .hide() .bind('ajaxStart', function() { jQuery(this).show(); }) .bind('ajaxStop', function() { jQuery(this).hide(); }); var dummy = 1; var checksum = ''; var isdirty = false; var indent = 35; var root_pos = jQuery('#root').position(); function setDirty( dirty ) { isdirty = dirty; if ( isdirty ) { jQuery('button.save').removeAttr('disabled').removeClass('disabled'); } else { jQuery('button.save').attr('disabled', 'disabled').addClass('disabled'); } } function loginAgain(fn) { jQuery(window) .unbind('dialogReady.loginAgain') .bind('dialogReady.loginAgain', function(){ var dialog = jQuery('#mt-dialog-iframe').contents(); dialog .find('#sign-in-button') .text('<__trans phrase="Continue" escape="js">') .unbind() .click(function(){ dialog.find('#msg-block').empty(); jQuery.ajax({ type: 'POST', contentType: 'application/x-www-form-urlencoded; charset=utf-8', async: false, url: '', dataType: 'json', data: { __mode: 'login_json', username: dialog.find('#username').val(), password: dialog.find('#password').val() }, success: function(data) { var token = data.result['magic_token']; if (token) { jQuery('input[name="magic_token"]').val(token); jQuery('a[href*="magic_token="]').each(function() { var replace = jQuery(this) .attr('href') .replace(/magic_token=[\d\w]+/, 'magic_token=' + token); jQuery(this).attr('href', replace); }); } jQuery.fn.mtDialog.close(); fn(data); return false; }, error: function(data) { dialog.find('#password').val(''); dialog .find('#msg-block') .append('
<__trans phrase="Invalid login." escape="js">
'); } }); return false; }); }); jQuery.fn.mtDialog.open('?__mode=dashboard'); } function handleMessages( data ) { jQuery('#msg-block').empty(); if ( data.error ) { jQuery('#msg-block').append( '

' + data.error + '

' + '<__trans phrase="Close" escape="js">' + '
'); return false; } if ( !data.result ) return false; var messages = data.result.messages; if ( !data.result.messages ) return true; for ( var i=0; i < messages.length; i++ ) { var msg = messages[i]; var text = msg.msg; var cls = msg.cls; jQuery('#msg-block').append( '

' + text + '

' + '<__trans phrase="Close" escape="js">' + '
'); } return true; } function fixInteractions( options ) { var defaults = { sortable: true, closeInlineForms: true }; var opts = jQuery.extend(defaults, options); if ( opts.closeInlineForms ) { jQuery('div.edit-form button.cancel').click(); jQuery('div.add-form button.cancel').click(); } if ( opts.sortable ) { jQuery('.sort-tab').show(); } else { jQuery('.sort-tab').hide(); } } jQuery('div#area-action input[name=category_label]').focus( function() { fixInteractions(); }); // id and parent should be numbers function createItem(id, parent, label, basename, number) { var line = ''; line += ''+label+''; if ( basename ) line += ''+basename+''; line += ' '; line += ' '+number+''; var $item = jQuery('
').append(line); return $item; } function initItem($item) { var id = $item.attr('id'); var catid = id.slice(4); $item.attr('class').match(/\bpcat-(\w+)\b/); var parent = RegExp.$1; var nest = countNested(parent, []); $item.css('margin-left', nest.length*indent) .addClass(jQuery.map(nest, function (a){ return 'pcat-'+a; }).join(' ')) .addClass('lv-'+nest.length) .addClass('sortable-item'); $item.find('.item-ctrl, .edit-form').remove(); $item.append(''); jQuery('<__trans phrase="Rename" escape="js">') .appendTo($item.find('.item-ctrl')) .bind('click', function() { fixInteractions({ sortable: false }); var $element = jQuery(this).parent('.item-ctrl').parent('div'); var $label = $element.find('.item-label a').length ? $element.find('.item-label a') : $element.find('.item-label'); var $basename = $element.find('.item-basename-text'); var $children = $element.children().hide(); var $form = jQuery('
') .append(jQuery('_label" class="text short label" placeholder="<__trans phrase="Label" escape="js">" />')); $form.find('.label').val($label.text()); $form.append(jQuery('_basename" class="text short basename" placeholder="<__trans phrase="Basename" escape="js">" />')); $form.find('.basename').val($basename.text()); jQuery.mtValidateRules['.label'] = function ($e) { if ( !$e.val().length ) return this.raise('<__trans phrase="Label is required." escape="js">'); return hasDupe(parent, catid, $e.val()) ? this.raise('<__trans phrase="Duplicated label on this level." escape="js">') : true; }; jQuery.mtValidateRules['.label'] = function ($e) { if ( !$e.val().length ) return this.raise('<__trans phrase="Label is required." escape="js">'); return true; }; jQuery.mtValidateRules['.basename'] = function ($e) { if ( !$e.val().length ) return this.raise('<__trans phrase="Basename is required." escape="js">'); if ( $e.val().match(/[^\w\-]/) ) return this.raise('<__trans phrase="Invalid Basename." escape="js">'); return hasDupe(parent, catid, null, $e.val()) ? this.raise('<__trans phrase="Duplicated basename on this level." escape="js">') : true; }; jQuery('') .bind('click', function() { if ( !$element.find('input.label, input.basename').mtValidate() ) return false; fixInteractions({ closeInlineForms: false }); $basename.text( $element.find('input.basename').val() ); $label.text( $element.find('input.label').val() ); $children.show(); initItem($item); setItemList(); setDirty(true); }) .appendTo($form); jQuery('') .bind('click', function() { fixInteractions({ closeInlineForms: false }); $children.show(); initItem($item); }) .appendTo($form); $form.appendTo($element); $form.find('.label, .basename').bind('keypress', function (e) { if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) { $form.find('button.rename').click(); return false; } }); $form.find('.label').focus(); return false; }); jQuery('<__trans phrase="Add child [_1]" params="" escape="js">') .appendTo($item.find('.item-ctrl')) .bind('click', function() { fixInteractions({ sortable: false }); var $element = jQuery(this).parent('.item-ctrl').parent('div'); var parent = $element.attr('id').slice(4); var $form = jQuery('
_label" class="text short" placeholder="<__trans phrase="[_1] label" params="" escape="js">" />\n
'); $form.css('margin-left', (nest.length+1)*indent).insertAfter($element).find('input[name=_label]').focus(); jQuery('') .bind('click', function() { var label = jQuery(this).parent('.add-form').find('input').val(); // sort of hack to do HTML escape. label = jQuery('
').text(label).html(); if ( addItem(parent, label) ) { jQuery(this).parent('.add-form').remove(); fixInteractions({ closeInlineForms: false }); } }) .appendTo($form); jQuery('') .bind('click', function() { fixInteractions({ closeInlineForms: false }); jQuery('#msg-block').empty(); jQuery(this).parent('.add-form').remove(); }) .appendTo($form); jQuery('.button').button(); }); jQuery('<__trans phrase="Remove [_1]" params="" escape="js">') .appendTo($item.find('.item-ctrl')) .bind('click', function() { fixInteractions(); var id = jQuery(this).parents('.sortable-item').attr('id').slice(4); removeItems(id); }); setHoverAction($item); } // parent and id should be numbers function hasDupe( parent, id, label, basename ) { var $parent = jQuery('#cat-' + parent); $parent.attr('class').match(/lv-(\w+)/); var parent_level = parseInt(RegExp.$1); if ( isNaN(parent_level) ) parent_level = -1; var level = parent_level + 1; var dupe = false; jQuery('.pcat-' + parent + '.lv-' + level).each( function () { if ( id && ( ('cat-'+id) == jQuery(this).attr('id') ) ) return true; var sibling_label = jQuery(this).find('.item-label').text(); if ( ( label && sibling_label == label ) ) { dupe = true; return false; } var sibling_basename = jQuery(this).find('.item-basename-text').text(); if ( ( basename && sibling_basename == basename ) ) { dupe = true; return false; } }); return dupe; } function makeBasename( parent, id, label ) { var limit = ; var basename = dirify( label ).substr( 0, limit ); if ( !basename.length ) basename = ''; var $parent = jQuery('#cat-' + parent); $parent.attr('class').match(/lv-(\w+)/); var parent_level = parseInt(RegExp.$1); if ( isNaN(parent_level) ) parent_level = -1; var level = parent_level + 1; var max = -1; var re = new RegExp( '^' + basename + '(\\-([1-9][0-9]*))?$' ); jQuery('.pcat-' + parent + '.lv-' + level).each( function () { if ( id && id == jQuery(this).attr('id') ) return true; var sibling_basename = jQuery(this).find('.item-basename-text').text(); if ( sibling_basename.match(re) ) { var num = parseInt(RegExp.$2) || 0; if ( max < num ) max = num; } return true; }); max++; return max > 0 ? basename + '-' + max : basename; } // parent should be a number function addItem(parent, label) { jQuery('#msg-block .additem-error').remove(); if ( hasDupe( parent, 0, label) ) { jQuery('#msg-block').append('
'+trans("[_1] '[_2]' already exists.", '', label)+'
'); return false; } if ( !label.length ) { jQuery('#msg-block').append('
'+trans("Label is required.")+'
'); return false; } var id = 'x'+dummy; var basename = makeBasename(parent, id, label); var $item = createItem(id, parent, label, basename, ''); initItem($item); $item.insertAfter(jQuery('#cat-'+parent)); var nest = countNested(parent, []); var nestLevel = nest.length; jQuery('#opt-'+parent).after(''); dummy++; setDirty(true); fixZeroStateMessage(); return true; } jQuery('input[name=_label]').live('keypress', function (e) { if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) { jQuery(this).siblings('button.add').click(); return false; } }); // id should be numeric / x1 function removeItems(id) { var singlar = ''; var plural = ''; var $items = jQuery('.pcat-'+id); var count = $items.length + 1; var label = jQuery('#cat-'+id).find('.item-label').text(); var message = (count == 1) ? trans('Are you sure you want to remove [_1] [_2]?', singlar, label) : trans('Are you sure you want to remove [_1] [_2] with [_3] sub [_4]?', singlar, label, count - 1, (count > 2 ? plural : singlar)); if (!confirm(message)) { return; } $items.remove(); jQuery('#cat-'+id).next('.add-form').remove().end().remove(); jQuery('.sort-tab').show(); setItemList(); setDirty(true); fixZeroStateMessage(); } function setItemList() { jQuery('#itemlist option').not(':first').remove(); jQuery('.sortable-item:visible').each(function() { var $item = jQuery(this); var id = $item.attr('id'); var catid = id.slice(4); var label = $item.find('.item-label').html(); var nest = countNested(catid, []); var nestLevel = nest.length - 1; jQuery('#itemlist').append(''); }); } // id should be a number, nest a list function countNested(id, nest) { if (id == 0) { return nest; } jQuery('#cat-'+id).attr('class').match(/\bpcat-(\w+)\b/); var parent = RegExp.$1; nest.push(parent); return countNested(parent, nest); } function nestedLabel( level, label ) { ret = ''; for( i = 0; i < level; i++ ) { ret = '- '+ret; } return ret + label; } function initMoving() { var place; var original_class; jQuery('.sortable').sortable({ distance: 3, opacity: 0.8, placeholder: 'ui-state-highlight', handle: 'span.sort-tab', start: function(event, ui) { var $item = jQuery(ui.item); original_class = $item.attr('class'); var id = $item.attr('id').slice(4); var count = jQuery('.pcat-'+id).hide().length; if (count) { var label = (count == 1) ? '' : ''; jQuery(' + '+count+' '+label+' ').insertAfter($item.find('.item-basename')); } $item.find('.item-ctrl').hide(); }, stop: function(event, ui) { var $item = jQuery(ui.item); var id = $item.attr('id'); var catid = id.slice(4); if (!place) place = 0; if (catid == place) { jQuery('.pcat-'+catid).show(); return; } function _stop() { $item.find('.with').remove(); $item.find('.item-basename, .plus, .delete').show(); $item.attr('class', ('pcat-'+place)); initItem($item); var $last = $item; jQuery('.pcat-'+catid).each(function() { var $this = jQuery(this).clone(); jQuery(this).remove(); $this.attr('class').match(/\bpcat-(\w+)\b/); var parent = RegExp.$1; $this.attr('class', ('pcat-'+parent)); initItem($this); $this.insertAfter($last).show(); $last = $this; }); setHoverAction(jQuery('.pcat-'+catid)); setItemList(); setDirty(true); } if ( hasDupe( place, catid, $item.find('.item-label').text() ) || hasDupe( place, catid, null, $item.find('.item-basename-text').text() ) hasDupe(place, catid, null, $item.find('.item-basename-text').text() ) ) { $item.attr('class', ('pcat-'+place)); initItem($item); jQuery.mtValidateRules['#new-label'] = function ($e) { return hasDupe(place, catid, $e.val()) ? this.raise('<__trans phrase="Duplicated label on this level." escape="js">') : true; }; jQuery.mtValidateRules['#new-basename'] = function ($e) { return hasDupe(place, catid, null, $e.val()) ? this.raise('<__trans phrase="Duplicated basename on this level." escape="js">') : true; }; jQuery('#new-label').val($item.find('.item-label').text()) jQuery('#new-basename').val($item.find('.item-basename-text').text()) jQuery('#change-and-move') .unbind('click') .bind( 'click', function(){ if ( jQuery('#new-label').mtValidate('simple') && jQuery('#new-basename').mtValidate('simple') ) { var $label = $item.find('.item-label a').length ? $item.find('.item-label a') : $item.find('.item-label'); $label.text( jQuery('#new-label').val() ); var $basename = $item.find('.item-basename-text'); $basename.text( jQuery('#new-basename').val() ); _stop(); jQuery('#dialog-change-basename').dialog('close'); } if ( jQuery('#new-basename').mtValidate('simple') ) { var $basename = $item.find('.item-basename-text'); $basename.text( jQuery('#new-basename').val() ); _stop(); jQuery('#dialog-change-basename').dialog('close'); } return false; }); jQuery('#cancel-move') .unbind('click') .bind('click', function () { jQuery('.sortable').sortable('cancel'); $item.attr('class', original_class); jQuery('.pcat-'+catid).show(); $item.find('.with').remove(); $item.find('.plus, .delete').show(); initItem($item); setHoverAction(jQuery('.pcat-'+catid)); setItemList(); jQuery('#dialog-change-basename').dialog('close'); }); jQuery('#dialog-change-basename').dialog({ title: trans('Alert'), dialogClass: 'alert', autoOpen: true, width: 450, modal: true, resizable: false, draggable: false, closeOnEscape: false }); jQuery('#new-label, #new-basename').mtValidate('simple'); jQuery('#new-basename').mtValidate('simple'); } else { _stop(); } }, sort: function(event, ui) { var $item = jQuery(ui.item); $item.attr('class').match(/\bpcat-(\w+)\b/); var parent = RegExp.$1; $item.attr('class').match(/lv-(\w+)/); var level = parseInt(RegExp.$1); var $place = jQuery(ui.placeholder); var $prev = $place.prevAll().not($item).not(':hidden').filter(':first'); var prev_id = 0; var prev_parent = 0; var prev_level = 0; if ($prev.length) { var prev_id = $prev.attr('id').slice(4); $prev.attr('class').match(/\bpcat-(\w+)\b/); prev_parent = RegExp.$1; $prev.attr('class').match(/lv-(\w+)/); prev_level = parseInt(RegExp.$1); } var nest = countNested(prev_parent, []); nest.pop(); nest.unshift(prev_parent); var $next = $place.nextAll().not($item).not(':hidden').filter(':first'); var next_parent = 0; var next_level = 0; if ($next.length) { $next.attr('class').match(/\bpcat-(\w+)\b/); next_parent = RegExp.$1; $next.attr('class').match(/lv-(\w+)/); next_level = parseInt(RegExp.$1); } var left = ui.offset.left - root_pos.left; var idx = parseInt(Math.abs(left)/indent); var d = prev_level < level ? 0 : prev_level - level + 1; var pos = 0; if (prev_level < next_level) { place = prev_id; pos = prev_level + 1; } else if (prev_level == next_level) { if (left > 0) { place = prev_id; pos = prev_level + 1; } else { place = prev_parent; pos = prev_level; } if (prev_id == 0) { place = prev_parent; pos = prev_level; } } else { if (left > 0) { if (idx < d) { place = nest[d - idx - 1]; pos = nest.length - (d - idx -1); } else { place = prev_id; pos = nest.length + 1; } } else if (left < 0) { if (idx + d < nest.length) { place = nest[idx + d]; pos = nest.length - (idx + d); } else { place = next_parent; pos = next_level; } } else { place = parent; pos = level; } } jQuery('
').css('width', pos*indent).appendTo($place.empty()); } }); } function setHoverAction($elements) { $elements.hover(function() { var parent = jQuery(this).addClass('highlight on').attr('id').slice(4); jQuery('.pcat-'+parent).addClass('highlight'); }, function() { var parent = jQuery(this).removeClass('highlight on').attr('id').slice(4); jQuery('.pcat-'+parent).removeClass('highlight'); }); } function renderItems(data) { jQuery('#root').empty(); jQuery('#itemlist option').not(':first').remove(); jQuery('
').hide().appendTo('#root'); var objs = data.result.objects; var count = objs.length; for (var i = 0; i < count; i++) { var id = parseInt(objs[i][0]); var parent = parseInt(objs[i][1]); var label = objs[i][2]; var basename = objs[i][3]; var number = objs[i][4] var $item = createItem(id, parent, label, basename, number); initItem($item); $item.appendTo('#root'); var nest = countNested(parent, []); var nestLevel = nest.length; jQuery('#itemlist').append(''); } fixZeroStateMessage(); checksum = data.result.checksum; setHoverAction(jQuery('.sortable-item')); jQuery('#area-action').children().removeClass('disabled').removeAttr('disabled'); } function fixZeroStateMessage () { if ( jQuery('#root div.sortable-item').length <= 1 ) { var message = trans('No [_1] could be found.', ''); jQuery('

'+message+'

').appendTo('#root'); } else jQuery('#zero-state-message').remove(); } function renderNestedList() { var params = { __mode: 'filtered_list', datasource: '', blog_id: }; jQuery.ajax({ type: 'POST', contentType: 'application/x-www-form-urlencoded; charset=utf-8', url: '', dataType: 'json', data: params, success: function(data) { if ( !handleMessages(data) ) return; if (data.result.debug) { jQuery('#listing-debug-block').text(data.result.debug); } renderItems(data); }, complete: function() { jQuery(window).trigger('listReady'); initMoving(); }, error: function(xhr, status) { if ( xhr.status == 401 ) { loginAgain(function(){ renderNestedList(); }); } else if ( xhr.status == 0 ) { // Maybe this is user abort. do nothing. } else { alert('Ajax error: ' + xhr.status + ': ' + status); } } }); } jQuery('.add').click(function() { var parent = jQuery(this).parent('#area-action').find('select').val(); var label = jQuery(this).parent('#area-action').find('input').val(); // sort of hack to do HTML escape. label = jQuery('
').text(label).html(); if ( addItem(parent, label) ) { fixInteractions(); jQuery(this).parent('#area-action').find('input').val(''); } return false; }); jQuery('.save').click( bulkUpdateCategories ); function bulkUpdateCategories() { jQuery('#area-action').children().addClass('disabled').attr('disabled', 'disabled'); var items = []; jQuery('.sortable-item:visible').each(function() { var $item = jQuery(this); var myid = $item.attr('id').slice(4); $item.attr('class').match(/\bpcat-(\w+)\b/); var parentid = RegExp.$1; items.push({id: myid, parent: parentid, label: $item.find('.item-label').text(), basename: $item.find('.item-basename-text').text() }); }); jQuery.ajax({ type: 'POST', contentType: 'application/x-www-form-urlencoded; charset=utf-8', url: '', dataType: 'json', data: { __mode: 'bulk_update_', datasource: '', blog_id: , checksum: checksum, objects: jQuery.toJSON(items), magic_token: jQuery('input[name="magic_token"]').val() }, success: function(data) { if ( !handleMessages(data) ) return; renderItems(data); setDirty(false); }, complete: function() { initMoving(); }, error: function(xhr, status) { if ( xhr.status == 401 ) { loginAgain(function(){ bulkUpdateCategories(); }); } else alert('Ajax error: ' + status); } }); return false; } jQuery(window).bind('beforeunload', function() { if (isdirty) { return trans('You have unsaved changes to this page that will be lost.'); } }); jQuery(window).bind('listReady', function() { jQuery('#area-action').children().removeClass('disabled').removeAttr('disabled'); }); renderNestedList();