0byt3m1n1
Path:
/
home1
/
aserty
/
public_html
/
bonniescraftygifts.com
/
iFzj4
/
configCHM
/
Jump
/
0-aserty
/
beatlesmontreal.com
/
wp-contentebbd3f
/
uploads
/
wp-content
/
plugins
/
jetpack
/
modules
/
after-the-deadline
/
[
Home
]
File: atd.core.js
/* * atd.core.js - A building block to create a front-end for AtD * Author : Raphael Mudge, Automattic * License : LGPL * Project : http://www.afterthedeadline.com/developers.slp * Contact : raffi@automattic.com */ /* EXPORTED_SYMBOLS is set so this file can be a JavaScript Module */ var EXPORTED_SYMBOLS = ['AtDCore']; function AtDCore() { /* these are the categories of errors AtD should ignore */ this.ignore_types = ['Bias Language', 'Cliches', 'Complex Expression', 'Diacritical Marks', 'Double Negatives', 'Hidden Verbs', 'Jargon Language', 'Passive voice', 'Phrases to Avoid', 'Redundant Expression']; /* these are the phrases AtD should ignore */ this.ignore_strings = {}; /* Localized strings */ this.i18n = {}; }; /* * Internationalization Functions */ AtDCore.prototype.getLang = function(key, defaultk) { if (this.i18n[key] == undefined) return defaultk; return this.i18n[key]; }; AtDCore.prototype.addI18n = function(localizations) { this.i18n = localizations; }; /* * Setters */ AtDCore.prototype.setIgnoreStrings = function(string) { var parent = this; this.map(string.split(/,\s*/g), function(string) { parent.ignore_strings[string] = 1; }); }; AtDCore.prototype.showTypes = function(string) { var show_types = string.split(/,\s*/g); var types = {}; /* set some default types that we want to make optional */ /* grammar checker options */ types["Double Negatives"] = 1; types["Hidden Verbs"] = 1; types["Passive voice"] = 1; types["Bias Language"] = 1; /* style checker options */ types["Cliches"] = 1; types["Complex Expression"] = 1; types["Diacritical Marks"] = 1; types["Jargon Language"] = 1; types["Phrases to Avoid"] = 1; types["Redundant Expression"] = 1; var ignore_types = []; this.map(show_types, function(string) { types[string] = undefined; }); this.map(this.ignore_types, function(string) { if (types[string] != undefined) ignore_types.push(string); }); this.ignore_types = ignore_types; }; /* * Error Parsing Code */ AtDCore.prototype.makeError = function(error_s, tokens, type, seps, pre) { var struct = new Object(); struct.type = type; struct.string = error_s; struct.tokens = tokens; if (new RegExp("\\b" + error_s + "\\b").test(error_s)) { struct.regexp = new RegExp("(?!"+error_s+"<)\\b" + error_s.replace(/\s+/g, seps) + "\\b"); } else if (new RegExp(error_s + "\\b").test(error_s)) { struct.regexp = new RegExp("(?!"+error_s+"<)" + error_s.replace(/\s+/g, seps) + "\\b"); } else if (new RegExp("\\b" + error_s).test(error_s)) { struct.regexp = new RegExp("(?!"+error_s+"<)\\b" + error_s.replace(/\s+/g, seps)); } else { struct.regexp = new RegExp("(?!"+error_s+"<)" + error_s.replace(/\s+/g, seps)); } struct.used = false; /* flag whether we've used this rule or not */ return struct; }; AtDCore.prototype.addToErrorStructure = function(errors, list, type, seps) { var parent = this; this.map(list, function(error) { var tokens = error["word"].split(/\s+/); var pre = error["pre"]; var first = tokens[0]; if (errors['__' + first] == undefined) { errors['__' + first] = new Object(); errors['__' + first].pretoks = {}; errors['__' + first].defaults = new Array(); } if (pre == "") { errors['__' + first].defaults.push(parent.makeError(error["word"], tokens, type, seps, pre)); } else { if (errors['__' + first].pretoks['__' + pre] == undefined) errors['__' + first].pretoks['__' + pre] = new Array(); errors['__' + first].pretoks['__' + pre].push(parent.makeError(error["word"], tokens, type, seps, pre)); } }); }; AtDCore.prototype.buildErrorStructure = function(spellingList, enrichmentList, grammarList) { var seps = this._getSeparators(); var errors = {}; this.addToErrorStructure(errors, spellingList, "hiddenSpellError", seps); this.addToErrorStructure(errors, grammarList, "hiddenGrammarError", seps); this.addToErrorStructure(errors, enrichmentList, "hiddenSuggestion", seps); return errors; }; AtDCore.prototype._getSeparators = function() { var re = '', i; var str = '"s!#$%&()*+,./:;<=>?@[\]^_{|}'; // Build word separator regexp for (i=0; i<str.length; i++) re += '\\' + str.charAt(i); return "(?:(?:[\xa0" + re + "])|(?:\\-\\-))+"; }; AtDCore.prototype.processXML = function(responseXML) { /* types of errors to ignore */ var types = {}; this.map(this.ignore_types, function(type) { types[type] = 1; }); /* save suggestions in the editor object */ this.suggestions = []; /* process through the errors */ var errors = responseXML.getElementsByTagName('error'); /* words to mark */ var grammarErrors = []; var spellingErrors = []; var enrichment = []; for (var i = 0; i < errors.length; i++) { if (errors[i].getElementsByTagName('string').item(0).firstChild != null) { var errorString = errors[i].getElementsByTagName('string').item(0).firstChild.data; var errorType = errors[i].getElementsByTagName('type').item(0).firstChild.data; var errorDescription = errors[i].getElementsByTagName('description').item(0).firstChild.data; var errorContext; if (errors[i].getElementsByTagName('precontext').item(0).firstChild != null) errorContext = errors[i].getElementsByTagName('precontext').item(0).firstChild.data; else errorContext = ""; /* create a hashtable with information about the error in the editor object, we will use this later to populate a popup menu with information and suggestions about the error */ if (this.ignore_strings[errorString] == undefined) { var suggestion = {}; suggestion["description"] = errorDescription; suggestion["suggestions"] = []; /* used to find suggestions when a highlighted error is clicked on */ suggestion["matcher"] = new RegExp('^' + errorString.replace(/\s+/, this._getSeparators()) + '$'); suggestion["context"] = errorContext; suggestion["string"] = errorString; suggestion["type"] = errorType; this.suggestions.push(suggestion); if (errors[i].getElementsByTagName('suggestions').item(0) != undefined) { var suggestions = errors[i].getElementsByTagName('suggestions').item(0).getElementsByTagName('option'); for (var j = 0; j < suggestions.length; j++) suggestion["suggestions"].push(suggestions[j].firstChild.data); } /* setup the more info url */ if (errors[i].getElementsByTagName('url').item(0) != undefined) { var errorUrl = errors[i].getElementsByTagName('url').item(0).firstChild.data; suggestion["moreinfo"] = errorUrl + '&theme=tinymce'; } if (types[errorDescription] == undefined) { if (errorType == "suggestion") enrichment.push({ word: errorString, pre: errorContext }); if (errorType == "grammar") grammarErrors.push({ word: errorString, pre: errorContext }); } if (errorType == "spelling" || errorDescription == "Homophone") spellingErrors.push({ word: errorString, pre: errorContext }); if (errorDescription == 'Cliches') suggestion["description"] = 'Clichés'; /* done here for backwards compatability with current user settings */ if (errorDescription == "Spelling") suggestion["description"] = this.getLang('menu_title_spelling', 'Spelling'); if (errorDescription == "Repeated Word") suggestion["description"] = this.getLang('menu_title_repeated_word', 'Repeated Word'); if (errorDescription == "Did you mean...") suggestion["description"] = this.getLang('menu_title_confused_word', 'Did you mean...'); } // end if ignore[errorString] == undefined } // end if } // end for loop var errorStruct; var ecount = spellingErrors.length + grammarErrors.length + enrichment.length; if (ecount > 0) errorStruct = this.buildErrorStructure(spellingErrors, enrichment, grammarErrors); else errorStruct = undefined; /* save some state in this object, for retrieving suggestions later */ return { errors: errorStruct, count: ecount, suggestions: this.suggestions }; }; AtDCore.prototype.findSuggestion = function(element) { var text = element.innerHTML; var context = ( this.getAttrib(element, 'pre') + "" ).replace(/[\\,!\\?\\."\s]/g, ''); if (this.getAttrib(element, 'pre') == undefined) { alert(element.innerHTML); } var errorDescription = undefined; var len = this.suggestions.length; for (var i = 0; i < len; i++) { var key = this.suggestions[i]["string"]; if ((context == "" || context == this.suggestions[i]["context"]) && this.suggestions[i]["matcher"].test(text)) { errorDescription = this.suggestions[i]; break; } } return errorDescription; }; /* * TokenIterator class */ function TokenIterator(tokens) { this.tokens = tokens; this.index = 0; this.count = 0; this.last = 0; }; TokenIterator.prototype.next = function() { var current = this.tokens[this.index]; this.count = this.last; this.last += current.length + 1; this.index++; /* strip single quotes from token, AtD does this when presenting errors */ if (current != "") { if (current[0] == "'") current = current.substring(1, current.length); if (current[current.length - 1] == "'") current = current.substring(0, current.length - 1); } return current; }; TokenIterator.prototype.hasNext = function() { return this.index < this.tokens.length; }; TokenIterator.prototype.hasNextN = function(n) { return (this.index + n) < this.tokens.length; }; TokenIterator.prototype.skip = function(m, n) { this.index += m; this.last += n; if (this.index < this.tokens.length) this.count = this.last - this.tokens[this.index].length; }; TokenIterator.prototype.getCount = function() { return this.count; }; TokenIterator.prototype.peek = function(n) { var peepers = new Array(); var end = this.index + n; for (var x = this.index; x < end; x++) peepers.push(this.tokens[x]); return peepers; }; /* * code to manage highlighting of errors */ AtDCore.prototype.markMyWords = function(container_nodes, errors) { var seps = new RegExp(this._getSeparators()); var nl = new Array(); var ecount = 0; /* track number of highlighted errors */ var parent = this; /* Collect all text nodes */ /* Our goal--ignore nodes that are already wrapped */ this._walk(container_nodes, function(n) { if (n.nodeType == 3 && !parent.isMarkedNode(n)) nl.push(n); }); /* walk through the relevant nodes */ var iterator; this.map(nl, function(n) { var v; if (n.nodeType == 3) { v = n.nodeValue; /* we don't want to mangle the HTML so use the actual encoded string */ var tokens = n.nodeValue.split(seps); /* split on the unencoded string so we get access to quotes as " */ var previous = ""; var doReplaces = []; iterator = new TokenIterator(tokens); while (iterator.hasNext()) { var token = iterator.next(); var current = errors['__' + token]; var defaults; if (current != undefined && current.pretoks != undefined) { defaults = current.defaults; current = current.pretoks['__' + previous]; var done = false; var prev, curr; prev = v.substr(0, iterator.getCount()); curr = v.substr(prev.length, v.length); var checkErrors = function(error) { if (error != undefined && !error.used && foundStrings['__' + error.string] == undefined && error.regexp.test(curr)) { var oldlen = curr.length; foundStrings['__' + error.string] = 1; doReplaces.push([error.regexp, '<span class="'+error.type+'" pre="'+previous+'">$&</span>']); error.used = true; done = true; } }; var foundStrings = {}; if (current != undefined) { previous = previous + ' '; parent.map(current, checkErrors); } if (!done) { previous = ''; parent.map(defaults, checkErrors); } } previous = token; } // end while /* do the actual replacements on this span */ if (doReplaces.length > 0) { newNode = n; for (var x = 0; x < doReplaces.length; x++) { var regexp = doReplaces[x][0], result = doReplaces[x][1]; /* it's assumed that this function is only being called on text nodes (nodeType == 3), the iterating is necessary because eventually the whole thing gets wrapped in an mceItemHidden span and from there it's necessary to handle each node individually. */ var bringTheHurt = function(node) { if (node.nodeType == 3) { ecount++; /* sometimes IE likes to ignore the space between two spans, solution is to insert a placeholder span with a non-breaking space. The markup removal code substitutes this span for a space later */ if (parent.isIE() && node.nodeValue.length > 0 && node.nodeValue.substr(0, 1) == ' ') return parent.create('<span class="mceItemHidden"> </span>' + node.nodeValue.substr(1, node.nodeValue.length - 1).replace(regexp, result), false); else return parent.create(node.nodeValue.replace(regexp, result), false); } else { var contents = parent.contents(node); for (var y = 0; y < contents.length; y++) { if (contents[y].nodeType == 3 && regexp.test(contents[y].nodeValue)) { var nnode; if (parent.isIE() && contents[y].nodeValue.length > 0 && contents[y].nodeValue.substr(0, 1) == ' ') nnode = parent.create('<span class="mceItemHidden"> </span>' + contents[y].nodeValue.substr(1, contents[y].nodeValue.length - 1).replace(regexp, result), true); else nnode = parent.create(contents[y].nodeValue.replace(regexp, result), true); parent.replaceWith(contents[y], nnode); parent.removeParent(nnode); ecount++; return node; /* we did a replacement so we can call it quits, errors only get used once */ } } return node; } }; newNode = bringTheHurt(newNode); } parent.replaceWith(n, newNode); } } }); return ecount; }; AtDCore.prototype._walk = function(elements, f) { var i; for (i = 0; i < elements.length; i++) { f.call(f, elements[i]); this._walk(this.contents(elements[i]), f); } }; AtDCore.prototype.removeWords = function(node, w) { var count = 0; var parent = this; this.map(this.findSpans(node).reverse(), function(n) { if (n && (parent.isMarkedNode(n) || parent.hasClass(n, 'mceItemHidden') || parent.isEmptySpan(n)) ) { if (n.innerHTML == ' ') { var nnode = document.createTextNode(' '); /* hax0r */ parent.replaceWith(n, nnode); } else if (!w || n.innerHTML == w) { parent.removeParent(n); count++; } } }); return count; }; AtDCore.prototype.isEmptySpan = function(node) { return (this.getAttrib(node, 'class') == "" && this.getAttrib(node, 'style') == "" && this.getAttrib(node, 'id') == "" && !this.hasClass(node, 'Apple-style-span') && this.getAttrib(node, 'mce_name') == ""); }; AtDCore.prototype.isMarkedNode = function(node) { return (this.hasClass(node, 'hiddenGrammarError') || this.hasClass(node, 'hiddenSpellError') || this.hasClass(node, 'hiddenSuggestion')); }; /* * Context Menu Helpers */ AtDCore.prototype.applySuggestion = function(element, suggestion) { if (suggestion == '(omit)') { this.remove(element); } else { var node = this.create(suggestion); this.replaceWith(element, node); this.removeParent(node); } }; /* * Check for an error */ AtDCore.prototype.hasErrorMessage = function(xmlr) { return (xmlr != undefined && xmlr.getElementsByTagName('message').item(0) != null); }; AtDCore.prototype.getErrorMessage = function(xmlr) { return xmlr.getElementsByTagName('message').item(0); }; /* this should always be an error, alas... not practical */ AtDCore.prototype.isIE = function() { return navigator.appName == 'Microsoft Internet Explorer'; };