1function settingstree_show_export(opts){ 2 if (!opts.on_complete || typeof window[opts.on_complete] !== 'function'){ 3 return false; // return failure if the callback is incomplete (popup won't be shown). 4 }; 5 var $ = jQuery, 6 $grayout = $('<div id="settingstree_grayout"></div>').appendTo('body'), 7 $container = $('<div id="settingstree_export_popup_container"></div>').appendTo($grayout), 8 $dialog = $('<div class="settingstree_export_popup_layer"></div>').appendTo($container), 9 $close = $('<div class="settingstree_export_popup_close_button"> x </div>').appendTo($container), 10 $form = $('<form class="settingstree_area" method="get"></form>').appendTo($dialog); 11 $close.on('click', function(e){ $form.trigger('settingstree_close');}); 12 opts._export = true; 13 $form.settingsTree(opts); 14 $form.on('settingstree_export_complete',function(e,values,changes){ 15 $form.trigger('settingstree_close'); // clean up before calling the on_complete. 16 window[opts.on_complete].call(null,values,changes); // call the on_complete callback. 17 }); 18 $form.on('settingstree_close', function(){$grayout.remove();}); // destroying the root with jQuery automatically removes all registered data from the memory. 19 return true; // return success (popup fill be shown). 20}; 21jQuery.fn.settingsTree = function(opts){ 22 if (jQuery(this).length !== 1){ 23 throw 'There must be exactly one settingsTree instance on a page!'; 24 } 25 var $ = jQuery, $root = $(this), opts = $.extend({},opts), pluginname = opts.pluginname, token = opts.token, pending = false, path = ':',_export = opts._export||false, 26 getLang = function (msgid){ 27 var str; 28 if ((str = LANG.plugins.settingstree[msgid]) === undefined){ 29 str = '{msgid:'+msgid+'}'; // Note: if lang keys needs to be html escaped then there is a conceptual problem about msgids... 30 } 31 return str; 32 }, 33 getchanged = function(){ 34 var values = {}; 35 $root.find('.input_area.changed, .protect_area.changed').each(function(){ 36 var $inp = $(this).find('input, textarea, select'), name = $inp.prop('name'), val = $inp.val(), m; 37 if ($inp.is(':checkbox')){ 38 val = $inp.prop('checked') ? 1 : 0; 39 } 40 if (!(m = name.match(/^(config|protect)\[(.*)\]$/))){ // we don't know what area is this... 41 return; 42 } 43 if (!values[m[2]]){ values[m[2]] = {};} 44 values[m[2]][m[1]] = val; 45 }); 46 return values; 47 }, 48 savelevel = function(){ // save: we save all data, and if it's successful, we display the save options by their new values or display invalid data on error. 49 $root.find('.settingstree_error_area').html($("<div class='notify'>"+getLang('saving_changes')+"</div>")); 50 var changes = getchanged(); 51 $.post(DOKU_BASE + 'lib/exe/ajax.php', 52 { call:'plugin_settingstree', operation: 'savelevel', pluginname: pluginname, path: path, sectok: token, data: changes }, 53 function(r){ 54 if (r.token) token = r.token; 55 if (r.html){ $root.html(r.html); } 56 if (r.success){ 57 $root.find('.settingstree_error_area').html(("<div class='success'>"+(r.msg||"success")+"</div>")); 58 // update the hierarchy, if it was changed by the save, and save was successful. 59 var key = $('.settingstree_left_column').data('current'); 60 if (key && changes[key] !== undefined){ 61 $('.settingstree_left_column').data('current',null); 62 show_in_hierarchy(key,path); 63 } 64 } 65 else{ $root.find('.settingstree_error_area').html($("<div class='error'>"+(r.msg||"fail")+"</div>")); } 66 } 67 ); 68 }, 69 simplify = function(conf){ 70 var ret = {}; 71 for (var key in conf){ 72 if (typeof conf[key] === 'object' && typeof conf[key].config !== undefined) 73 ret[key] = conf[key].config; 74 } 75 return ret; 76 }, 77 exportlevel = function(){ // export: we check all data - but not save it, and if it's successful, we are finished. on error we display invalid data an all changes. 78 $root.find('.settingstree_error_area').html($("<div class='notify'>"+getLang('preparing_export')+"</div>")); 79 var changes = getchanged(); 80 $.post(DOKU_BASE + 'lib/exe/ajax.php', 81 { call:'plugin_settingstree', operation: 'exportlevel', pluginname: pluginname, path: path, sectok: token, data: changes, options: opts.options }, 82 function(r){ 83 if (r.token) token = r.token; 84 if (r.html){ $root.html(r.html); } 85 if (r.success){ $root.trigger('settingstree_export_complete',[r.values,simplify(changes)]); } 86 else{ $root.find('.settingstree_error_area').html($("<div class='error'>"+(r.msg||"fail")+"</div>")); } 87 } 88 ); 89 90 }, 91 resetlevel = function(){ 92 $root.find('.input_area.changed, .protect_area.changed').each(function(){ 93 var $inp = $(this).find('input, textarea, select'), val =$inp.val(), def = $(this).data('currentval'); 94 if ($inp.is(':checkbox')){ 95 $inp.prop('checked',def ? true : false); 96 }else{ 97 $inp.val(def); 98 } 99 $(this).removeClass('changed'); 100 }) 101 }, 102 inputchange = function(){ 103 var $inp = $(this), $inpa = $inp.parents('.input_area:first, .protect_area:first'), val = $inp.val(); 104 if ($inp.is(':checkbox')){ 105 val = $inp.prop('checked') ? 1 : 0; 106 } 107 if (val == $inpa.data('currentval')){ 108 $inpa.removeClass('changed'); 109 }else{ 110 $inpa.addClass('changed'); 111 } 112 }, 113 has_pending = function(){ 114 return (pending || $root.has('.input_area.changed, .protect_area.changed').length); 115 }, 116 open_hierarchy_level = function(open_level){ 117 var $hier = $('.settingstree_left_column'); 118 $hier.find('.highlighted_level').removeClass('highlighted_level'); 119 $hier.find('[data-path="'+open_level+'"]').addClass('highlighted_level'); 120 }, 121 selectlevel = function(id){ 122 if (has_pending()){ 123 $root.find('.settingstree_error_area').html($("<div class='error'><h4>"+getLang('pending_change')+"</h4><p>"+getLang('pending_change_explain')+"</p></div>")); 124 return; 125 } 126 $root.html('<div class="settingstree_error_area"><div class="notify">'+getLang('loading_level')+'</div></div>'); 127 $.post(DOKU_BASE + 'lib/exe/ajax.php', 128 { call:'plugin_settingstree', operation: 'loadlevel', pluginname: pluginname, path: id, sectok: token, showtype: _export? 'export' : 'normal', options: opts.options }, 129 function(r){ 130 if (r.token) token = r.token; 131 if (r.error) alert(r.msg); 132 if (r.path){ path = r.path; } 133 if (r.html){ 134 $root.html(r.html); 135 var key = $('.settingstree_left_column').data('current'); 136 if (key){ 137 show_in_hierarchy(key,path); 138 } 139 } 140 else alert('Error: html not loaded!'); 141 } 142 ); 143 }, 144 show_in_hierarchy = function(key,open_level){ 145 var $left_col = $('.settingstree_left_column'), current = $left_col.data('current')||null; 146 if (current !== key){ 147 $left_col.html('<div class="notify">'+getLang('loading_hierarchy')+'</div>'); 148 $.post(DOKU_BASE + 'lib/exe/ajax.php', 149 { call:'plugin_settingstree', operation: 'show_hierarchy', pluginname: pluginname, key: key, sectok: token }, 150 function(r){ 151 if (r.token) token = r.token; 152 if (r.error) alert(r.msg); 153 if (r.html){ 154 $left_col.html(r.html); 155 $left_col.data('current',key); 156 open_hierarchy_level(open_level); 157 } 158 else alert('Error: html not loaded!'); 159 } 160 ); 161 }else{ 162 open_hierarchy_level(open_level); 163 } 164 } 165 ; 166 if (typeof opts.explorertree_id === 'string'){ 167 $(document).ready(function(){ 168 $('#'+opts.explorertree_id).on('tree_selected',function (event,id){ selectlevel(id); }); 169 }); 170 } 171 if (!(path = $root.find('#config__manager').data('path'))){ path = ':';} 172 if (typeof opts.path === 'string' && opts.path !== path){ 173 selectlevel(opts.path); 174 } 175 // we're delegating the listener to the $root (the container) so events will bubble up to it for any dynamically placed children. 176 $root.on('select_level', function (event,id){ selectlevel(id); }); 177 $root.on('show_in_hierarchy',function(event,key,open_level){ show_in_hierarchy(key,open_level); }); 178 $root.on('change','input, textarea, select',inputchange); 179 $root.on('settingstree_save',savelevel); 180 $root.on('settingstree_export',exportlevel); 181 $root.on('settingstree_cancel',resetlevel); 182 return this; 183};