// ==UserScript==
// @name CMS Extension
// @include http://*.sharpschool.com/*
// @version 1.0.0
// @grant none
// @description This script simplifies content migration.
// @namespace https://greasyfork.org/users/13871
// ==/UserScript==
// This is the server address, used to connect to server.exe
var server = 'http://localhost:9000';
// This is the text area for the HTML editor.
var textArea;
// Initializing a DOM parser
var parser = new DOMParser();
// Initializing a second DOM, synchronized with the source code in the editor
var DOM2;
// Initializing a list used to store URLs
var queue = [];
// Initializing server folder name for ajax call
var serverFolder;
// Avoid form submission by pressing Enter
$(document).ready(function() {
$(window).keydown(function(event) {
if (event.keyCode == 13) {
event.preventDefault();
return false;
}
});
});
$(document).ready(function() {
detect()
});
function detect() {
$.ajax({
url: server,
method: 'HEAD',
success: function() {
main();
if (serverListener != undefined) {
clearInterval(serverListener)
}
}
})
}
// Detect if server.exe is running every 2000 miliseconds; execute the rest only if the server.exe is on
var serverListener = setInterval(function() {
detect()
}, 2000)
// Decides which part will be executed based on the page type
function main() {
if (Boolean(document.URL.match(/action=edit/i)) && Boolean(document.URL.match(/portletAction=pageedit/i))) {
execContent();
} else if (Boolean(document.URL.match(/action=addextlinkpage/i)) || Boolean(document.URL.match(/action=editextlinkpage/i))) {
execExt();
};
function execContent() {
// Inject UI when creating or modifying a content space page
$(window).ready(function() {
// Inject UI only once
if (typeof $('div #ExtensionPlaceHolder')[0] == 'undefined') {
$('div[id*="divInlineEdit"]').after($('<div id="ExtensionPlaceHolder"></div>').load(server))
}
});
// Create an observer instance for editor mode
(function() {
var observer = new MutationObserver(function() {
if ($('a.reMode_html').hasClass('reMode_html reMode_selected')) {
$('#overlay').fadeOut();
} else {
$('#overlay').fadeIn();
}
});
var options = {
'attributes': true,
'subtree': true
};
observer.observe($('.reEditorModes')[0], options)
})();
// Button binding
$(document).on('click', '#startBtn', function() {
sendElem(0);
$("#loadBtn, #stripBtn, #startBtn").prop("disabled", true);
$(".reEditorModes").fadeOut();
}).on('click', '#stripBtn', strip).on('click', '#loadBtn', function() {
textArea = $('td[id*="reEditArea"].reContentCell iframe:last-child')[0].contentDocument.body.childNodes[0];
updateDOM();
createDOMObserver();
displayRows();
}).on('click', '#loadBtn', function() {
textArea = $('td[id*="reEditArea"].reContentCell iframe:last-child')[0].contentDocument.body.childNodes[0];
updateDOM();
createDOMObserver();
displayRows();
sendPageInfo();
}).on('focus', '.URLBox', function() {
$(this).css({
'background-color': '#333333'
})
}).on('blur', '.URLBox', function() {
$(this).blur(function() {
$(this).css({
'background-color': ''
})
});
}).on('mouseover', '.URLBox', function() {
$(this).css({
'color': '#AAAAAA'
})
}).on('mouseleave', '.URLBox', function() {
$(this).css({
'color': ''
})
});
}
}
// Retrieve HTML code in the editor and pass it to DOM2
function updateDOM() {
DOM2 = parser.parseFromString(textArea.value, 'text/html');
console.log('DOM Updated.')
}
// Update the text area according to DOM
function updateText() {
textArea.value = DOM2.body.innerHTML
}
// Create an observer instance for DOM2
function createDOMObserver() {
observer = new MutationObserver(function() {
updateText()
});
var options = {
'attributes': true,
'subtree': true
};
observer.observe(DOM2.querySelector('html'), options)
}
// This function removes the HTML formatting once called
function strip() {
// Remove attributes
var attrToRemove = [
'class',
'id',
'style',
'target'
];
for (i = 0; i < attrToRemove.length; i++) {
$(DOM2).find('*').removeAttr(attrToRemove[i]);
};
// Remove the following nodes
var nodeToRemove = [
'script',
'style'
];
for (i = 0; i < nodeToRemove.length; i++) {
$(DOM2).find(nodeToRemove[i]).each(function() {
this.remove()
})
};
// Remove the following tags
tagToRemove = [
'span',
'font'
];
for (i = 0; i < tagToRemove.length; i++) {
$(DOM2).find(tagToRemove[i]).contents().unwrap();
};
// Remove comments
$(DOM2).find('*').contents().each(function() {
if (this.nodeType == Node.COMMENT_NODE) {
$(this).remove()
}
})
}
// This method returns the last element of an array.
Array.prototype.last = function() {
return this[this.length - 1]
}
// This function returns an array of string, each string represents the page title, from parent to child.
function getPageList() {
var last = $('#breadcrumbs span:last-child')[0];
if (last == undefined) {
return []
} else {
var dir = [];
$('#breadcrumbs a').each(function() {
dir.push(this.textContent)
});
dir.push(last.textContent);
dir.shift(0);
return dir
}
}
// Use ajax to get serverFolder
(function() {
$.ajax({
url: 'http://' + document.domain + '/cms/FileAdministration/FileExplorer.aspx',
dataType: 'html',
success: function(data) {
var parser,
doc,
address;
parser = new DOMParser();
doc = parser.parseFromString(data, 'text/html');
address = doc.getElementById('radFileExploer_address').value;
serverFolder = address.split('/')[3]
console.log("The server folder is: " + serverFolder)
}
})
})();
// Returns the ProdX folder based on the domain
function getProdFolder() {
var domain = document.domain;
var number = domain.split('.')[1].replace('ss', '');
return 'Prod' + number
}
// Send page information to server.exe
function sendPageInfo() {
var info = {
PAGEINFO: {
prod: getProdFolder(),
serverFolder: serverFolder,
pageList: getPageList()
}
};
$.ajax({
url: server,
type: 'POST',
data: JSON.stringify(info),
crossDomain: true,
error: function(res, err) {
console.log(err)
},
success: function() {
console.log('Page info sent.')
$(document).find('#stripBtn, #startBtn').prop('disabled', null)
}
})
}
// Add one row to the summary table based on a node in DOM2
function addRow(e) {
var newRow = $('<div class="rowBox"><input class="linktext" readOnly="true" type="text" value=""><input class="URLBox" type="text" value="" readonly="true" onclick="this.readOnly=\'\'"><input type="text" class="status" value="Ready" readonly="true">');
$(newRow).find('.linktext').val(linkText(e));
if (e.tagName == 'A') {
$(newRow).find('.URLBox').val(e.getAttribute('href')).change(function() {
e.href = $(this).val()
});
} else {
$(newRow).find('.URLBox').val(e.getAttribute('src')).change(function() {
e.src = $(this).val()
});
};
$('#scrollBox').append(newRow);
return [$(e),
newRow
]
}
// Get link text from an element
function linkText(e) {
if (e.tagName == 'A') {
return e.text.replace(/^[ \n\t\r]*|[ \n\t\r]*$/g, '')
} else {
return '<img>'
}
}
// Display rows of URLs in the summary list, tag is either "IMG" or "A"
function displayRows() {
queue = [];
$('#scrollBox').html('');
$(DOM2).find('a').each(function() {
queue.push(addRow(this))
});
$(DOM2).find('img').each(function() {
queue.push(addRow(this))
});
}
// Start Button, i starts from 1 (first URL)
function sendElem(i) {
if (queue[i]) {
$.ajax({
url: server,
beforeSend: function(xhr) {
xhr.overrideMimeType('application/json');
},
type: 'POST',
data: JSON.stringify({
START: {
URL: URLattr(i),
tagName: tagName(i)
}
}),
crossDomain: true,
});
var realtimeStatus = setInterval(function() {
checkStatus(function(data) {
stat = data.status;
setStatus(i, stat);
if (stat == 'Skipped' || stat.contains('Error')) {
clearInterval(realtimeStatus);
URLattr(i, data.URL);
sendElem(i + 1)
} else if (stat == 'Done') {
clearInterval(realtimeStatus);
URLattr(i, data.URL);
sendElem(i + 1)
} else {
return false
}
})
}, 200)
} else {
$("#loadBtn, #stripBtn, #startBtn").prop("disabled", false);
$(".reEditorModes").fadeIn();
}
}
// Check status
function checkStatus(callback) {
$.getJSON(server + '/status', function(data) {
// data = {status: "string"}
callback(data)
})
}
// Helper functions to set status tag name and URLs
function setStatus(i, status) {
var $r = queue[i][1];
$r.find('.status').val(status)
}
// Return the i-th tag name in queue
function tagName(i) {
var $e = queue[i][0];
return $e.prop('tagName')
}
// Return the i-th URL if url is not specified; otherwise change to url
function URLattr(i, url) {
var $r = queue[i][1];
var $e = queue[i][0];
if (url) {
$r.find('.URLBox').val(url);
if (tagName(i) == 'A') {
$e.attr('href', url)
} else {
$e.attr('src', url)
}
} else {
if (tagName(i) == 'A') {
return $e.attr('href')
} else {
return $e.attr('src')
}
}
}
// The following functions are used for external link editor
function execExt() {
var $inputBox = $('input[id*="txtUrl"]');
var $protocol = $('select[id*="ddlProtocol"]')
// Inject Status Box
if (typeof $('div #extLinkUI')[0] == 'undefined') {
$('span[id*="txtUrl_ErrFlag"]').after($('<div style="padding:2px" id="extLinkUI"><button type="button" id="chkBtn">Check</button><input style="border:none; position: relative; cursor: default; font-family: consolas; padding-left: 10px" type="text" readlonly="true" id="statusBox" value="Ready"></div>')).ready(function() {
$('#chkBtn').click(function() {
sendPageInfo();
send()
})
})
}
// Get the external link in the text box
function getExternal() {
if ($inputBox.val().match(new RegExp('^(http://|https://)')) == null) {
var url = $protocol.val() + $inputBox.val()
} else {
var url = $inputBox.val()
}
return url
}
// Mutates the status
function setExtStatus(st) {
$('#statusBox').val(st)
}
// Send the information to server.exe
function send() {
$.ajax({
url: server,
beforeSend: function(xhr) {
xhr.overrideMimeType('application/json');
},
type: 'POST',
data: JSON.stringify({
START: {
URL: getExternal(),
tagName: 'A'
}
}),
error: function(data, err) {
console.log(err)
},
success: function() {
$("#chkBtn").prop("disabled", true);
},
crossDomain: true,
});
var realtimeStatus = setInterval(function() {
checkStatus(function(data) {
stat = data.status;
setExtStatus(stat);
if (stat == 'Skipped' || stat.contains('Error')) {
clearInterval(realtimeStatus);
$("#chkBtn").prop("disabled", false);
} else if (stat == 'Done') {
clearInterval(realtimeStatus);
$inputBox.val(data.URL);
$("#chkBtn").prop("disabled", false);
$("input[id*='rblTypes_1']").prop("checked", true);
}
})
}, 200)
}
}