## @noparams
#set ( $containerManagerClass = $content.class.forName('com.atlassian.spring.container.ContainerManager') )
#set ( $getInstanceMethod = $containerManagerClass.getDeclaredMethod('getInstance',null) )
#set ( $containerManager = $getInstanceMethod.invoke(null,null) )
#set ( $containerContext = $containerManager.containerContext )
#set ( $webResourceManager = $containerContext.getComponent('webResourceManager') )
$webResourceManager.requireResource('com.atlassian.auiplugin:aui-select2')
#set ( $Integer = 0 )
#set ( $requestedSearch = "" )
#set ( $requestedSearch = $req.getParameter('requestedSearch') )
#set ( $requestedSpaces = "" )
#set ( $requestedSpaces = $req.getParameter('requestedSpaces') )
#set ( $replace = "" )
#set ( $replace = $req.getParameter('replace') )
#set ( $requestedReplace = "" )
#set ( $requestedReplace = $req.getParameter('requestedReplace') )
#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;
}
function htmlDecode (text) {
return jQuery('<textarea/>').html(text).text();
}
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 = formatted.substr(0, formatted.length - 1) + ln + '\n';
else
formatted += padding + ln + '\n';
}
return formatted;
};
</script>
#if ( $requestedSearch == "" )
<form class="aui top-label" onsubmit="return false;">
<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 "${escapedRequestedSearch}" in $space.name </p>
#set ( $spacePages = $pageManager.getPages($space, true) )
<table>
<thead>
<tr>
<th>
<p>Page</p>
</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 ( $quoteEscapedPageMarkup = $pageMarkup.replaceAll('"', '@@quot@@').replaceAll('"', '@@quot@@') )
<tr>
<td style="vertical-align:middle">
<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">
</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>
</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" )
<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 "${escapedRequestedSearch}" 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 style="vertical-align:middle">
<p><a href="$action.getGlobalSettings().getBaseUrl()$page.getUrlPath()" target="_blank">$page.title</a></p>
</td>
<td style="vertical-align:middle">
#if ( $permissionHelper.canEdit($action.remoteUser, $page) )
#set ( $replacedPageMarkup = $pageMarkup.replaceAll($requestedSearch, $requestedReplace) )
#set ( $newPageMarkup = $replacedPageMarkup.replaceAll('"', '@@quot@@').replaceAll('"', '@@quot@@') )
#set ( $newPageMarkup = $newPageMarkup.replaceAll(" ", " ") ) ## because of some sort of bug where is replaced with Â
#set ( $quoteEscapedPageMarkup = $pageMarkup.replaceAll('"', '@@quot@@').replaceAll('"', '@@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>
</tr>
#end
#end
</tbody>
</table>
#end
<p> Found $searchResultCount results. You are about to replace "${escapedRequestedSearch}" with "${escapedRequestedReplace}" on all selected pages. Continue? </p>
<p> </p>
<button class="aui-button" onclick="replaceText()">Continue</button>
<button class="aui-button" onclick="window.location = '$content.getUrlPath()'">New Search</button>
<script>
function replaceText() {
searchReplace(jQuery(".page-checkbox.unchanged:checked").first())
}
function searchReplace(nextCheckbox) {
var pageId = jQuery(nextCheckbox).attr("pageid");
var pageObj = {
"id": pageId,
"type": "page",
"title": jQuery(nextCheckbox).attr("title"),
"space": {
"key": jQuery(nextCheckbox).attr("space")
},
"body": {
"storage": {
"value": jQuery(nextCheckbox).attr("content").split('@@quot@@').join('"'),
"representation": "storage"
}
},
"version": {
"number": parseInt(jQuery(nextCheckbox).attr("version")) + 1
}
}
jQuery.ajax({
dataType: "json",
contentType: "application/json",
type: "PUT",
url: contextPath + "/rest/api/content/" + pageId,
data: JSON.stringify(pageObj),
success: function (response) {
jQuery(nextCheckbox)
.removeClass("unchanged")
.addClass("changed");
jQuery(nextCheckbox)
.next()
.removeClass("aui-lozenge-current")
.removeClass("aui-lozenge-error")
.addClass("aui-lozenge-complete")
.html("updated");
jQuery("#undo-" + pageObj.id).show();
nextCheckbox = jQuery(".page-checkbox.unchanged:checked").first();
if (nextCheckbox.length) {
searchReplace(nextCheckbox);
}
},
error: function() {
jQuery(nextCheckbox).removeClass("unchanged").addClass("error");
jQuery(nextCheckbox)
.next()
.removeClass("aui-lozenge-complete")
.removeClass("aui-lozenge-current")
.addClass("aui-lozenge-error")
.html("error")
console.log(response);
nextCheckbox = jQuery(".page-checkbox.unchanged:checked").first();
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('<')
.split('>')
.join('>')
.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>