Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
## @noparams
#set ( $Integer$containerManagerClass = 0$content.class.forName('com.atlassian.spring.container.ContainerManager') )
#set ( $requestedSearch$getInstanceMethod = ""$containerManagerClass.getDeclaredMethod('getInstance',null) )
#set ( $requestedSearch$containerManager = $req$getInstanceMethod.getParameter('requestedSearch'invoke(null,null) )
#set ( $requestedSpaces$containerContext = ""$containerManager.containerContext )
#set ( $requestedSpaces$webResourceManager = $req$containerContext.getParametergetComponent('requestedSpaceswebResourceManager') )
$webResourceManager.requireResource('com.atlassian.auiplugin:aui-select2')

#set ( $replace$Integer = 0 )
#set ( $requestedSearch = "" )
#set ( $requestedSearch = $req.getParameter('requestedSearch') )
#set ( $requestedSpaces = "" )
#set ( $replace$requestedSpaces = $req.getParameter('replacerequestedSpaces') )
#set ( $requestedReplace$replace = "" )
#set ( $requestedReplace$replace = $req.getParameter('requestedReplacereplace') )
#set ( $continue$requestedReplace = "" )
#set ( $continue$requestedReplace = $req.getParameter('continuerequestedReplace') )
#set ( $escapedRequestedSearch = $generalUtil.escapeXml($requestedSearch) )
#set ( $escapedRequestedReplace = $generalUtil.escapeXml($requestedReplace) )
#set ( $requestCharacter = "?" )
#if ( $content.getUrlPath().contains("?") )
  #set ( $requestCharacter = "&" )
#end
<script>
  var qs = (function(a) {
    if (a == "") return {};
    var b = {};
    for (var i = 0; i < a.length; ++i) {
      var p=a[i].split('=', 2);
      if (p.length == 1)
        b[p[0]] = "";
      else
        b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
    }
    return b;
  })(window.location.search.substr(1).split('&'));
   
  function htmlEncode ( html ) {
    return document.createElement( 'a' ).appendChild( document.createTextNode( html ) ).parentNode.innerHTML;
  };
</script> #if (
$requestedSearch == ""  function htmlDecode (text) {
 <form class="aui top-label" onsubmit="return false;">jQuery('<textarea/>').html(text).text();
  }

<div class="field-group top-label">
      <label for="requested-search">Enter Search Terms:</label> 
      <input id="requested-search" class="text long-field" type="text" name="requestedSearch">
    </div>
    <div class="field-group">
      <input id="replace" type="checkbox" onclick="jQuery('#requested-replace').val('');jQuery('#replace-fields').toggle();">
      <span>Do Search/Replace</span>
    </div>
    <div class="field-group" id="replace-fields" style="display:none;">
      <label for="requested-replace">Text to replace:</label> 
      <input id="requested-replace" class="text long-field" type="text" name="requestedReplace">
    </div>
    <script> jQuery(function() { if (document.getElementById('replace').checked) { jQuery('#replace-fields').show(); } }); </script> ## show replace field if user hits back button
    <div class="field-group">
      <label for="requestedSpaces">Spaces to search:</label>
      <select class="select" id="requestedSpaces" name="requestedSpaces" multiple>
      #set ( $allSpaces = $spaceManager.getAllSpaces() )
      #foreach ( $space in $allSpaces )
        #if ( $space.isGlobal() )
          <option value="$space.key">$space.name - $space.key</option>
        #end
      #end
    </div>
    <button class="button submit" onclick="window.location = '$content.getUrlPath()' + '${requestCharacter}requestedSearch=' + encodeURIComponent(document.getElementById('requested-search').value) + '&requestedSpaces=' + jQuery('#requestedSpaces').select2('val').join() + '&replace=' + jQuery('#replace').is(':checked') + '&requestedReplace=' + encodeURIComponent(document.getElementById('requested-replace').value);">Search</button>
  </form>
  <script>
    jQuery("#requestedSpaces").auiSelect2();
  </script>
#elseif ( $requestedSearch != "" && $replace == "false" )
  #set ( $searchTerm = $requestedSearch )
  #foreach ( $spaceKey in $requestedSpaces.split(",") )
    #set ( $space = $spaceManager.getSpace($spaceKey) )
    <p> Pages containing &quot;${escapedRequestedSearch}&quot; in $space.name </p>
    #set ( $spacePages = $pageManager.getPages($space, true) )
    <table>
      <thead>
        <tr>
          <th>
            <p>Page</p>
          </th>
          <th>
 var formatXml = this.formatXml = function (xml) {
    var reg = /(>)\s*(<)(\/*)/g;
    var wsexp = / *(.*) +\n/g;
    var contexp = /(<.+>)(.+\n)/g;
    xml = xml.replace(reg, '$1\n$2$3').replace(wsexp, '$1\n').replace(contexp, '$1\n$2');
    var pad = 0;
    var formatted = '';
    var lines = xml.split('\n');
    var indent = 0;
    var lastType = 'other';
    var transitions = {
      'single->single': 0,
      'single->closing': -1,
      'single->opening': 0,
      'single->other': 0,
      'closing->single': 0,
      'closing->closing': -1,
      'closing->opening': 0,
      'closing->other': 0,
      'opening->single': 1,
      'opening->closing': 0,
      'opening->opening': 1,
      'opening->other': 1,
      'other->single': 0,
      'other->closing': -1,
      'other->opening': 0,
      'other->other': 0
    };

    for (var i = 0; i < lines.length; i++) {
      var ln = lines[i];
      var single = Boolean(ln.match(/<.+\/>/));
      var closing = Boolean(ln.match(/<\/.+>/));
      var opening = Boolean(ln.match(/<[^!].*>/));
      var type = single ? 'single' : closing ? 'closing' : opening ? 'opening' : 'other';
      var fromTo = lastType + '->' + type;
      lastType = type;
      var padding = '';
    
      indent += transitions[fromTo];
      for (var j = 0; j < indent; j++) {
        padding += '  ';
      }
      if (fromTo == 'opening->closing')
        formatted </th>
        </tr>= formatted.substr(0, formatted.length - 1) + ln + '\n';
      else
</thead>       <tbody> formatted += padding + ln + #foreach ($page in $spacePages)
 '\n';
    }
    return formatted;
#set ( $pageId = $page.id };
</script>
#if ( $requestedSearch == "" )
  <form class="aui top-label" onsubmit="return false;">
  #set ( $pageMarkup<div class= $page.getBodyAsString() )"field-group top-label">
      <label for="requested-search">Enter Search Terms:</label>
#if ( $permissionHelper.canView($action.remoteUser, $page) && $pageMarkup.contains($searchTerm) )
          #set ( $quoteEscapedPageMarkup = $pageMarkup.replaceAll($generalUtil.urlDecode("%22"), "&quot;") )
    <input id="requested-search" class="text long-field" type="text" name="requestedSearch">
    </div>
      <tr><div class="field-group">
      <input      <td>
              <p><a href="$action.getGlobalSettings().getBaseUrl()$page.getUrlPath()" target="_blank">$page.title</a></p>id="replace" type="checkbox" onclick="jQuery('#requested-replace').val('');jQuery('#replace-fields').toggle();">
      <span>Do Search/Replace</span>
    </div>
   <input style="display:none;" <div class="page-checkbox" type="checkbox"field-group" id="pagereplace-$pageIdfields" originalstyle="$quoteEscapedPageMarkupdisplay:none;">
      <label for="requested-replace">Text to    replace:</td>label>
      <input id="requested-replace" class="text long-field" type="text" name="requestedReplace">
<td>    </div>
    <script>  jQuery(function() { if  <button id="preview${pageId}" class="aui-button">Preview</button>
        (document.getElementById('replace').checked) { jQuery('#replace-fields').show(); } }); </script> ## show replace field if user hits back button
     <button<div class="auifield-buttongroup" onclick="window.open(contextPath + '/pages/editpage.action?pageId=$pageId', '_blank');">Edit</button>>
      <label for="requestedSpaces">Spaces to search:</label>
      <select  <script>
class="select" id="requestedSpaces" name="requestedSpaces" multiple>
      #set ( $allSpaces = $spaceManager.getAllSpaces() )
   var dialog${pageId} = new#foreach AJS.Dialog({ $space in $allSpaces )
        #if ( $space.isGlobal() )
    width: 840,     <option value="$space.key">$space.name - $space.key</option>
        #end
    height: 640, #end
    </div>
    <button class="button submit" onclick="window.location = '$content.getUrlPath()'      id: "dialog${pageId}", 
                    closeOnOutsideClick: true
                });
                dialog${pageId}.addHeader("Preview");
                
                var originalMarkup = jQuery("#page-${pageId}").attr("original");
                var originalMarkupArray = originalMarkup.split(jQuery('<textarea/>').html(qs["requestedSearch"]).text());
+ '${requestCharacter}requestedSearch=' + encodeURIComponent(document.getElementById('requested-search').value) + '&requestedSpaces=' + jQuery('#requestedSpaces').select2('val').join() + '&replace=' + jQuery('#replace').is(':checked') + '&requestedReplace=' + encodeURIComponent(document.getElementById('requested-replace').value);">Search</button>
  </form>
  <script>
    jQuery("#requestedSpaces").auiSelect2();
  </script>
#elseif ( $requestedSearch != "" && $replace == "false" )
  #set ( $searchTerm = $requestedSearch )
  #foreach ( $spaceKey in $requestedSpaces.split(",") )
    #set ( $space = $spaceManager.getSpace($spaceKey) )
    <p> Pages containing &quot;${escapedRequestedSearch}&quot; in $space.name </p>
    #set ( $spacePages = $pageManager.getPages($space, true) )
    <table>
      <thead>
        var<tr>
 previewMarkup = jQuery('<pre style="white-space: pre-wrap;white-space: -moz-pre-wrap;white-space: -pre-wrap;white-space: -o-pre-wrap;word-wrap: break-word;"></pre>');
 <th>
            <p>Page</p>
  var replaceElement = '<span style="background-color: #ddfade;">' + htmlEncode(qs["requestedSearch"]) + '</span>';th>
          <th>
      jQuery.each( originalMarkupArray, function(i, val) {</th>
        </tr>
      </thead>
  jQuery(previewMarkup).append(jQuery('<span>' + htmlEncode(val) + '</span>' + replaceElement));   <tbody>
      #foreach ($page in $spacePages)
        #set ( $pageId = $page.id )
      });  #set ( $pageMarkup = $page.getBodyAsString() )
        #if jQuery('span', previewMarkup).last().remove();
 $permissionHelper.canView($action.remoteUser, $page) && $pageMarkup.contains($searchTerm) )
          #set ( $quoteEscapedPageMarkup =  dialog${pageId}.addPanel("SinglePanel", previewMarkup, "singlePanel");
$pageMarkup.replaceAll('"', '@@quot@@').replaceAll('&quot;', '@@quot@@') )
          <tr>
                     dialog${pageId}.addButton("Close", function (dialog${pageId}) {<td style="vertical-align:middle">
                       dialog${pageId}.hide();
<p><a href="$action.getGlobalSettings().getBaseUrl()$page.getUrlPath()" target="_blank">$page.title</a></p>
               });
  <input style="display:none;" class="page-checkbox" type="checkbox" id="page-$pageId" pageid="$pageId" original="$quoteEscapedPageMarkup">
             jQuery("#preview${pageId}").click(function() {</td>
            <td>
         dialog${pageId}.gotoPage(0);                     dialog$<button id="preview${pageId}.gotoPanel(0);
" class="aui-button">Preview</button>
              <button class="aui-button" onclick="window.open(contextPath   dialog${pageId}.show();
                });
              </script>+ '/pages/editpage.action?pageId=$pageId', '_blank');">Edit</button>
            </td>
          </tr>
        #end
      #end
      </tbody>
    </table>
  #end
  <p> </p>
  <button class="aui-button" onclick="window.location = '$content.getUrlPath()'">New Search</button>
#elseif ( $requestedSearch != "" && $replace == "true" && $continue == "" )
  <button class="aui-button" onclick="jQuery('.page-checkbox').prop('checked', true);">Select All</button>
  <button class="aui-button" onclick="jQuery('.page-checkbox').prop('checked', false);">Select None</button>
  #set ( $searchResultCount = 0 )
  #set ( $searchTerm = $requestedSearch )
  #foreach ( $spaceKey in $requestedSpaces.split(",") )
    #set ( $space = $spaceManager.getSpace($spaceKey) )
    <p> Pages containing &quot;${escapedRequestedSearch}&quot; in $space.name </p>
    #set ( $spacePages = $pageManager.getPages($space, true) )
    <table>
      <thead>
        <colgroup> ## To prevent table from being sortable
        </colgroup>
        <tr>
          <th>
            <p>Page</p>
          </th>
          <th>
            <button class="aui-button" onclick="jQuery('.page-checkbox[space=\'$space.key\']').click();">X</button>
          </th>
          <th>
          </th>
        </tr>
      </thead>
      <tbody>
      #foreach ($page in $spacePages)
        #set ( $pageId = $page.id )
        #set ( $pageMarkup = $page.getBodyAsString() )
        #if ( $permissionHelper.canView($action.remoteUser, $page) && $pageMarkup.contains($searchTerm) )
          #set ( $searchResultCount = $searchResultCount + 1 )
          <tr>
            <td>
<td style="vertical-align:middle">
              <p><a href="$action.getGlobalSettings().getBaseUrl()$page.getUrlPath()" target="_blank">$page.title</a></p>
            </td>
            <td> <td style="vertical-align:middle">
              #if ( $permissionHelper.canEdit($action.remoteUser, $page) )
                #set ( $replacedPageMarkup = $pageMarkup.replaceAll($requestedSearch, $requestedReplace) )
                #set ( $newPageMarkup = $replacedPageMarkup.replaceAll($generalUtil.urlDecode("%22"), "&quot;"'"', '@@quot@@').replaceAll('&quot;', '@@quot@@') )
## %22 = "
                #set ( $newPageMarkup = $newPageMarkup.replaceAll("&nbsp;", " ") ) ## because of some sort of bug where &nbsp; is replaced with Â
                #set ( $quoteEscapedPageMarkup = $pageMarkup.replaceAll($generalUtil.urlDecode("%22"), "&quot;"'"', '@@quot@@').replaceAll('&quot;', '@@quot@@') )
                <input class="page-checkbox unchanged" type="checkbox" id="page-$pageId" pageid="$pageId" version="$page.version" title="$page.title" parent="$page.parent.id" space="$space.key" content="$newPageMarkup" original="$quoteEscapedPageMarkup" checked="checked">
                <span class="aui-lozenge">unchanged</span>
              #else
                <span class="aui-lozenge aui-lozenge-current">cannot edit</span>
              #end
            </td>
            <td>
              <button id="preview${pageId}" class="aui-button">Preview</button>
              <button class="aui-button" onclick="window.open(contextPath + '/pages/editpage.action?pageId=$pageId', '_blank');">Edit</button>
              <button style="display:none;" id="undo-${pageId}" class="aui-button" onclick="window.open(contextPath + '/pages/revertpagebacktoversion.action?pageId=${pageId}&version=$page.version', '_blank');">Undo</button>
            </td>
 <script>         </tr>
       var dialog${pageId}#end
= new AJS.Dialog({    #end
      </tbody>
    </table>
  #end
 width: 840,<p> Found $searchResultCount results.  You are about to replace &quot;${escapedRequestedSearch}&quot; with &quot;${escapedRequestedReplace}&quot; on all selected pages.  Continue? </p>
  height: 640,<p> </p>
  <button class="aui-button" onclick="replaceText()">Continue</button>
  <button class="aui-button" onclick="window.location = '$content.getUrlPath()'">New Search</button>
  <script>
    function id: "dialog${pageId}",replaceText() {
      searchReplace(jQuery(".page-checkbox.unchanged:checked").first())
    }

    function searchReplace(nextCheckbox) {
 closeOnOutsideClick: true    var pageId = jQuery(nextCheckbox).attr("pageid");
      var pageObj = {
 });       "id": pageId,
        dialog${pageId}.addHeader("Preview");
"type": "page",
        "title": jQuery(nextCheckbox).attr("title"),
        "space": {
            var originalMarkup ="key": jQuery("#page-${pageId}").attr("original");nextCheckbox).attr("space")
        },
        var originalMarkupArray = originalMarkup.split(jQuery('<textarea/>').html(qs["requestedSearch"]).text());"body": {
          "storage": {
        var previewMarkup = jQuery('<pre style="white-space: pre-wrap;white-space: -moz-pre-wrap;white-space: -pre-wrap;white-space: -o-pre-wrap;word-wrap: break-word;"></pre>'); "value": jQuery(nextCheckbox).attr("content").split('@@quot@@').join('"'),
            "representation": "storage"
      var replaceElement = '<span style="background-color: #ddfade;">' + htmlEncode(qs["requestedReplace"]) + '</span>';
  }
        },
        "version": {
     if (qs["requestedReplace"] === "") { replaceElement = '<span style="background-color: #ddfade;">[blank]</span>' } ## so there is something to show if replacement field is blank
     "number": parseInt(jQuery(nextCheckbox).attr("version")) + 1
        }
      }
      jQuery.ajax({
        dataType: "json",
     jQuery.each( originalMarkupArray, function(i, val) {   contentType: "application/json",
        type: "PUT",
        url: contextPath  jQuery(previewMarkup).append(jQuery('<span>' + htmlEncode(val) + '</span>' + replaceElement));+ "/rest/api/content/" + pageId,
        data: JSON.stringify(pageObj),
        success: function (response) {
        });  jQuery(nextCheckbox)
              jQuery('span', previewMarkup).last().remove();removeClass("unchanged")
                dialog${pageId}.addPanel.addClass("SinglePanel", previewMarkup, "singlePanel"changed");
          jQuery(nextCheckbox)
              .next()
       dialog${pageId}.addButton("Close", function (dialog${pageId}) {      .removeClass("aui-lozenge-current")
              dialog${pageId}.hide();removeClass("aui-lozenge-error")
                });.addClass("aui-lozenge-complete")
                jQuery.html("#preview${pageId}updated").click(function() {;
          jQuery("#undo-" + pageObj.id).show();
         dialog${pageId}.gotoPage(0); nextCheckbox = jQuery(".page-checkbox.unchanged:checked").first();
          if (nextCheckbox.length) {
           dialog${pageId}.gotoPanel(0 searchReplace(nextCheckbox);
          }
         dialog${pageId}.show();},
        error: function() {
     });     jQuery(nextCheckbox).removeClass("unchanged").addClass("error");
         </script>
 jQuery(nextCheckbox)
           </td>   .next()
       </tr>         #end.removeClass("aui-lozenge-complete")
       #end       </tbody>.removeClass("aui-lozenge-current")
     </table>   #end   <p> Found $searchResultCount results..addClass("aui-lozenge-error")
 You   are about to replace &quot;${escapedRequestedSearch}&quot; with &quot;${escapedRequestedReplace}&quot; on all selected pages.html("error")
 Continue? </p>   <p> </p>   <button class="aui-button" onclick="replaceText()">Continue</button> console.log(response);
  <button class="aui-button" onclick="window.location = '$content.getUrlPath()'">New Search</button>   <script>
    function replaceText(){searchReplace(nextCheckbox = jQuery(".page-checkbox.unchanged:checked").first())}
function searchReplace(a){var c=[],b={};b.id=jQuery(a).attr("pageid");b.version=jQuery(a).attr("version");b.title=jQuery(a).attr("title");b.space=jQuery(a).attr("space");b.content=jQuery(a).attr("content");b.parentId=jQuery(a).attr("parent");c.push(b);jQuery.ajax({dataType:"json",contentType:"application/json",type:"POST",url:contextPath+"/rpc/json-rpc/confluenceservice-v2/storePage",data:JSON.stringify(c),success:function(c){c.hasOwnProperty("id")?(jQuery(a).removeClass("unchanged").addClass("changed"),
jQuery(a).next().removeClass("aui-lozenge-current").removeClass("aui-lozenge-error").addClass("aui-lozenge-complete").html("updated"),jQuery("#undo-"+b.id).show(),a=jQuery("input[type='checkbox'].page-checkbox.unchanged:checked").first()):(jQuery(a).removeClass("unchanged").addClass("error"),jQuery(a).next().removeClass("aui-lozenge-complete").removeClass("aui-lozenge-current").addClass("aui-lozenge-error").html("error"),console.log(c),a=jQuery(".page-checkbox.unchanged:checked").first());0<a.length&&
searchReplace(a)}})};
  </script>
#end;
          
          if (nextCheckbox.length) {
            searchReplace(nextCheckbox);
          }
        }
      });
    }
  </script>
#end
<script>
  var nextMatch;
  var dialogs = {};
  var requestedSearch = qs["requestedSearch"];
  var requestedReplace = qs["requestedReplace"];
  var replace = qs["replace"];
  
  if (replace !== 'true') {
    requestedReplace = requestedSearch;
  }
  if (requestedReplace === "") {
    requestedReplace = '[Blank]';
  }
  
  if (requestedSearch) {
    jQuery(".page-checkbox").each(function() {
      var pageId = jQuery(this).attr("pageid");
      dialogs[pageId] = new AJS.Dialog({
          width: 840,
          height: 640,
          id: "dialog" + pageId,
          closeOnOutsideClick: true
      });
      dialogs[pageId].addHeader("Preview");
       
      var replacedMarkup = jQuery(this)
          .attr("original")
          .split('@@quot@@')
          .join('"')
          .split(htmlDecode(requestedSearch))
          .join(' @@start@@ ' + htmlEncode(requestedReplace) + ' @@end@@ ');
      var formattedMarkup = formatXml(replacedMarkup);
      var previewMarkup = jQuery('<pre style="white-space: pre-wrap;white-space: -moz-pre-wrap;white-space: -pre-wrap;white-space: -o-pre-wrap;word-wrap: break-word;"><span>' + 
          formattedMarkup
          .split('<')
          .join('&lt;')
          .split('>')
          .join('&gt;') 
          .split(' @@start@@ ')
          .join('</span><span class="match" style="background-color: #ddfade;">')
          .split(' @@end@@ ')
          .join('</span><span>') + 
          '</span></pre>');
      dialogs[pageId].addPanel("SinglePanel", previewMarkup, "singlePanel");
      
      dialogs[pageId].addButton("Next Match", function () {
          if (!nextMatch) {
            nextMatch = jQuery(".match:visible").first();
            nextMatch.css("background-color", "yellow");
          } else {
            nextMatch.css("background-color", "#ddfade");
            nextMatch = nextMatch.next().next(".match").length ? nextMatch.next().next(".match") : jQuery(".match:visible").first();
            nextMatch.css("background-color", "yellow");
          }
          nextMatch.get(0).scrollIntoView();
      });
      
      dialogs[pageId].addButton("Close", function () {
          if (nextMatch) { 
            nextMatch.css("background-color", "#ddfade");
            nextMatch = undefined;
          }
          dialogs[pageId].hide();
      });
      
      jQuery("#preview" + pageId).click(function() {
          dialogs[pageId].gotoPage(0);
          dialogs[pageId].gotoPanel(0);
          dialogs[pageId].show();
      });
    });
  }
</script>