admin.js
421 lines
| 1 | /** |
| 2 | * plugin admin area javascript |
| 3 | */ |
| 4 | (function($){$(function () { |
| 5 | if ( ! $('body.pmxi_plugin').length) return; // do not execute any code if we are not on plugin page |
| 6 | |
| 7 | // fix layout position |
| 8 | setTimeout(function () { |
| 9 | $('table.layout').length && $('table.layout td.left h2:first-child').css('margin-top', $('.wrap').offset().top - $('table.layout').offset().top); |
| 10 | }, 10); |
| 11 | |
| 12 | |
| 13 | // help icons |
| 14 | $('a.help').tipsy({ |
| 15 | gravity: function() { |
| 16 | var ver = 'n'; |
| 17 | if ($(document).scrollTop() < $(this).offset().top - $('.tipsy').height() - 2) { |
| 18 | ver = 's'; |
| 19 | } |
| 20 | var hor = ''; |
| 21 | if ($(this).offset().left + $('.tipsy').width() < $(window).width() + $(document).scrollLeft()) { |
| 22 | hor = 'w'; |
| 23 | } else if ($(this).offset().left - $('.tipsy').width() > $(document).scrollLeft()) { |
| 24 | hor = 'e'; |
| 25 | } |
| 26 | return ver + hor; |
| 27 | }, |
| 28 | live: true, |
| 29 | html: true, |
| 30 | opacity: 1 |
| 31 | }).live('click', function () { |
| 32 | return false; |
| 33 | }).each(function () { // fix tipsy title for IE |
| 34 | $(this).attr('original-title', $(this).attr('title')); |
| 35 | $(this).removeAttr('title'); |
| 36 | }); |
| 37 | |
| 38 | // swither show/hide logic |
| 39 | $('input.switcher').change(function (e) { |
| 40 | if ($(this).is(':radio:checked')) { |
| 41 | $(this).parents('form').find('input.switcher:radio[name="' + $(this).attr('name') + '"]').not(this).change(); |
| 42 | } |
| 43 | var $targets = $('.switcher-target-' + $(this).attr('id')); |
| 44 | var is_show = $(this).is(':checked'); if ($(this).is('.switcher-reversed')) is_show = ! is_show; |
| 45 | if (is_show) { |
| 46 | $targets.fadeIn(); |
| 47 | } else { |
| 48 | $targets.hide().find('.clear-on-switch').add($targets.filter('.clear-on-switch')).val(''); |
| 49 | } |
| 50 | }).change(); |
| 51 | |
| 52 | // autoselect input content on click |
| 53 | $('input.selectable').live('click', function () { |
| 54 | $(this).select(); |
| 55 | }); |
| 56 | |
| 57 | // input tags with title |
| 58 | $('input[title]').each(function () { |
| 59 | var $this = $(this); |
| 60 | $this.bind('focus', function () { |
| 61 | if ('' == $(this).val() || $(this).val() == $(this).attr('title')) { |
| 62 | $(this).removeClass('note').val(''); |
| 63 | } |
| 64 | }).bind('blur', function () { |
| 65 | if ('' == $(this).val() || $(this).val() == $(this).attr('title')) { |
| 66 | $(this).addClass('note').val($(this).attr('title')); |
| 67 | } |
| 68 | }).blur(); |
| 69 | $this.parents('form').bind('submit', function () { |
| 70 | if ($this.val() == $this.attr('title')) { |
| 71 | $this.val(''); |
| 72 | } |
| 73 | }); |
| 74 | }); |
| 75 | |
| 76 | // datepicker |
| 77 | $('input.datepicker').datepicker({ |
| 78 | dateFormat: 'yy-mm-dd', |
| 79 | showOn: 'button', |
| 80 | buttonText: '', |
| 81 | constrainInput: false, |
| 82 | showAnim: 'fadeIn', |
| 83 | showOptions: 'fast' |
| 84 | }).bind('change', function () { |
| 85 | var selectedDate = $(this).val(); |
| 86 | var instance = $(this).data('datepicker'); |
| 87 | var date = null; |
| 88 | if ('' != selectedDate) { |
| 89 | try { |
| 90 | date = $.datepicker.parseDate(instance.settings.dateFormat || $.datepicker._defaults.dateFormat, selectedDate, instance.settings); |
| 91 | } catch (e) { |
| 92 | date = null; |
| 93 | } |
| 94 | } |
| 95 | if ($(this).hasClass('range-from')) { |
| 96 | $(this).parent().find('.datepicker.range-to').datepicker("option", "minDate", date); |
| 97 | } |
| 98 | if ($(this).hasClass('range-to')) { |
| 99 | $(this).parent().find('.datepicker.range-from').datepicker("option", "maxDate", date); |
| 100 | } |
| 101 | }).change(); |
| 102 | $('.ui-datepicker').hide(); // fix: make sure datepicker doesn't break wordpress layout upon initialization |
| 103 | |
| 104 | // no-enter-submit forms |
| 105 | $('form.no-enter-submit').find('input,select,textarea').not('*[type="submit"]').keydown(function (e) { |
| 106 | if (13 == e.keyCode) e.preventDefault(); |
| 107 | }); |
| 108 | |
| 109 | // choose file form: option selection dynamic |
| 110 | // options form: highlight options of selected post type |
| 111 | $('form.choose-file input[name="type"]').click(function() { |
| 112 | var $container = $(this).parents('.file-type-container'); |
| 113 | $('.file-type-container').not($container).removeClass('selected').find('.file-type-options').hide(); |
| 114 | $container.addClass('selected').find('.file-type-options').show(); |
| 115 | }).filter(':checked').click(); |
| 116 | |
| 117 | // template form: auto submit when `load template` list value is picked |
| 118 | $('form.template').find('select[name="load_template"]').change(function () { |
| 119 | $(this).parents('form').submit(); |
| 120 | }); |
| 121 | // template form: preview button |
| 122 | $('form.template').each(function () { |
| 123 | var $form = $(this); |
| 124 | var $modal = $('<div></div>').dialog({ |
| 125 | autoOpen: false, |
| 126 | modal: true, |
| 127 | title: 'Preview Post', |
| 128 | width: 760, |
| 129 | maxHeight: 600, |
| 130 | open: function(event, ui) { |
| 131 | $(this).dialog('option', 'height', 'auto').css({'max-height': $(this).dialog('option', 'maxHeight') - $(this).prev().height() - 24, 'overflow-y': 'auto'}); |
| 132 | } |
| 133 | }); |
| 134 | $form.find('.preview').click(function () { |
| 135 | $modal.addClass('loading').empty().dialog('open').dialog('option', 'position', 'center'); |
| 136 | tinyMCE.triggerSave(false, false); |
| 137 | $.post('admin.php?page=pmxi-admin-import&action=preview', $form.serialize(), function (response) { |
| 138 | $modal.removeClass('loading').html(response).dialog('option', 'position', 'center'); |
| 139 | }); |
| 140 | return false; |
| 141 | }); |
| 142 | }); |
| 143 | |
| 144 | // options form: highlight options of selected post type |
| 145 | $('form.options input[name="type"]').click(function() { |
| 146 | var $container = $(this).parents('.post-type-container'); |
| 147 | $('.post-type-container').not($container).removeClass('selected').find('.post-type-options').hide(); |
| 148 | $container.addClass('selected').find('.post-type-options').show(); |
| 149 | }).filter(':checked').click(); |
| 150 | // options form: add / remove custom params |
| 151 | $('.form-table a.action[href="#add"]').live('click', function () { |
| 152 | var $template = $(this).parents('table').first().find('tr.template'); |
| 153 | $template.clone(true).insertBefore($template).css('display', 'none').removeClass('template').fadeIn(); |
| 154 | return false; |
| 155 | }); |
| 156 | // options form: auto submit when `load options` checkbox is checked |
| 157 | $('form.options').find('input[name="load_options"]').click(function () { |
| 158 | if ($(this).is(':checked')) $(this).parents('form').submit(); |
| 159 | }); |
| 160 | // options form: auto submit when `reset options` checkbox is checked |
| 161 | $('form.options').find('input[name="reset_options"]').click(function () { |
| 162 | if ($(this).is(':checked')) $(this).parents('form').submit(); |
| 163 | }); |
| 164 | $('.form-table .action.remove a').live('click', function () { |
| 165 | $(this).parents('tr').first().remove(); |
| 166 | return false; |
| 167 | }); |
| 168 | |
| 169 | var dblclickbuf = { |
| 170 | 'selected':false, |
| 171 | 'value':'' |
| 172 | }; |
| 173 | |
| 174 | // [xml representation dynamic] |
| 175 | $.fn.xml = function (opt) { |
| 176 | if ( ! this.length) return this; |
| 177 | |
| 178 | var $self = this; |
| 179 | var opt = opt || {}; |
| 180 | var action = {}; |
| 181 | if ('object' == typeof opt) { |
| 182 | action = opt; |
| 183 | } else { |
| 184 | action[opt] = true; |
| 185 | } |
| 186 | action = $.extend({init: ! this.data('initialized')}, action); |
| 187 | |
| 188 | if (action.init) { |
| 189 | this.data('initialized', true); |
| 190 | // add expander |
| 191 | this.find('.xml-expander').click(function () { |
| 192 | var method; |
| 193 | if ('-' == $(this).text()) { |
| 194 | $(this).text('+'); |
| 195 | method = 'addClass'; |
| 196 | } else { |
| 197 | $(this).text('-'); |
| 198 | method = 'removeClass'; |
| 199 | } |
| 200 | // for nested representation based on div |
| 201 | $(this).parent().find('> .xml-content')[method]('collapsed'); |
| 202 | // for nested representation based on tr |
| 203 | var $tr = $(this).parent().parent().filter('tr.xml-element').next()[method]('collapsed'); |
| 204 | }); |
| 205 | } |
| 206 | if (action.dragable) { // drag & drop |
| 207 | var _w; var _dbl = 0; |
| 208 | var $drag = $('__drag'); $drag.length || ($drag = $('<input type="text" id="__drag" readonly="readonly" />')); |
| 209 | |
| 210 | $drag.css({ |
| 211 | position: 'absolute', |
| 212 | background: 'transparent', |
| 213 | top: -50, |
| 214 | left: 0, |
| 215 | margin: 0, |
| 216 | border: 'none', |
| 217 | lineHeight: 1, |
| 218 | opacity: 0, |
| 219 | cursor: 'pointer', |
| 220 | borderRadius: 0 |
| 221 | }).appendTo(document.body).mousedown(function (e) { |
| 222 | if (_dbl) return; |
| 223 | var _x = e.pageX - $drag.offset().left; |
| 224 | var _y = e.pageY - $drag.offset().top; |
| 225 | if (_x < 4 || _y < 4 || $drag.width() - _x < 0 || $drag.height() - _y < 0) { |
| 226 | return; |
| 227 | } |
| 228 | $drag.width($(document.body).width() - $drag.offset().left - 5).css('opacity', 1); |
| 229 | $drag.select(); |
| 230 | _dbl = true; setTimeout(function () {_dbl = false;}, 400); |
| 231 | }).mouseup(function () { |
| 232 | $drag.css('opacity', 0).css('width', _w); |
| 233 | $drag.blur(); |
| 234 | }).dblclick(function(){ |
| 235 | if (dblclickbuf.selected) |
| 236 | { |
| 237 | $('.xml-element[title*="/'+dblclickbuf.value.replace('{','').replace('}','')+'"]').removeClass('selected'); |
| 238 | |
| 239 | if ($(this).val() == dblclickbuf.value) |
| 240 | { |
| 241 | dblclickbuf.value = ''; |
| 242 | dblclickbuf.selected = false; |
| 243 | } |
| 244 | else |
| 245 | { |
| 246 | dblclickbuf.selected = true; |
| 247 | dblclickbuf.value = $(this).val(); |
| 248 | $('.xml-element[title*="/'+$(this).val().replace('{','').replace('}','')+'"]').addClass('selected'); |
| 249 | } |
| 250 | } |
| 251 | else |
| 252 | { |
| 253 | dblclickbuf.selected = true; |
| 254 | dblclickbuf.value = $(this).val(); |
| 255 | $('.xml-element[title*="/'+$(this).val().replace('{','').replace('}','')+'"]').addClass('selected'); |
| 256 | } |
| 257 | }); |
| 258 | |
| 259 | var insertxpath = function(){ |
| 260 | if (dblclickbuf.selected) |
| 261 | { |
| 262 | $(this).val($(this).val() + dblclickbuf.value); |
| 263 | $('.xml-element[title*="/'+dblclickbuf.value.replace('{','').replace('}','')+'"]').removeClass('selected'); |
| 264 | dblclickbuf.value = ''; |
| 265 | dblclickbuf.selected = false; |
| 266 | } |
| 267 | } |
| 268 | $('#title, #content, .widefat, input[name^=custom_name], textarea[name^=custom_value], input[name^=featured_image], input[name^=unique_key]').bind('focus', insertxpath ); |
| 269 | |
| 270 | $(document).mousemove(function () { |
| 271 | if (parseInt($drag.css('opacity')) != 0) { |
| 272 | setTimeout(function () { |
| 273 | $drag.css('opacity', 0); |
| 274 | }, 50); |
| 275 | setTimeout(function () { |
| 276 | $drag.css('width', _w); |
| 277 | }, 500); |
| 278 | } |
| 279 | }); |
| 280 | |
| 281 | if ($('#content').length) tinymce.dom.Event.add('wp-content-editor-container', 'click', function(e) { |
| 282 | if (dblclickbuf.selected) |
| 283 | { |
| 284 | tinyMCE.activeEditor.selection.setContent(dblclickbuf.value); |
| 285 | $('.xml-element[title*="'+dblclickbuf.value.replace('{','').replace('}','')+'"]').removeClass('selected'); |
| 286 | dblclickbuf.value = ''; |
| 287 | dblclickbuf.selected = false; |
| 288 | } |
| 289 | }); |
| 290 | |
| 291 | this.find('.xml-tag.opening > .xml-tag-name, .xml-attr-name').each(function () { |
| 292 | var $this = $(this); |
| 293 | var xpath = '{' + (($this.is('.xml-attr-name') ? $this.parent() : $this.parent().parent()).attr('title').replace(/^\/[^\/]+\/?/, '') || '.') + '}'; |
| 294 | |
| 295 | $this.mouseover(function (e) { |
| 296 | $drag.val(xpath).offset({left: $this.offset().left - 2, top: $this.offset().top - 2}).width(_w = $this.width() + 4).height($this.height() + 4); |
| 297 | }); |
| 298 | }).eq(0).mouseover(); |
| 299 | } |
| 300 | return this; |
| 301 | }; |
| 302 | |
| 303 | // selection logic |
| 304 | $('form.choose-elements').each(function () { |
| 305 | var $form = $(this); |
| 306 | $form.find('.xml').xml(); |
| 307 | var $input = $form.find('input[name="xpath"]'); |
| 308 | $form.find('.xml-tag.opening').bind('mousedown', function () {return false;}).dblclick(function () { |
| 309 | if ($form.hasClass('loading')) return; // do nothing if selecting operation is currently under way |
| 310 | $input.val($(this).parents('.xml-element').first().attr('title').replace(/\[\d+\]$/, '')).change(); |
| 311 | }); |
| 312 | var xpathChanged = function () { |
| 313 | if ($input.val() == $input.data('checkedValue')) return; |
| 314 | $form.addClass('loading'); |
| 315 | $form.find('.xml-element.selected').removeClass('selected'); // clear current selection |
| 316 | // request server to return elements which correspond to xpath entered |
| 317 | $input.attr('readonly', true).unbind('change', xpathChanged).data('checkedValue', $input.val()); |
| 318 | $('.ajax-console').load('admin.php?page=pmxi-admin-import&action=evaluate', {xpath: $input.val()}, function () { |
| 319 | $input.attr('readonly', false).change(xpathChanged); |
| 320 | $form.removeClass('loading'); |
| 321 | }); |
| 322 | }; |
| 323 | $input.change(xpathChanged).change(); |
| 324 | $input.keyup(function (e) { |
| 325 | if (13 == e.keyCode) $(this).change(); |
| 326 | }); |
| 327 | }); |
| 328 | |
| 329 | // tag preview |
| 330 | $.fn.tag = function () { |
| 331 | this.each(function () { |
| 332 | var $tag = $(this); |
| 333 | $tag.xml('dragable'); |
| 334 | var tagno = parseInt($tag.find('input[name="tagno"]').val()); |
| 335 | $tag.find('.navigation a').click(function () { |
| 336 | tagno += '#prev' == $(this).attr('href') ? -1 : 1; |
| 337 | $tag.addClass('loading').css('opacity', 0.7); |
| 338 | $.post('admin.php?page=pmxi-admin-import&action=tag', {tagno: tagno}, function (data) { |
| 339 | var $indicator = $('<span />').insertBefore($tag); |
| 340 | $tag.replaceWith(data); |
| 341 | $indicator.next().tag().prevObject.remove(); |
| 342 | }, 'html'); |
| 343 | return false; |
| 344 | }); |
| 345 | }); |
| 346 | return this; |
| 347 | }; |
| 348 | $('.tag').tag(); |
| 349 | // [/xml representation dynamic] |
| 350 | |
| 351 | $('input.autocomplete').each(function () { |
| 352 | $(this).autocomplete({ |
| 353 | source: eval($(this).attr('id')), |
| 354 | minLength: 0 |
| 355 | }).click(function () { |
| 356 | $(this).autocomplete('search', ''); |
| 357 | }); |
| 358 | }); |
| 359 | |
| 360 | function process(first_chank, update_previous){ |
| 361 | $('input[name=is_first_chank],input[name=is_update_previous]').remove(); |
| 362 | $("form").append('<input type="hidden" name="is_first_chank" value="'+((first_chank) ? 1 : 0)+'"/>'); |
| 363 | $("form").append('<input type="hidden" name="is_update_previous" value="'+update_previous+'"/>'); |
| 364 | |
| 365 | $.ajax({ |
| 366 | type: 'POST', |
| 367 | url: 'admin.php?page=pmxi-admin-import&action=options', |
| 368 | data: $("form").serialize(), |
| 369 | success: function(data) { |
| 370 | switch (data.status) |
| 371 | { |
| 372 | case 'process': |
| 373 | $('.wrap').append(data.log); |
| 374 | $(window).scrollTop($(document).height()); |
| 375 | process(false, data.update_previous); |
| 376 | break; |
| 377 | case 'stop': |
| 378 | $('form.options').remove(); |
| 379 | var import_stats = ''; |
| 380 | import_stats = '<p><b> Import started at</b> ' + data.start_time + '</p>'; |
| 381 | import_stats += '<p><b> Import ended at</b> ' + data.end_time + '</p>'; |
| 382 | import_stats += '<p><b> Import time</b> ' + data.import_time + '</p>'; |
| 383 | $('.wrap').append(data.log + import_stats); |
| 384 | break; |
| 385 | } |
| 386 | }, |
| 387 | error: function(request, status, error){ |
| 388 | $('form.options').hide(); |
| 389 | var error = "<script type='text/javascript'>(function($){$('#status').html('Error');window.onbeforeunload = false;})(jQuery);</script>"; |
| 390 | if (request.responseText.indexOf('options') === -1) $('.wrap').append(error + request.responseText); else $('form.options').append(error).submit(); |
| 391 | }, |
| 392 | dataType: "json" |
| 393 | }); |
| 394 | } |
| 395 | |
| 396 | $('.ajax-import').click(function(e){ |
| 397 | e.preventDefault(); |
| 398 | $('form').hide(); |
| 399 | $('#process').show(); |
| 400 | $('#status').each(function () { |
| 401 | var $this = $(this); |
| 402 | if ($this.html().match(/\.{3}$/)) { |
| 403 | var dots = 0; |
| 404 | var status = $this.html().replace(/\.{3}$/, ''); |
| 405 | var interval ; |
| 406 | interval = setInterval(function () { |
| 407 | if ($this.html().match(new RegExp(status + '\\.{1,3}$', ''))) { |
| 408 | $this.html(status + '...'.substr(0, dots++ % 3 + 1)); |
| 409 | } else { |
| 410 | clearInterval(interval); |
| 411 | } |
| 412 | }, 1000); |
| 413 | } |
| 414 | }); |
| 415 | window.onbeforeunload = function () { |
| 416 | return 'WARNING:\nImport process in under way, leaving the page will interrupt\nthe operation and most likely to cause leftovers in posts.'; |
| 417 | }; |
| 418 | process(true, 0); |
| 419 | }); |
| 420 | |
| 421 | });})(jQuery); |