Difference between revisions of "MediaWiki:JKeyEditor.js"
From Species-ID
Line 286: | Line 286: | ||
function jedtParsedDataCoupletMemory_CreateItemEntry(itemID, newItemID, uniqueKeyID, coupletID, createNewCoupletInMemory) { | function jedtParsedDataCoupletMemory_CreateItemEntry(itemID, newItemID, uniqueKeyID, coupletID, createNewCoupletInMemory) { | ||
− | var newItemData = {wasOrigin: false, wasEdited: true | + | var newItemData = {wasOrigin: false, wasEdited: true}; |
if (createNewCoupletInMemory) { | if (createNewCoupletInMemory) { | ||
jedtParsedPageData[uniqueKeyID].coupletMemory[coupletID] = {}; // clean | jedtParsedPageData[uniqueKeyID].coupletMemory[coupletID] = {}; // clean | ||
Line 867: | Line 867: | ||
if (coupletMemory[coupletID][itemID]) { // filter unwanted properties from the prototype | if (coupletMemory[coupletID][itemID]) { // filter unwanted properties from the prototype | ||
itemData = coupletMemory[coupletID][itemID]; | itemData = coupletMemory[coupletID][itemID]; | ||
− | parsedDataStructure = (itemData.wasOrigin) ? jedtParsedPageData[itemID] : jedtParsedPageData[ | + | parsedDataStructure = (itemData.wasOrigin) ? jedtParsedPageData[itemID] : jedtParsedPageData[jedtParsedDataCoupletMemory_ExtractOriginItemID(itemID)]; |
if (itemData.wasEdited) { | if (itemData.wasEdited) { | ||
// get values from inputs | // get values from inputs |
Revision as of 11:09, 2 December 2009
/* Copyright (c) 2009, Stephan Opitz, JKI Berlin Dahlem
This program is free software; you can redistribute it and/or modify it under the terms of the EUPL v.1.1 or (at your option) the GNU General Public License as published by the Free Software Foundation; either GPL v.3 or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License (http://www.gnu.org/licenses/) for more details. */
/*global $j, wgContentLanguage, wgPageName, wgScript, wgScriptPath, wgServer, wgUserName, alert, console, document, Image, location, setTimeout, window, JKeyException, jkeyExceptionAlert */
//// JKey editor global vars ////
"use strict";
var localTstMode = false;
var jedtI18n, jedtImgs; // resrc holders
var pastelColors = ["#FFFDD8", "#FFE9CC", "#FFE4D9", "#FFDCDF", "#FFDCF8", "#DFE1F6", "#D8E7FF", "#D8F5FF", "#D8FFE1", "#ECFFD8"];
var jkeyParser; // parser class
var jedtPageCharArray; // holds complete content (need for content between)
var jedtParsedPageData; // parsed tpl & child data
var jedtHtmlEditTpls = {}; // cache for editor tpls
var jedtEditFormVars = {}; // cache for saving
/*
* Description: Get resource string (text, image URLs) for a given language, based on a string-key
* If, for a key, resource is missing in a given language, the resource for "en" will be returned, if this is missing as well an error message.
* resrcKey: key for the resource (string)
*/
function jedtInitResourceDict() {
return {
en: {
edtInstantSave: "Instant save",
edtSave: "Save",
edtRightsFault: "No edit rights!",
edtActionEditTitle: "Edit item(s)",
edtActionRemoveTitle: "Remove item",
edtActionMoveUpTitle: "Move item up",
edtActionMoveDownTitle: "Move item down",
edtActionAddNewTitle: "Add new item below",
edtActionRemoveFault: "Two decision alternatives are minimum required!",
edtCoupletDescription: "Couplet",
edtSaving: "Please wait, saving ...",
edtSavingFault: "Stopped saving, because no couplets were changed into to edit mode!",
edtWpSummary: "Saved using JKey Editor",
jkeyAjaxSuccessFault : "Response from server was empty!",
edtSysExNfo1: "No coupletID can be extracted!",
edtSysExNfo2: "No itemID found in coupletMemory!",
edtParsExNfo1: "No defined ID was found. Check this!",
edtParsExNfo2A: "Key before key with ID: ",
edtParsExNfo2B: " was not finished by a 'Key End' template!",
edtParsExNfo3: "Couplet definition is not parseable!",
edtParsExReas1: "Empty field",
edtParsExReas2: "Structure not valid!",
edtParsExReas3: "No valid id found!",
edtInitNfoEx: "Extraction of coupletID failed",
edtTplExNfo1: "No jedtCoupletBacklink as input field found!",
edtTplExNfo2: "No jedtCoupletAltID as input field found!",
edtTplExNfo3: "No jedtParseLeadID as input field found!",
edtNiExNfoA: "toggleMode: ",
edtNiExNfoB: " is not available!"
},
de: {
edtInstantSave: "Zwischenspeichern",
edtSave: "Speichern",
edtRightsFault: "Keine Rechte zum Bearbeiten!",
edtActionEditTitle: "Bearbeite Entscheidungspaar(e)",
edtActionRemoveTitle: "Lösche Element",
edtActionMoveUpTitle: "Bewege Element nach oben",
edtActionMoveDownTitle: "Bewege Element nach unten",
edtActionAddNewTitle: "Füge neues Element darunter hinzu",
edtActionRemoveFault: "Zwei Entscheidungsalternativen werden mindestens benötigt!",
edtCoupletDescription: "Entscheidungspaar",
edtSaving: "Bitte warten, es wird gespeichert ...",
edtSavingFault: "Speichern gestoppt, da keine Entscheidungspaare in den Bearbeiten-Modus geändert wurden!",
edtWpSummary: "Gepeichert durch den JKey Editor"
}
};
}
function jedtResource(resrcKey) {
if (!jedtI18n) {
jedtI18n = jedtInitResourceDict();
}
var lang = wgContentLanguage.split("-")[0]; // language: "pt-BR", "de-formal", etc.
return (jedtI18n[lang] && jedtI18n[lang][resrcKey] ?
jedtI18n[lang][resrcKey] :
(jedtI18n.en[resrcKey]) ? jedtI18n.en[resrcKey] : "MISSING RESOURCE");
}
function jedtImgPreloader(resrcKey) {
var imgUrls = {
edtIconActionEdit: "http://upload.wikimedia.org/wikipedia/commons/thumb/8/8f/View-so_edit_simple.svg/25px-View-so_edit_simple.svg.png",
edtIconActionRemove: "http://upload.wikimedia.org/wikipedia/commons/thumb/0/06/View-so_remove_simple.svg/20px-View-so_remove_simple.svg.png",
edtIconActionMoveUp: "http://upload.wikimedia.org/wikipedia/commons/thumb/b/b5/View-so_move_up_simple.svg/20px-View-so_move_up_simple.svg.png",
edtIconActionMoveDown: "http://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/View-so_move_down_simple.svg/20px-View-so_move_down_simple.svg.png",
edtIconActionAddNew: "http://upload.wikimedia.org/wikipedia/commons/thumb/5/52/View-so_add_new_simple.svg/20px-View-so_add_new_simple.svg.png",
edtIconLoading: "http://upload.wikimedia.org/wikipedia/commons/4/42/Loading.gif"
}, key, newImg;
jedtImgs = {}; // init holder
for (key in imgUrls) {
if (imgUrls[key]) { // filter unwanted properties from the prototype
newImg = new Image();
jedtImgs[key] = $j(newImg).attr({src: imgUrls[key]});
}
}
}
function jedtImgResource(resrcKey) {
return jedtImgs[resrcKey].clone();
}
//// JKey common ////
function jkeyAjax(callingScript, parameters, typeGet, async, successFct, errorFct) {
var respObj = $j.ajax({ // execute ajax call
url: callingScript,
data: parameters,
type: (typeGet) ? "GET" : "POST",
async: async,
success: successFct,
error: errorFct
});
if (!async) { // return result
return (parameters.format && (parameters.format === "xml")) ? respObj.responseXML : respObj.responseText;
}
}
function jkeyAjaxSuccess(content) {
if (!content) {
throw (new JKeyException("ConnectionException", {info: jedtResource("jkeyAjaxSuccessFault")}));
}
}
function jkeyAjaxError(xhr, ajaxOptions, thrownError) {
throw (new JKeyException("ConnectionException", {status: xhr.status, statusText: xhr.statusText, thrownError: thrownError}));
}
function jkeyCoupletAsCollection(firstDtRow) {
var startIdx, endIdx, sibblingRow, gtFilter, ltFilter,
parentTableRows = $j(firstDtRow.closest("table").get(0).rows);
// starIdx
startIdx = parentTableRows.index(firstDtRow.prevAll("tr:not(.dt-hspacer,.dt-subheading):first").next("tr"));
// endIdx
sibblingRow = firstDtRow;
while (sibblingRow.length) {
sibblingRow = sibblingRow.next("tr");
if (sibblingRow.find("td.actionCell:first").length) { // rowHasActionCell
sibblingRow = sibblingRow.prevAll("tr:not(.dt-hspacer,.dt-subheading):first"); // end of couplet
break;
}
}
endIdx = parentTableRows.index(sibblingRow.get(0));
// filter
gtFilter = (startIdx > 0) ? ":gt(" + (startIdx - 1) + ")" : "";
ltFilter = (endIdx !== -1) ? (":lt(" + (endIdx - ((startIdx === -1) ? 0 : startIdx) + 1) + ")") : ""; // lt with gt means here count/number of next
return parentTableRows.filter("tr" + gtFilter + ltFilter);
}
function jkeyExtractCombinedCoupletLeadID(combinedCoupletLeadID) {
var retData = {coupletID: "", alt: "", backlink: ""},
regExpResult = /^(\d+)(.*)/.exec(combinedCoupletLeadID); // extract "coupletID" & "alt" - .* because of special chars
if (regExpResult) {
retData.coupletID = regExpResult[1];
retData.alt = $j.trim(regExpResult[2]);
// extract "backlink", which can be in "alt"
regExpResult = /.*\((\d+)\)/.exec(retData.alt); // - .* because of special chars
if (regExpResult) {
retData.backlink = $j.trim(regExpResult[1]);
retData.alt = $j.trim(retData.alt.replace("(" + retData.backlink + ")", ""));
}
}
else {
throw (new JKeyException("SystemException", {info: jedtResource("edtSysExNfo1")}));
}
return retData;
}
function jkeyScrollToElement(elem) {
function getElemOffset(elem) {
var left = !!elem.offsetLeft ? elem.offsetLeft : 0,
top = !!elem.offsetTop ? elem.offsetTop : 0;
while ((elem = elem.offsetParent)) {
left += !!elem.offsetLeft ? elem.offsetLeft : 0;
top += !!elem.offsetTop ? elem.offsetTop : 0;
}
return {x: left, y: top};
}
var pos = getElemOffset(elem);
window.scrollTo(pos.x, pos.y);
}
//// jedtBase ////
function jedtBase_CountKeys(base) {
// some objs have problems with length (imitate it)
var counter = 0, key;
for (key in base) {
if (base[key]) { // filter unwanted properties from the prototype
counter += 1;
}
}
return counter;
}
function jedtBase_CreateNewAfter(base, targetKey, newInsertKey, newInsertValue) {
var baseCounter = 0, siblingOriginPos = 0, // parameters for wrong tpl definition case
newBase = {}, afterOriginAction = false, // reorganize parsed data
key;
// iterate to find correct position & insert it there
for (key in base) {
if (base[key]) { // filter unwanted properties from the prototype
baseCounter += 1;
// handle insert process of new sibling
if (afterOriginAction) {
newBase[newInsertKey] = newInsertValue;
afterOriginAction = false; // no more needed
}
// default insert itself
if (!newBase[key]) { // add if not exists (no overwriting of afterOriginAction item can happen)
newBase[key] = base[key];
}
// check current if already was target parent
if (key === targetKey) {
afterOriginAction = true;
siblingOriginPos = baseCounter;
}
}
}
// handle special case - targetKey was last key in base (its like an simple appending)
if (siblingOriginPos === baseCounter) {
newBase[newInsertKey] = newInsertValue;
}
// return new
return newBase;
}
function jedtBase_MoveKeyOnceUpOrDown(base, targetKey, moveUpOrDown) {
// a key within an object is moved
var keysCounter = 0, keyPosition = 0, // 0 is also a position
newKeysCounter = 0, wasAdded = false, newBase = {},
key;
for (key in base) {
if (base[key]) { // filter unwanted properties from the prototype
if (key === targetKey) {
keyPosition = keysCounter;
}
keysCounter += 1;
}
}
// special cases: already an edge region position
if (moveUpOrDown && (keyPosition === 0)) { // move up, but already first pos
return base;
}
if (!moveUpOrDown && (keyPosition === (keysCounter - 1))) { // move down, but already last pos
return base;
}
// perform move
for (key in base) {
if (base[key]) { // filter unwanted properties from the prototype
// add specific key
if (newKeysCounter === (moveUpOrDown ? (keyPosition - 1) : (keyPosition + 1))) {
wasAdded = true;
newBase[targetKey] = base[targetKey];
}
// add all other
if (key !== targetKey) {
newKeysCounter += 1;
newBase[key] = base[key];
}
}
}
// special case - moved to last item
if (!wasAdded) {
newBase[targetKey] = base[targetKey];
}
return newBase;
}
function jedtBase_RemoveKey(base, key) {
try {
delete base[key];
} catch (err) {}
}
//// jedtParsedDataCoupletMemory ////
function jedtParsedDataCoupletMemory_ExtractOriginItemID(itemID) {
var regExpResult = /(\d*)n(\d+)/.exec(itemID); // check if originItemID is already a combined id
return !regExpResult ? itemID : regExpResult[1];
}
function jedtParsedDataCoupletMemory_CreateItemEntry(itemID, newItemID, uniqueKeyID, coupletID, createNewCoupletInMemory) {
var newItemData = {wasOrigin: false, wasEdited: true};
if (createNewCoupletInMemory) {
jedtParsedPageData[uniqueKeyID].coupletMemory[coupletID] = {}; // clean
jedtParsedPageData[uniqueKeyID].coupletMemory[coupletID][newItemID] = newItemData;
}
else {
jedtParsedPageData[uniqueKeyID].coupletMemory[coupletID] = jedtBase_CreateNewAfter(jedtParsedPageData[uniqueKeyID].coupletMemory[coupletID], itemID, newItemID, newItemData);
}
}
function jedtParsedDataCoupletMemory_CalculateNewItemID(uniqueKeyID, originID) {
var regExpResult, regExpSearch = /(\d*)n(\d+)/,
basePartID = originID, sibblingPartID = 1,
coupletMemory, newSibblingPartID, coupletID, itemID;
// check if originID is already a combined id & extract parts
regExpResult = regExpSearch.exec(originID);
if (regExpResult) {
basePartID = parseInt(regExpResult[1], 10);
sibblingPartID = parseInt(regExpResult[2], 10);
}
// extract highest sibblingPartID
coupletMemory = jedtParsedPageData[uniqueKeyID].coupletMemory;
for (coupletID in coupletMemory) {
if (coupletMemory[coupletID]) { // filter unwanted properties from the prototype
for (itemID in coupletMemory[coupletID]) {
if (coupletMemory[coupletID][itemID]) { // filter unwanted properties from the prototype
// extract highest belonging sibling id
regExpResult = regExpSearch.exec(itemID);
if (regExpResult && (parseInt(regExpResult[1], 10) === basePartID)) {
newSibblingPartID = parseInt(regExpResult[2], 10);
if (newSibblingPartID >= sibblingPartID) {
sibblingPartID = (newSibblingPartID + 1); // set to next higher
}
}
}
}
}
}
// return new id
return basePartID + "n" + sibblingPartID;
}
function jedtParsedDataCoupletMemory_FindItemID(uniqueKeyID, itemID) {
var retObj = {coupletID: "", itemsCounter: 0},
coupletMemory = jedtParsedPageData[uniqueKeyID].coupletMemory,
coupletIDKey, coupletStructure, itemsCounter, hasFound, itemIDKey;
for (coupletIDKey in coupletMemory) {
if (coupletMemory[coupletIDKey]) { // filter unwanted properties from the prototype
coupletStructure = coupletMemory[coupletIDKey];
// init loop variables
itemsCounter = 0;
hasFound = false;
// look for itemID
for (itemIDKey in coupletStructure) {
if (coupletStructure[itemIDKey]) { // filter unwanted properties from the prototype
if (itemIDKey === itemID) { // no break; to get correct itemsCounter
hasFound = true;
}
itemsCounter += 1;
}
}
if (hasFound) {
retObj.coupletID = coupletIDKey; // key is the ID
retObj.itemsCounter = itemsCounter;
return retObj;
}
}
}
return retObj;
}
function jedtParsedDataCoupletMemory_GenerateNewCoupletID(uniqueKeyID, otherCoupletID) {
// get collection which holds all couplet parent ids (defined in "Key Start" parsed tpl data)
var coupletMemory = jedtParsedPageData[uniqueKeyID].coupletMemory,
newCoupletID = -1, coupletID, currCoupletID;
for (coupletID in coupletMemory) {
if (coupletMemory[coupletID]) { // filter unwanted properties from the prototype
currCoupletID = parseInt(coupletID, 10);
if (currCoupletID > newCoupletID) {
newCoupletID = currCoupletID;
}
}
}
// next highest
newCoupletID += 1;
// add that further addings are possible
if (!coupletMemory[newCoupletID]) { // lazy init
jedtParsedPageData[uniqueKeyID].coupletMemory = jedtBase_CreateNewAfter(coupletMemory, otherCoupletID, newCoupletID, {});
}
return newCoupletID;
}
function jedtParsedDataCoupletMemory_RemoveItemID(uniqueKeyID, itemID) {
var foundItemData = jedtParsedDataCoupletMemory_FindItemID(uniqueKeyID, itemID);
// remove itemID & parent (if only one entry)
if (foundItemData.coupletID.length) {
jedtBase_RemoveKey(jedtParsedPageData[uniqueKeyID].coupletMemory[foundItemData.coupletID], itemID);
if (foundItemData.itemsCounter === 1) { // remove also couplet - was last decision
jedtBase_RemoveKey(jedtParsedPageData[uniqueKeyID].coupletMemory, foundItemData.coupletID);
}
}
else {
throw (new JKeyException("SystemException", {info: jedtResource("edtSysExNfo2")}));
}
}
//// jedtParsedData ////
function jedtParsedData_ExtractIDFromChilds(childData) {
var namedID = "", firstUnnamed = "", // look for id (prio has field 'id' - alternative try first unnamed)
fieldKey, currField, fieldsConcated;
for (fieldKey in childData) {
if (childData[fieldKey]) { // filter unwanted properties from the prototype
currField = childData[fieldKey];
if (currField.name === 1) {
firstUnnamed = currField.content;
}
if ((typeof(currField.name) === 'string') && (currField.name.toLowerCase() === "id")) {
namedID = currField.content;
break;
}
}
}
if ((namedID.length === 0) && (firstUnnamed.length === 0)) { // nothing found
fieldsConcated = "\n{{... ";
for (fieldKey in childData) {
if (childData[fieldKey]) { // filter unwanted properties from the prototype
currField = childData[fieldKey];
fieldsConcated += currField.name + "=" + currField.content + "\n" + currField.closingType + " ";
}
}
throw (new JKeyException("ParserException", {info: jedtResource("edtParsExNfo1"), position: fieldsConcated}));
}
return (namedID.length > 0) ? namedID : firstUnnamed;
}
function jedtParsedData_InitCoupletMemoryForKey(keyDiv) {
// get all keys with this id from page
var keyDivs = $j("#" + keyDiv.id),
keyPosInData = 0, keyPosInDOM = 1, // default the should be only one key with the id
withinAnyKey = false, withinCorrectKey = false, finishInit = false,
keyStartRef, parseDataKey, currTpl, currTplName, foundKeyStart, currKeyID,
unextractedCoupletID, extracted;
if (keyDivs.length > 1) { // more keys with same id
keyDivs.each(function () {
if (this !== keyDiv) {
keyPosInDOM += 1;
}
});
}
// navigate through parsed data & create coupletMemory
for (parseDataKey in jedtParsedPageData) {
if (jedtParsedPageData[parseDataKey] && (parseDataKey !== 'tplNames') && (jedtParsedPageData[parseDataKey].type === "{{")) { // is a parsed tpl
currTpl = jedtParsedPageData[parseDataKey];
currTplName = currTpl.name;
foundKeyStart = false; // ignore "Key Start" adding to coupletMemory
// check key start & end to find correct key
if (currTplName === "Key Start") {
currKeyID = jedtParsedData_ExtractIDFromChilds(currTpl.fields);
if (withinAnyKey) { // new key starts, even though old hasn't finished
throw (new JKeyException("ParserException", {info: jedtResource("edtParsExNfo2A") + currKeyID + jedtResource("edtParsExNfo2B")}));
}
// set flag
withinAnyKey = true;
// key is same as from current clicked player
if (currKeyID === keyDiv.id) {
keyPosInData += 1; // found a key with this id
}
// found correct key
if (keyPosInDOM === keyPosInData) {
foundKeyStart = true;
withinCorrectKey = true;
currTpl.wasEdited = true; // set action flag
currTpl.domRef = keyDiv;
keyStartRef = currTpl;
$j.data(keyDiv, "keyData", {uniqueKeyID: parseDataKey});
}
}
else if (currTplName === "Key End") {
withinAnyKey = false; // set flag back
if (withinCorrectKey) { // handled already the right key data
finishInit = true;
}
}
// add to return object
if (withinCorrectKey && !foundKeyStart && !finishInit) {
if (!keyStartRef.coupletMemory) {
keyStartRef.coupletMemory = {};
}
unextractedCoupletID = jedtParsedData_ExtractIDFromChilds(currTpl.fields);
extracted = jkeyExtractCombinedCoupletLeadID(unextractedCoupletID);
if (extracted.coupletID.length === 0) {
throw (new JKeyException("InitException", {info: jedtResource("edtInitNfoEx")}));
}
if (!keyStartRef.coupletMemory[extracted.coupletID]) {
keyStartRef.coupletMemory[extracted.coupletID] = {};
}
keyStartRef.coupletMemory[extracted.coupletID][parseDataKey] = {wasOrigin: true, wasEdited: false};
}
// handled already the right key data
if (finishInit) {
break;
}
}
}
}
//// jedtTemplate ////
function jedtTemplate_LegendInputs() { // TODO: tdLeadextras is to specific (but with it the "Lead" tpl looks better)
var splittedID = this.id.split("_"),
action = splittedID[splittedID.length - 1],
parent = $j(this).closest("fieldset"),
tdLeadextras, collection, isOtherOff, isCurrentOff;
// perform action
switch (action) {
case ("moreAll"):
if (this.checked) {
// disable & activate checkbox for neigbhours
$j(this).nextAll("input").attr("checked", true).attr("disabled", "disabled");
// show all affected elements
parent.find("tr.moreSubheading, tr.moreResultExtras").show();
tdLeadextras = parent.find("td.leadextras");
tdLeadextras.show();
tdLeadextras.find("table.moreText,table.moreImages").show();
} else {
// enable & reset checkbox for neigbhours
$j(this).nextAll("input").attr("checked", false).attr("disabled", false);
// hide all affected elements
parent.find("tr.moreSubheading, tr.moreResultExtras").hide();
tdLeadextras = parent.find("td.leadextras");
tdLeadextras.hide();
tdLeadextras.find("table.moreText,table.moreImages").hide();
}
break;
case ("moreResultExtras"):
case ("moreSubheading"):
collection = parent.find("tr." + action);
if (collection.get(0).style.display === "none") { // toggle() has problems in IE
collection.show();
}
else {
collection.hide();
}
break;
case ("moreText"):
case ("moreImages"):
tdLeadextras = parent.find("td.leadextras"); // has to noted because of style
// get other status
isOtherOff = (tdLeadextras.find("table." + ((action === "moreText") ? "moreImages" : "moreText")).get(0).style.display === "none");
// toggle current
tdLeadextras.find("table." + action).toggle();
isCurrentOff = (tdLeadextras.find("table." + action).get(0).style.display === "none");
// switch parent-td display
if (isOtherOff && isCurrentOff) {
tdLeadextras.hide();
} else {
tdLeadextras.show();
}
break;
}
}
function jedtTemplate_AddItemRowID(tpl, itemRowID) {
tpl.find("[id],[for]").each(function () {
var jThis = $j(this);
if (this.id.length !== 0) {
jThis.attr("id", itemRowID + "_" + this.id);
jThis.attr("name", this.id);
return;
}
jThis.attr("for", itemRowID + "_" + jThis.attr("for"));
});
}
function jedtTemplate_AddLegendInputAction(tpl) {
if (tpl.hasClass("jedtHandleLegendInputs")) {
tpl.find("legend input").click(jedtTemplate_LegendInputs);
}
}
function jedtTemplate_FillParseLeadID(currTpl) {
var parseLeadIDElem = currTpl.find(".jedtParseLeadID").get(0),
extracted, parseCoupletBacklinkElem, parseCoupletAltElem;
if (parseLeadIDElem) { // handle jedtParseLeadID
extracted = jkeyExtractCombinedCoupletLeadID(parseLeadIDElem.value);
parseLeadIDElem.value = extracted.coupletID;
// set jedtCoupletBacklink (also can be empty)
parseCoupletBacklinkElem = currTpl.find(".jedtCoupletBacklink").get(0);
if (parseCoupletBacklinkElem) {
parseCoupletBacklinkElem.value = extracted.backlink;
} else {
throw (new JKeyException("TemplateException", {info: jedtResource("edtTplExNfo1")}));
}
// set jedtCoupletAltID (also can be empty)
parseCoupletAltElem = currTpl.find(".jedtCoupletAltID").get(0);
if (parseCoupletAltElem) {
parseCoupletAltElem.value = extracted.alt;
} else {
throw (new JKeyException("TemplateException", {info: jedtResource("edtTplExNfo2")}));
}
}
else {
throw (new JKeyException("TemplateException", {info: jedtResource("edtTplExNfo3")}));
}
}
function jedtTemplate_FillValues(tpl, itemRowID) {
var clonedTpl = jedtHtmlEditTpls[tpl.name].clone().closest("fieldset"),
unknownFieldsPointer = clonedTpl.find("#unknownFields"),
unknownFieldsCounter = 0,
fieldKey, currField, searchID, currElem;
// change holder for unknownField
unknownFieldsPointer.append($j("<table/>").addClass("unknownFields"));
unknownFieldsPointer = unknownFieldsPointer.find("table"); // set new
// fill tpl
for (fieldKey in tpl.fields) {
if (tpl.fields[fieldKey]) { // filter unwanted properties from the prototype
currField = tpl.fields[fieldKey];
searchID = currField.isUnnamedField ? ("unnamed_" + currField.name) : currField.name;
// looks for element in cloned to fill it
currElem = clonedTpl.find("#" + searchID.replace(' ', '_'));
if (currElem.length === 1) { // found
currElem.attr({value: currField.content});
} else { // append to unknownFields
unknownFieldsPointer.append($j("<tr/>")
.append($j("<td/>").html(searchID))
.append($j("<td/>").append($j("<input/>").attr({type: "text", id: searchID.replace(' ', '_'), size: "120", value: currField.content})))
);
unknownFieldsCounter += 1;
}
}
}
// show unknown fields area
if (unknownFieldsCounter > 0) {
$j(unknownFieldsPointer).closest("div").show();
}
// change all "id" & "for" & add itemRowID before
jedtTemplate_AddItemRowID(clonedTpl, itemRowID);
// add function for clicking the inputs
jedtTemplate_AddLegendInputAction(clonedTpl);
return clonedTpl;
}
//// jedtContainer ////
function jedtContainer_CreateHtml(coupletID, coupletRowID, inEdit, colspanCells) {
return $j("<tr class='edtCouplet' id=" + coupletRowID + " />")
.append($j("<td align='right' />")
.addClass("actionCell")
.append(jedtActionCell_CreatePrimary(inEdit)))
.append($j("<td class='actionContent' " + ((colspanCells > 1) ? ("colspan='" + colspanCells + "'") : "") + "/>")
.append($j("<fieldset />")
.addClass("jedtFieldset")
.append($j("<legend />")
.append("<b>" + jedtResource("edtCoupletDescription") + " " + coupletID + "</b>")
)));
}
function jedtContainer_CreateItemRow(id, data, unknownTplMode, addMaxWidth, color) {
if (!unknownTplMode) {
data.find("td.actionCell").append(jedtActionCell_CreateSecondary());
data.css(color ? {backgroundColor: color} : {});
}
return $j("<tr/>").addClass("edtItem").attr(addMaxWidth ? {id: id, width: "100%"} : {id: id}).append($j("<td/>").append(data));
}
function jedtContainer_CreateItemRowForUnknownTpl(tplName, tplContent) {
return $j("<fieldset/>")
.addClass("jedtFieldset")
.append($j("<legend/>").append("<b>" + tplName + "</b>"))
.append($j("<table/>")
.append($j("<tr/>")
.append($j("<td/>").css({width: "100%"}).append($j("<textarea rows=\"5\" cols=\"50\" />").css({width: "99%"}).attr({value: tplContent})))
.append($j("<td/>").addClass("actionCell"))
)
);
}
function jedtContainer_CreateItemRowID(keyID, uniqueKeyID, itemIDOrCoupletID, belonging) {
return "jkey_" + keyID + "_edt_uqID" + uniqueKeyID + "_" + belonging + itemIDOrCoupletID;
}
function jedtContainer_CreateItemsContainerHtml(itemRowID) {
return $j("<table/>").addClass("coupletItems")
.attr({width: "100%", cellspacing: "0", cellpadding: "0", id: itemRowID});
}
function jedtContainer_CreateItemsContainerContent(keyDiv, coupletID) {
var uniqueKeyID = $j.data(keyDiv, "keyData").uniqueKeyID,
itemsContainer = jedtContainer_CreateItemsContainerHtml(jedtContainer_CreateItemRowID(keyDiv.id, uniqueKeyID, coupletID, "coupletItems")),
coupletInMemory = jedtParsedPageData[uniqueKeyID].coupletMemory[coupletID],
unknownTplMode = false, backgroundColorCounter = 0, data,
itemID, currTpl, itemRowID, color;
// add all children in keyData - add them to specific holder depending on mode
for (itemID in coupletInMemory) {
if (coupletInMemory[itemID]) { // filter unwanted properties from the prototype
currTpl = jedtParsedPageData[itemID];
itemRowID = jedtContainer_CreateItemRowID(keyDiv.id, uniqueKeyID, itemID, "itemID");
// get editor tpl & fill with current values
if (jedtHtmlEditTpls[currTpl.name]) { // tpl exists
data = jedtTemplate_FillValues(currTpl, itemRowID);
jedtTemplate_FillParseLeadID(data);
} else { // tpl does not exists - create unknown fieldset with legend, textarea & actionCell
unknownTplMode = (jedtBase_CountKeys(coupletInMemory) === 1);
data = jedtContainer_CreateItemRowForUnknownTpl(currTpl.name, jkeyParser.buildString(jedtPageCharArray, currTpl.startIndex, jkeyParser.indexAfterToken(currTpl.closingType, currTpl.endIndex)));
}
// choose color & append to container
color = pastelColors[backgroundColorCounter];
backgroundColorCounter = (backgroundColorCounter === (pastelColors.length - 1)) ? 0 : (backgroundColorCounter + 1);
itemsContainer.append(jedtContainer_CreateItemRow(itemRowID, data, unknownTplMode, false, color));
}
}
return itemsContainer;
}
function jedtContainer_ItemizeRowID(itemRowID) {
var regExpResult = /jkey_(\w+)_edt_uqID(\w+)_(itemID|couplet|coupletItems)(\w+)/.exec(itemRowID);
return (regExpResult[3] === "itemID") ?
{keyID: regExpResult[1], uniqueKeyID: regExpResult[2], itemID: regExpResult[4]} :
{keyID: regExpResult[1], uniqueKeyID: regExpResult[2], coupletID: regExpResult[4]};
}
//// jedtSerialize ////
function jedtSerialize_UnknownEdtTpl(inputValue) {
var contentCharArray = inputValue.split(''),
parsedTpl = null, countedKeys, extracted;
// is empty
if (contentCharArray.length === 0) {
throw (new JKeyException("ParserException", {info: jedtResource("edtParsExNfo3"), reason: jedtResource("edtParsExReas1")}));
}
// is it parseable
try {
parsedTpl = jkeyParser.initialize(contentCharArray);
}
catch (err) {
throw (new JKeyException("ParserException", {info: jedtResource("edtParsExNfo3") + "\n", expectedToke: err.variables.expectedToken + "\n", contentBeforeErrorPosition: err.variables.contentBeforeErrorPosition + "\n", contentAfterErrorPosition: err.variables.contentAfterErrorPosition, content: inputValue}));
}
// is parsed result only an empty obj
if (parsedTpl["0"].fields) {
countedKeys = jedtBase_CountKeys(parsedTpl["0"].fields);
if (countedKeys === 0) {
throw (new JKeyException("ParserException", {info: jedtResource("edtParsExNfo3"), reason: jedtResource("edtParsExReas2"), content: inputValue}));
}
} else {
throw (new JKeyException("ParserException", {info: jedtResource("edtParsExNfo3"), reason: jedtResource("edtParsExReas2"), content: inputValue}));
}
// has it a parseable id
try {
extracted = jkeyExtractCombinedCoupletLeadID(jedtParsedData_ExtractIDFromChilds(parsedTpl["0"].fields));
}
catch (err2) {
throw (new JKeyException("ParserException", {info: jedtResource("edtParsExNfo3"), reason: jedtResource("edtParsExReas3"), content: inputValue}));
}
if (extracted.coupletID.length === 0) {
throw (new JKeyException("ParserException", {info: jedtResource("edtParsExNfo3"), reason: jedtResource("edtParsExReas3"), content: inputValue}));
}
// if all valid add to new parse data
return inputValue;
}
function jedtSerialize_KnownEdtTpl(inputs, itemRowID) {
var fields = {unnamed: {}, named: {}},
inputsLength = inputs.length,
i, currInput, tagName, validInput, name, contentCharArray, parsedTpl, key, currContent,
regExpResult, origMultipleFieldFirstPart = "", multipleFieldMiddlePartContent, multipleFieldLastPartContent,
multipleFieldKey = "", checkID = "", unnamed = "", named = "";
for (i = 0; i < inputsLength; i += 1) { // not each - is slower
currInput = $j(inputs.get(i));
tagName = currInput.attr("tagName").toLowerCase();
// check if correct input
validInput = false;
if (((tagName === "input") && (currInput.attr("type") === "text")) || (tagName === "textarea")) {
validInput = true;
}
// check field
if (validInput) {
// extract field name & content
name = currInput.attr("id").replace(itemRowID + "_", "");
contentCharArray = currInput.attr("value").split('');
// check content is valid (parse like page to find missing closing types)
parsedTpl = null;
try {
parsedTpl = jkeyParser.initialize(contentCharArray);
} catch (err) {
throw (new JKeyException("ParserException", {info: jedtResource("edtParsExNfo3") + "\n", expectedToken: err.variables.expectedToken + "\n", contentBeforeErrorPosition: err.variables.contentBeforeErrorPosition + "\n", contentAfterErrorPosition: err.variables.contentAfterErrorPosition}));
}
// sort field
if (name.search(/unnamed_/) !== -1) {
fields.unnamed[name.replace("unnamed_", "")] = {content: currInput.attr("value")};
} else {
fields.named[name] = currInput.attr("value");
}
}
}
// loop through fields & find unamed_x with b || c
for (key in fields.unnamed) {
if (!fields.unnamed[key].alreadyExtracted) { // not handled yet
regExpResult = /(\d*)(b|c)?/.exec(key);
if (regExpResult[2] && (regExpResult[2].length > 0)) {
origMultipleFieldFirstPart = fields.unnamed[regExpResult[1]].content;
multipleFieldKey = regExpResult[1];
// concate fields
multipleFieldMiddlePartContent = fields.unnamed[regExpResult[1] + "b"].content;
multipleFieldLastPartContent = fields.unnamed[regExpResult[1] + "c"].content;
fields.unnamed[regExpResult[1]].content = fields.unnamed[regExpResult[1]].content +
((multipleFieldMiddlePartContent.search(/'|\*|\"|\^|\`|\°|\´|\ˆ|\ˇ|\ˉ|\˘|\˙|\˚|\˜ |\‘|\’|\“|\”|[a-z]+/) !== -1) ? " " : "") +
multipleFieldMiddlePartContent + ((multipleFieldLastPartContent.length !== 0) ? " (" + multipleFieldLastPartContent + ")" : "");
fields.unnamed[regExpResult[1]].alreadyExtracted = true;
fields.unnamed[regExpResult[1] + "b"].alreadyExtracted = true;
fields.unnamed[regExpResult[1] + "c"].alreadyExtracted = true;
}
}
}
// remove b & c if exists
if (multipleFieldKey.length !== 0) {
jedtBase_RemoveKey(fields.unnamed, multipleFieldKey + "b");
jedtBase_RemoveKey(fields.unnamed, multipleFieldKey + "c");
}
// check if a field with id exists or in unnamed (& check if valid)
if (fields.named.id) {
checkID = fields.named.id;
}
if (fields.unnamed[multipleFieldKey]) {
checkID = ((origMultipleFieldFirstPart.length !== 0) ? origMultipleFieldFirstPart : ((fields.unnamed["1"]) ? fields.unnamed["1"].content : "")); // last chance try content "1"
}
if (jkeyExtractCombinedCoupletLeadID(checkID).coupletID.length === 0) {
throw (new JKeyException("ParserException", {info: jedtResource("edtParsExNfo3"), reason: jedtResource("edtParsExReas3")}));
}
// concatenate fields
for (key in fields.unnamed) {
if (fields.unnamed[key]) { // filter unwanted properties from the prototype
currContent = fields.unnamed[key].content;
if (currContent.length > 0) {
unnamed += " | " + currContent;
}
}
}
for (key in fields.named) {
if (fields.named[key]) { // filter unwanted properties from the prototype
currContent = fields.named[key];
if (currContent.length > 0) {
named += "\n | " + key.replace("_", " ") + " = " + currContent;
}
}
}
// create new concatenated with all necessary fields
return unnamed + ((named.length !== 0) ? (named + "\n") : " ");
}
function jedtSerialize() {
var newPage = "", // retValue
ignoreUntilNextKeyEnd = false,
parseDataKey, currParseData, doTemplateParse,
coupletMemory, coupletID, itemID, itemData, parsedDataStructure, itemRowID, inputs;
for (parseDataKey in jedtParsedPageData) { // handle the internal memory flag
if (jedtParsedPageData[parseDataKey] && (parseDataKey !== 'tplNames')) { // filter unwanted properties from the prototype
currParseData = jedtParsedPageData[parseDataKey];
doTemplateParse = false;
if ((currParseData.type === "contentGap") && !ignoreUntilNextKeyEnd) { // handle text gaps
newPage += jkeyParser.buildString(jedtPageCharArray, currParseData.startIndex, currParseData.endIndex);
}
else if (currParseData.type === "{{") { // is a tpl
if (currParseData.name === "Key Start") { // is a starting tpl
doTemplateParse = true;
// check whether key was edited
if (currParseData.wasEdited) {
ignoreUntilNextKeyEnd = true; // key will parsed here (ignore all until next "Key End" in jedtParsedPageData is reached)
doTemplateParse = false; // set back will handled here
// parse "Key Start" itself
newPage += jkeyParser.buildString(jedtPageCharArray, currParseData.startIndex, jkeyParser.indexAfterToken(currParseData.closingType, currParseData.endIndex)) + "\n";
// parse this complete key (use state of the the "coupletMemory")
coupletMemory = currParseData.coupletMemory;
// iterate through all couplets saved there
for (coupletID in coupletMemory) {
if (coupletMemory[coupletID]) { // filter unwanted properties from the prototype
// the couplets have key-children which are itemID data objs
for (itemID in coupletMemory[coupletID]) {
if (coupletMemory[coupletID][itemID]) { // filter unwanted properties from the prototype
itemData = coupletMemory[coupletID][itemID];
parsedDataStructure = (itemData.wasOrigin) ? jedtParsedPageData[itemID] : jedtParsedPageData[jedtParsedDataCoupletMemory_ExtractOriginItemID(itemID)];
if (itemData.wasEdited) {
// get values from inputs
itemRowID = jedtContainer_CreateItemRowID(currParseData.domRef.id, parseDataKey, itemID, "itemID");
inputs = $j(currParseData.domRef).find("#" + itemRowID).find("input,textarea");
if (inputs.length > 1) {
newPage += parsedDataStructure.type + parsedDataStructure.name + jedtSerialize_KnownEdtTpl(inputs, itemRowID) + parsedDataStructure.closingType;
}
else if (inputs.length === 1) { // was an unknown only textarea possible
newPage += jedtSerialize_UnknownEdtTpl(inputs.attr("value"));
}
} else {
newPage += jkeyParser.buildString(jedtPageCharArray, parsedDataStructure.startIndex, jkeyParser.indexAfterToken(parsedDataStructure.closingType, parsedDataStructure.endIndex));
}
newPage += "\n";
}
}
}
}
}
} else if (currParseData.name === "Key End") {
doTemplateParse = true;
ignoreUntilNextKeyEnd = false;
} else { // is tpl within an unedited key
if (!ignoreUntilNextKeyEnd) {
doTemplateParse = true;
}
}
}
// default parsing
if (doTemplateParse) {
newPage += jkeyParser.buildString(jedtPageCharArray, currParseData.startIndex, jkeyParser.indexAfterToken(currParseData.closingType, currParseData.endIndex));
}
}
}
return newPage;
}
//// jEditor ActionCell ////
function jedtActionCell_CreateNewTplData(tplName, coupletID, newItemID, newItemRowID) {
var data, originItemID;
if (jedtHtmlEditTpls[tplName]) {
data = jedtHtmlEditTpls[tplName].clone().closest("fieldset");
data.find(".jedtParseLeadID").val(coupletID); // fill couplet id
// add empty field for alt & backlink (if needed)
jedtTemplate_FillParseLeadID(data);
// change all "id" & "for" & add itemRowID
jedtTemplate_AddItemRowID(data, newItemRowID);
// add function for clicking the inputs
jedtTemplate_AddLegendInputAction(data);
} else { // use open_token, tplname & close_token
originItemID = jedtParsedDataCoupletMemory_ExtractOriginItemID(newItemID);
data = jedtContainer_CreateItemRowForUnknownTpl(tplName, jedtParsedPageData[originItemID].type + tplName + "\n" + jedtParsedPageData[originItemID].closingType);
}
return data;
}
function jedtActionCell_ActionAddNew() {
var itemizedRowID, tplName,
actionCellParentRow = $j(this).closest("td.actionCell").parent(),
coupletID, itemizedLastItem, unknownTplMode, newItemID, newItemRowID, newItemID2, newItemRowID2,
itemsContainer, container, currItemRow;
if (actionCellParentRow.hasClass("edtCouplet")) { // is a couplet-container
// extract generated coupletID part & uniqueID from row
itemizedRowID = jedtContainer_ItemizeRowID(actionCellParentRow.get(0).id);
// calculate id for a new couplet container
coupletID = jedtParsedDataCoupletMemory_GenerateNewCoupletID(itemizedRowID.uniqueKeyID, itemizedRowID.coupletID);
// find last itemRow in the coupletItems container
itemizedLastItem = jedtContainer_ItemizeRowID(actionCellParentRow.find("td.actionContent:first tr.edtItem:last").get(0).id);
// tpl name from origin (last lead of current couplet container) - is same for new items
tplName = jedtParsedPageData[jedtParsedDataCoupletMemory_ExtractOriginItemID(itemizedLastItem.itemID)].name;
unknownTplMode = (!jedtHtmlEditTpls[tplName] && (actionCellParentRow.find("table.coupletItems tr.edtItem").length === 1));
// create first new item id & add to coupletMemory
newItemID = jedtParsedDataCoupletMemory_CalculateNewItemID(itemizedLastItem.uniqueKeyID, itemizedLastItem.itemID);
jedtParsedDataCoupletMemory_CreateItemEntry(itemizedLastItem.itemID, newItemID, itemizedRowID.uniqueKeyID, coupletID, true);
newItemRowID = jedtContainer_CreateItemRowID(itemizedRowID.keyID, itemizedRowID.uniqueKeyID, newItemID, "itemID");
// create second new item id & add to coupletMemory
if (!unknownTplMode) {
newItemID2 = jedtParsedDataCoupletMemory_CalculateNewItemID(itemizedLastItem.uniqueKeyID, newItemID);
jedtParsedDataCoupletMemory_CreateItemEntry(newItemID, newItemID2, itemizedRowID.uniqueKeyID, coupletID, false);
newItemRowID2 = jedtContainer_CreateItemRowID(itemizedRowID.keyID, itemizedRowID.uniqueKeyID, newItemID2, "itemID");
}
// create itemsContainer & add couplet
itemsContainer = jedtContainer_CreateItemsContainerHtml(jedtContainer_CreateItemRowID(itemizedRowID.keyID, itemizedRowID.uniqueKeyID, coupletID, "coupletItems"));
itemsContainer.append(jedtContainer_CreateItemRow(newItemRowID, jedtActionCell_CreateNewTplData(tplName, coupletID, newItemID, newItemRowID), unknownTplMode, false, pastelColors[0])) // first new item
.append(!unknownTplMode ? jedtContainer_CreateItemRow(newItemRowID2, jedtActionCell_CreateNewTplData(tplName, coupletID, newItemID2, newItemRowID2), unknownTplMode, false, pastelColors[1]) : ""); // second new item
container = jedtContainer_CreateHtml(coupletID, jedtContainer_CreateItemRowID(itemizedRowID.keyID, itemizedRowID.uniqueKeyID, coupletID, "couplet"), true, (actionCellParentRow.find("td.actionContent:first").attr("colspan") ? actionCellParentRow.find("td.actionContent:first").attr("colspan") : 0));
container.find("td.actionContent fieldset").append(itemsContainer);
// add after current row
actionCellParentRow.after(container);
} else {
currItemRow = actionCellParentRow.closest("tr.edtItem");
itemizedRowID = jedtContainer_ItemizeRowID(currItemRow.get(0).id);
// create item id & structure in coupletMemory
newItemID = jedtParsedDataCoupletMemory_CalculateNewItemID(itemizedRowID.uniqueKeyID, itemizedRowID.itemID);
coupletID = jedtParsedDataCoupletMemory_FindItemID(itemizedRowID.uniqueKeyID, itemizedRowID.itemID).coupletID;
jedtParsedDataCoupletMemory_CreateItemEntry(itemizedRowID.itemID, newItemID, itemizedRowID.uniqueKeyID, coupletID, false);
// create new tpl
tplName = jedtParsedPageData[jedtParsedDataCoupletMemory_ExtractOriginItemID(itemizedRowID.itemID)].name; // same as from current row
// create new newEditorItemRowID
newItemRowID = jedtContainer_CreateItemRowID(itemizedRowID.keyID, itemizedRowID.uniqueKeyID, newItemID, "itemID");
// add after current row
currItemRow.after(jedtContainer_CreateItemRow(newItemRowID, jedtActionCell_CreateNewTplData(tplName, coupletID, newItemID, newItemRowID), false, false, pastelColors[$j.random(0, pastelColors.length - 1)]));
}
}
function jedtActionCell_ActionEdit() {
var jThis = $j(this),
currDtRow = jThis.closest("tr.dt-row"),
parentTable = currDtRow.closest("table"),
keyDiv = jThis.closest("div.decisiontree").get(0),
changeCouplets = parseInt(jThis.closest("td.actionCell").find("select:first").val(), 10),
changedCounter = 0, cells = 0,
cellCountEachFct = function () {
cells += (($j(this).attr("colspan")) ? parseInt($j(this).attr("colspan"), 10) : 1);
},
itemsContainer, newRowID, extracted, coupletDataInMemory, itemID, container,
coupletRows, untransformedRows;
while (currDtRow.length) {
changedCounter += 1;
if (changedCounter > changeCouplets) {
break;
}
// count cells for colspan of container
cells = 0; // init again
currDtRow.find("td:first").nextAll("td, th").andSelf().each(cellCountEachFct);
cells -= 1; // subtract action cell
itemsContainer = jedtContainer_CreateItemsContainerContent(keyDiv, parseInt($j.trim(currDtRow.find("td.actionCell").next("td").text()), 10));
newRowID = itemsContainer.attr("id").replace("coupletItems", "couplet");
// set edit flag for all belonging decision leads in coupletMemory
extracted = jedtContainer_ItemizeRowID(newRowID);
coupletDataInMemory = jedtParsedPageData[extracted.uniqueKeyID].coupletMemory[extracted.coupletID];
for (itemID in coupletDataInMemory) {
if (coupletDataInMemory[itemID]) { // filter unwanted properties from the prototype
coupletDataInMemory[itemID].wasEdited = true;
}
}
// create transformed couplet
container = jedtContainer_CreateHtml(extracted.coupletID, newRowID, true, cells);
container.find("td.actionContent fieldset").append(itemsContainer);
// append container
coupletRows = jkeyCoupletAsCollection(currDtRow);
coupletRows.filter(":first").before(container);
// set for next loop
currDtRow = coupletRows.filter(":last").nextAll("tr.dt-row:first");
// remove old
coupletRows.remove();
}
// if no more unchanged rows - change colspan layout stuff to all rows
untransformedRows = parentTable.find("tr:first").nextAll("tr.dt-row").length;
if (!parentTable.find("tr:first").hasClass("edtCouplet")) {
untransformedRows += 1;
}
if (untransformedRows === 0) { // all are transformed - change colspan
parentTable.find("tr:first").nextAll("tr").andSelf().each(function () {
$j(this).find("td.actionContent:first").removeAttr("colspan");
});
}
}
function jedtActionCell_ActionMove() {
var itemizedRowID, done,
moveUpOrDown = ($j(this).hasClass("edtIconActionMoveUp")),
actionCellParentRow = $j(this).closest("td.actionCell").parent(),
sibblingFirstDtRow, keyDiv, itemRow, coupletID, coupletMemory;
if (actionCellParentRow.hasClass("edtCouplet") || (actionCellParentRow.hasClass("dt-row") && actionCellParentRow.attr("id"))) { // is a coupletContainer || untransformed couplet
// find neighbours start row
sibblingFirstDtRow = actionCellParentRow; // start loop at current
while (sibblingFirstDtRow.length) {
sibblingFirstDtRow = moveUpOrDown ? sibblingFirstDtRow.prev("tr") : sibblingFirstDtRow.next("tr");
if (sibblingFirstDtRow.find("td.actionCell:first").length) { // rowHasActionCell
break;
}
}
// move current if neighbour
if (sibblingFirstDtRow.length) { // no neighbour means edge region table
keyDiv = actionCellParentRow.closest("div.decisiontree").get(0);
itemizedRowID = (actionCellParentRow.hasClass("edtCouplet")) ?
jedtContainer_ItemizeRowID(actionCellParentRow.get(0).id) : // itemize infos
{keyID: keyDiv.id, uniqueKeyID: $j.data(keyDiv, "keyData").uniqueKeyID, coupletID: $j.trim(actionCellParentRow.find("td.actionCell").next("td").text())}; // collect infos
// move in coupletMemory (whole will be rewritten) & DOM
jedtParsedPageData[itemizedRowID.uniqueKeyID].coupletMemory = jedtBase_MoveKeyOnceUpOrDown(jedtParsedPageData[itemizedRowID.uniqueKeyID].coupletMemory, itemizedRowID.coupletID, moveUpOrDown);
done = moveUpOrDown ? // move coupletRows before || after neighboursCoupletRows
jkeyCoupletAsCollection(sibblingFirstDtRow).filter(":first").before(jkeyCoupletAsCollection(actionCellParentRow)) :
jkeyCoupletAsCollection(sibblingFirstDtRow).filter(":last").after(jkeyCoupletAsCollection(actionCellParentRow));
}
}
else { // is within a coupletContainer
itemRow = actionCellParentRow.closest("tr.edtItem");
itemizedRowID = jedtContainer_ItemizeRowID(itemRow.get(0).id);
coupletID = jedtParsedDataCoupletMemory_FindItemID(itemizedRowID.uniqueKeyID, itemizedRowID.itemID).coupletID;
// move in coupletMemory & DOM
coupletMemory = jedtParsedPageData[itemizedRowID.uniqueKeyID].coupletMemory;
coupletMemory[coupletID] = jedtBase_MoveKeyOnceUpOrDown(coupletMemory[coupletID], itemizedRowID.itemID, moveUpOrDown);
done = moveUpOrDown ? itemRow.prev("tr").before(itemRow) : itemRow.next("tr").after(itemRow);
}
}
function jedtActionCell_ActionRemove() {
var actionCellParentRow = $j(this).closest("td.actionCell").parent(),
itemizedRowID, itemRow, coupletContainer, coupletRow, itemizedParentRowID;
if (actionCellParentRow.hasClass("edtCouplet")) { // is a couplet-container
itemizedRowID = jedtContainer_ItemizeRowID(actionCellParentRow.get(0).id);
jedtBase_RemoveKey(jedtParsedPageData[itemizedRowID.uniqueKeyID].coupletMemory, itemizedRowID.coupletID);
actionCellParentRow.remove();
} else {
itemRow = actionCellParentRow.closest("tr.edtItem");
itemizedRowID = jedtContainer_ItemizeRowID(itemRow.get(0).id);
// rescue container ref
coupletContainer = itemRow.closest("table.coupletItems");
if (coupletContainer.find("tr.edtItem").length === 2) {
alert(jedtResource("edtActionRemoveFault"));
}
else { // contains more than two decisions
itemRow.remove();
// check if container is obsolete
if (!coupletContainer.find("tr.edtItem").length) { // if last entry in coupletItems -> remove (never reached, because min 2)
coupletRow = coupletContainer.closest("tr.edtCouplet");
// remove from view & parsedData
itemizedParentRowID = jedtContainer_ItemizeRowID(coupletRow.get(0).id);
jedtBase_RemoveKey(jedtParsedPageData[itemizedParentRowID.uniqueKeyID].coupletMemory, itemizedParentRowID.coupletID); // remove coupletID & last itemID
coupletRow.remove();
} else {
jedtParsedDataCoupletMemory_RemoveItemID(itemizedRowID.uniqueKeyID, itemizedRowID.itemID);
}
}
}
}
function jedtActionCell_CreatePrimary(inEdit) {
return $j("<table " + (inEdit ? "style='margin-top:1em;'" : "") + "/>")
.attr({"cellspacing": "0", "cellpadding": "0"})
.append($j("<tr/>")
.append(!inEdit ? $j("<td />")
.append($j("<select><option>1</option><option>2</option><option>5</option><option>9</option></select>")) : "")
.append(inEdit ? $j("<td />")
.addClass("actionRemove")
.append(jedtImgResource("edtIconActionRemove")
.addClass("edtIconActionRemove")
.attr({border: "0", title: jedtResource("edtActionRemoveTitle")})
.click(jedtActionCell_ActionRemove)) : "")
.append($j("<td />")
.addClass("actionMove")
.append(jedtImgResource("edtIconActionMoveUp")
.addClass("edtIconActionMoveUp")
.attr({border: "0", title: jedtResource("edtActionMoveUpTitle")})
.click(jedtActionCell_ActionMove)))
)
.append($j("<tr/>")
.append(!inEdit ? $j("<td />")
.addClass("actionEdit")
.append(jedtImgResource("edtIconActionEdit")
.attr({border: "0", title: jedtResource("edtActionEditTitle")})
.click(jedtActionCell_ActionEdit)) : "")
.append(inEdit ? $j("<td />")
.addClass("actionAddNew")
.append(jedtImgResource("edtIconActionAddNew")
.addClass("edtIconActionAddNew")
.attr({border: "0", title: jedtResource("edtActionAddNewTitle")})
.click(jedtActionCell_ActionAddNew)) : "")
.append($j("<td />").addClass("actionMove")
.append(jedtImgResource("edtIconActionMoveDown")
.addClass("edtIconActionMoveDown")
.attr({border: "0", title: jedtResource("edtActionMoveDownTitle")})
.click(jedtActionCell_ActionMove)))
);
}
function jedtActionCell_CreateSecondary() {
return $j("<table />")
.append($j("<tr/>").append($j("<td/>").addClass("actionRemove")
.append(jedtImgResource("edtIconActionRemove")
.attr({border: "0", title: jedtResource("edtActionRemoveTitle")})
.click(jedtActionCell_ActionRemove)
)))
.append($j("<tr/>").append($j("<td/>").addClass("actionMove")
.append(jedtImgResource("edtIconActionMoveUp")
.addClass("edtIconActionMoveUp")
.attr({border: "0", title: jedtResource("edtActionMoveUpTitle")})
.click(jedtActionCell_ActionMove)
)))
.append($j("<tr/>").append($j("<td/>").addClass("actionMove")
.append(jedtImgResource("edtIconActionMoveDown")
.addClass("edtIconActionMoveDown")
.attr({border: "0", title: jedtResource("edtActionMoveDownTitle")})
.click(jedtActionCell_ActionMove)
)))
.append($j("<tr/>").append($j("<td/>").addClass("actionAddNew")
.append(jedtImgResource("edtIconActionAddNew")
.attr({border: "0", title: jedtResource("edtActionAddNewTitle")})
.click(jedtActionCell_ActionAddNew)
)));
}
//// JKey parser ////
function JKeyPageParser() {
/*
* description: main function, which parses first level tpls + non-tpl content between
* and skips all lower level tpls as well as links, img, comments, nowiki, etc.
* charArray: complete content of the page as char array
* returns: object with parsed content
*/
this.initialize = function (charArray) {
if (!charArray) { // abort main fct
return {};
}
// data container
var parsedData = {}, // loop variables
token, index = 0, retValue, tplCounter = -1,
addContentGap = false, gapStartIndex = 0, gapEndIndex = 0, // space between tpls (nonparsable gap)
currTplName, lastParsed;
// parses the whole text looking for tpls, comments
do {
token = this.extractToken(charArray, index);
index = token.indexAfter;
// choose function
switch (token.type) {
case "{{":
gapEndIndex = this.indexBeforeToken(token.type, index);
retValue = this.parseTpl(charArray, index);
if ((gapEndIndex - gapStartIndex) > 0) { // is a gap
addContentGap = true;
}
break;
case "[[":
index = this.skipLinkOrImg(charArray, index);
break;
case "<!--":
case "<nowiki>":
index = this.skipSpecial(charArray, index, token.type, (token.type === "<!--") ? "-->" : "</nowiki>");
break;
case " ": // tokenNone
case "": // tokenEnd
retValue = null;
break;
}
// memorize content gap between tpls
if (addContentGap) {
parsedData[tplCounter += 1] = {startIndex: gapStartIndex, endIndex: gapEndIndex, type: "contentGap"};
}
// add valid value
if (retValue) {
// set index to new value
index = this.indexAfterToken(token.type, retValue.endIndex);
// gap handling
addContentGap = false;
gapStartIndex = index;
// add tpl name
if (typeof(parsedData.tplNames) !== 'object') {
parsedData.tplNames = {};
}
currTplName = retValue.name;
// set frequency
if (!parsedData.tplNames[currTplName]) {
parsedData.tplNames[currTplName] = 0;
}
parsedData.tplNames[currTplName] += 1;
// add parsed tpl structure to data
tplCounter += 1;
parsedData[tplCounter] = retValue;
// reset
retValue = null;
}
}
while (token.type !== "");
// add content gap after last tpl if exists
if (parsedData[tplCounter]) {
lastParsed = parsedData[tplCounter];
if ((lastParsed.type === "{{") && (jkeyParser.indexAfterToken(lastParsed.closingType, lastParsed.endIndex) < index)) {
tplCounter += 1;
parsedData[tplCounter] = {startIndex: jkeyParser.indexAfterToken(lastParsed.closingType, lastParsed.endIndex), endIndex: index, type: "contentGap"};
}
}
return parsedData;
};
/*
* description: skip whitespace
* charArray: complete content of the page as array of chars
* index: current position within charArray
* returns: index of first non-whitespace
*/
this.skipWhitespace = function (charArray, index) {
for (; index < charArray.length; index += 1) {
if (" \t\n\r".indexOf(charArray[index]) === -1) {
return index;
}
}
// no whitespace
return index;
};
/*
* description: skip whitespace form right to left
* charArray: complete content of the page as array of chars
* index: current position within charArray
* returns: index (depending on found whitespace)
*/
this.skipWhitespaceBackward = function (charArray, index) {
// perform whitespace jump back
for (; index > 0; index -= 1) {
if (" \t\n\r".indexOf(charArray[index - 1]) === -1) {
return index;
}
}
// no whitespace
return index;
};
/*
* description: looks for current token
* charArray: complete content of the page as array of chars
* index: current position within charArray
* returns: token type & next index position
*/
this.extractToken = function (charArray, index) {
// ignore empty or system chars
index = this.skipWhitespace(charArray, index);
// check tokens with one char
if (index >= charArray.length) { // main abort condition
return {type: "", indexAfter: index};
}
// variables are set character strings & will compared
var s = {}, i, prev = "", token = " "; // tokenNone
for (i = 0; i < 9; i += 1) {
s[i] = ((index + i) >= charArray.length) ? "" : prev + charArray[index + i];
prev = s[i];
}
if (s[8] === "</nowiki>") {
token = s[8];
} else if (s[7] === "<nowiki>") {
token = s[7];
} else if (s[3] === "<!--") {
token = s[3];
} else if (s[2] === "-->") {
token = s[2];
} else if (s[1] === "{{" || s[1] === "}}" || s[1] === "[[" || s[1] === "]]" || s[1] === "]]") {
token = s[1];
} else if (s[0] === "|" || s[0] === "=") {
token = s[0];
}
return {type: token, indexAfter: this.indexAfterToken(token, index)};
};
/*
* description: return a slice of the char array as string
* charArray: complete content of the page as array of chars
* index: start index
* endIndex: end index
* returns: string
*/
this.buildString = function (charArray, index, endIndex) {
var retString = "";
for (; index < endIndex; index += 1) {
if (charArray[index]) { // does char exists
retString += charArray[index];
}
}
return retString;
};
/*
* description: return a slice of the char array as string
* charArray: complete content of the page as array of chars
* index: start index
* endIndex: end index
* children: object including parsed-children to be skipped
* returns: string
*/
this.buildStringWithoutChilds = function (charArray, index, endIndex, chields) {
var retString = "", e, i, childrenLength = 0, writeChar = true;
for (e in chields) {
if (chields.hasOwnProperty(e)) {
childrenLength += 1;
}
}
for (; index < endIndex; index += 1) {
writeChar = true;
for (i = 0; i < childrenLength; i += 1) {
if (index === chields[i].startIndex) {
index = this.indexAfterToken(chields[i].closingType, chields[i].endIndex) - 1; // -1 because to add itself & will checked in next loop
writeChar = false;
break;
}
}
if (writeChar) {
retString += charArray[index];
}
}
return retString;
};
/*
* description: main tpl parsing, after {{ was found
* charArray: complete content of the page as array of chars
* index: current position within charArray
* returns: object with parsed tpl content
*/
this.parseTpl = function (charArray, index) {
// initialize tpl container
var tplData = {type: "{{", startIndex: this.indexBeforeToken("{{", index), closingType: "}}"},
token, endIndexName, whitespaceAtEndStartIndex, fieldCounter, unnamedFieldName;
// iterate through whole tpl
while (true) {
token = this.extractToken(charArray, index);
index = token.indexAfter;
// extract tpl name, then test for fields:
if ((token.type === "}}") || (token.type === "|")) {
// calculate end index
endIndexName = this.indexBeforeToken(token.type, index);
// get tpl name
whitespaceAtEndStartIndex = this.skipWhitespaceBackward(charArray, endIndexName);
tplData.whitespaceAtEnd = this.buildString(charArray, whitespaceAtEndStartIndex, endIndexName);
tplData.name = this.buildString(charArray, this.indexAfterToken("{{", tplData.startIndex), whitespaceAtEndStartIndex);
tplData.name.replace("_", " ");
// tpl immediately closed, no fields available
if (token.type === "}}") {
tplData.endIndex = endIndexName;
return tplData;
}
// else (implied) has tokenPipe: initialize field counter, field container & check further fields
fieldCounter = 0;
unnamedFieldName = 1;
tplData.fields = {};
while (true) {
// parse token field
tplData.fields[fieldCounter] = this.parseOneTplField(charArray, index, unnamedFieldName);
// already finished tpl definition
if (tplData.fields[fieldCounter].isLastField === true) {
// reset last index
tplData.endIndex = tplData.fields[fieldCounter].endIndex;
// finish current tpl
return tplData;
}
// prepare token loop
index = this.indexAfterToken("|", tplData.fields[fieldCounter].endIndex); // only pipe possible
if (tplData.fields[fieldCounter].isUnnamedField === true) { // check special fields
unnamedFieldName += 1;
}
fieldCounter += 1;
}
}
else if (token.type === "{{") { // ignore tpls within
index = this.skipTpl(charArray, index);
}
else if ((token.type === "<!--") || (token.type === "<nowiki>")) { // ignore unnecessary areas
index = this.skipSpecial(charArray, index, token.type, (token.type === "<!--") ? "-->" : "</nowiki>");
}
else if (token.type === "") { // no closing token found means syntax fault
throw (new JKeyException("ParserException", {errorPosition: tplData.startIndex, contentBeforeErrorPosition: this.buildString(charArray, (tplData.startIndex - 50), tplData.startIndex), contentAfterErrorPosition: this.buildString(charArray, tplData.startIndex, (tplData.startIndex + 50)), expectedToken: "}}"}));
}
}
};
/*
* description: handles parsing of a field (mediawiki: "tpl parameter") of a tpl
* charArray: complete content of the page as array of chars
* index: current position within charArray
* returns: object with parsed field content
*/
this.parseOneTplField = function (charArray, index, unnamedFieldName) {
// initialize new field container
var fieldData = {startIndex: this.indexBeforeToken("|", index), isLastField: false, isUnnamedField: false},
token, // loop variables
childCounter = 0,
startIndexAfterToken, whitespaceAtStartEndIndex, whitespaceAtEndStartIndex,
wholeField, isUnnamed, firstEqualSignPos, fieldUntilFirstEqual;
while (true) {
token = this.extractToken(charArray, index);
index = token.indexAfter;
if ((token.type === "}}") || (token.type === "|")) {
// calculate end idx & set closing
fieldData.endIndex = this.indexBeforeToken(token.type, index);
fieldData.closingType = token.type;
startIndexAfterToken = this.indexAfterToken(token.type, fieldData.startIndex);
whitespaceAtStartEndIndex = this.skipWhitespace(charArray, startIndexAfterToken);
whitespaceAtEndStartIndex = this.skipWhitespaceBackward(charArray, fieldData.endIndex);
fieldData.whitespaceAtStart = this.buildString(charArray, startIndexAfterToken, whitespaceAtStartEndIndex);
fieldData.whitespaceAtEnd = this.buildString(charArray, whitespaceAtEndStartIndex, fieldData.endIndex);
// get position where name ends and rest starts
wholeField = this.buildString(charArray, whitespaceAtStartEndIndex, whitespaceAtEndStartIndex);
isUnnamed = true;
firstEqualSignPos = wholeField.indexOf('=');
if (firstEqualSignPos !== -1) { // extract named
fieldUntilFirstEqual = this.buildString(charArray, whitespaceAtStartEndIndex, whitespaceAtStartEndIndex + firstEqualSignPos);
// check name has complex structure
try {
this.initialize(fieldUntilFirstEqual.split(''));
isUnnamed = false; // parsing was successful
fieldData.name = this.buildStringWithoutChilds(charArray, whitespaceAtStartEndIndex, this.skipWhitespaceBackward(charArray, (whitespaceAtStartEndIndex + firstEqualSignPos)), fieldData.children); // skip space between named and = & ignore children like comments
fieldData.content = this.buildString(charArray, this.skipWhitespace(charArray, (whitespaceAtStartEndIndex + firstEqualSignPos + 1)), whitespaceAtEndStartIndex); //+1 because start after equal sign
}
catch (exception) {
isUnnamed = true;
}
}
// handle as unnamed
if (isUnnamed) {
fieldData.name = unnamedFieldName;
fieldData.content = wholeField;
fieldData.isUnnamedField = true;
}
// already reached tpl definition
if (token.type === "}}") {
fieldData.isLastField = true;
}
// finish current tpl
return fieldData;
}
else if (token.type === "{{") { // ignore tpls within
index = this.skipTpl(charArray, index);
}
if (token.type === "[[") { // ignore links within
index = this.skipLinkOrImg(charArray, index);
}
else if ((token.type === "<!--") || (token.type === "<nowiki>")) {
// add container if necessary
if (childCounter === 0) {
fieldData.children = {};
}
// parse unnecessary areas
fieldData.children[childCounter] = this.parseSpecial(charArray, index, token.type, (token.type === "<!--") ? "-->" : "</nowiki>");
// ignore comments within
index = fieldData.children[childCounter].endIndex;
childCounter += 1;
}
else if (token.type === "") { // no closing token found means syntax fault
throw (new JKeyException("ParserException", {errorPosition: fieldData.startIndex, contentBeforeErrorPosition: this.buildString(charArray, (fieldData.startIndex - 50), fieldData.startIndex), contentAfterErrorPosition: this.buildString(charArray, fieldData.startIndex, (fieldData.startIndex + 50)), expectedToken: "}}"}));
}
}
};
/*
* description: handles "[[" to "]]", used in mediawiki for link, categories, images, etc.
* charArray: complete content of the page as array of chars
* index: current position within charArray
* returns: object with parsed link content
*/
this.parseLinkOrImg = function (charArray, index) {
// initialize comment container
var linkData = {type: "[[", startIndex: this.indexBeforeToken("[[", index), closingType: "]]"},
token; // loop variables
while (true) {
token = this.extractToken(charArray, index);
index = token.indexAfter;
if (token.type === "]]") {
linkData.endIndex = this.indexBeforeToken(token.type, index);
return linkData; // all fine return link
}
else if (token.type === "{{") { // ignore tpls within
index = this.skipTpl(charArray, index);
}
else if (token.type === "[[") { // ignore links within
index = this.skipLinkOrImg(charArray, index);
}
else if ((token.type === "<!--") || (token.type === "<nowiki>")) { // ignore unnecessary areas
index = this.skipSpecial(charArray, index, token.type, (token.type === "<!--") ? "-->" : "</nowiki>");
}
else if (token.type === "") { // no closing token found means syntax fault
throw (new JKeyException("ParserException", {errorPosition: linkData.startIndex, contentBeforeErrorPosition: this.buildString(charArray, (linkData.startIndex - 50), linkData.startIndex), contentAfterErrorPosition: this.buildString(charArray, linkData.startIndex, (linkData.startIndex + 50)), expectedToken: "]]"}));
}
}
};
/*
* description: handles an area defined by two limiter-tokens
* charArray: complete content of the page as array of chars
* index: current position within charArray
* startToken: defined token, with which the area starts
* endToken: defined token, with which the area ends
* returns: object with parsed content
*/
this.parseSpecial = function (charArray, index, startToken, endToken) {
// initialize comment container
var definedAreaData = {type: startToken, startIndex: this.indexBeforeToken(startToken, index), closingType: endToken},
token; // loop variables
while (true) {
token = this.extractToken(charArray, index);
index = token.indexAfter;
if (token.type === endToken) {
definedAreaData.endIndex = this.indexBeforeToken(token.type, index);
definedAreaData.content = this.buildString(charArray, this.indexAfterToken(startToken, definedAreaData.startIndex), this.indexBeforeToken(token.type, token.indexAfter));
// all fine return comment
return definedAreaData;
}
else if (token.type === "") { // no closing token found means syntax fault
throw (new JKeyException("ParserException", {errorPosition: definedAreaData.startIndex, contentBeforeErrorPosition: this.buildString(charArray, (definedAreaData.startIndex - 50), definedAreaData.startIndex), contentAfterErrorPosition: this.buildString(charArray, definedAreaData.startIndex, (definedAreaData.startIndex + 50)), expectedToken: endToken}));
}
}
};
/*
* description: skip functions: reduce token parser to a skip functionality, set index to end index
* Compare associate parse-functions for parameter details
*/
this.skipTpl = function (charArray, index) {
return this.indexAfterToken("}}", this.parseTpl(charArray, index).endIndex);
};
this.skipLinkOrImg = function (charArray, index) {
return this.indexAfterToken("]]", this.parseLinkOrImg(charArray, index).endIndex);
};
this.skipSpecial = function (charArray, index, startToken, endToken) {
return this.indexAfterToken(endToken, this.parseSpecial(charArray, index, startToken, endToken).endIndex);
};
/*
* description: jump before/after a token
* token: current token
* index: current position within charArray
* returns: index
*/
this.indexBeforeToken = function (token, index) {
return (index - token.length);
};
this.indexAfterToken = function (token, index) {
return (token.length + index);
};
}
//// JKey editor local ////
//jQueryLocalFileProxy.php
//<?php
// // built up url with parameters
// $fileName = $_GET['fileName'];
// // print file
// if (strlen($fileName) > 1) {
// $file = fopen("local/".$fileName, "r") or exit("Unable to open file!");
// while(!feof($file)) {
// echo fgets($file);
// }
// fclose($file);
// }
//?>
function localAjaxProxy(fileName) {
var targetUrl = "/jQueryLocalFileProxy.php",
parameters = {fileName: fileName},
ajaxResponse;
$j.ajax({
type: "GET",
async: false,
url: targetUrl,
data: parameters,
success: function (content) {
ajaxResponse = content;
},
error: function () {
alert("Error from local proxy!");
}
});
return ajaxResponse;
}
//// JKey editor sub ////
function jedtInitEditor() {
var jKeyDiv = $j("div.decisiontree"), // exist valid keys
apiResult, apiScript = wgServer + wgScriptPath + "/api.php";
if (jKeyDiv.length > 0) {
try { // avoid a fault of the loaded site
if (!localTstMode) {
apiResult = $j(jkeyAjax(apiScript, {action: "query", prop: "info|revisions", intoken: "edit", format: "xml", titles: wgPageName}, true, false, jkeyAjaxSuccess, jkeyAjaxError));
}
} catch (err) {}
// initialize editor
try { // avoid a fault of the loaded site
// fill edit form variables
jedtEditFormVars.wpSave = "";
jedtEditFormVars.wpSection = "";
jedtEditFormVars.wpSummary = jedtResource("edtWpSummary");
if (apiResult && (apiResult.find("rev").length === 1)) { // add dynamic values
jedtEditFormVars.wpEditToken = apiResult.find("page").attr("edittoken");
jedtEditFormVars.wpEdittime = apiResult.find("rev").attr("timestamp").replace(/-|:|T|Z/g, "");
jedtEditFormVars.wpStarttime = apiResult.find("page").attr("starttimestamp").replace(/-|:|T|Z/g, "");
}
// add editor container stuff (has to exists already in dom else wait symbol won't work)
jKeyDiv.find("table.dt-body:last").before($j('<div class="jedt" />').append($j("<form/>")
.append($j("<div/>").addClass("jedtWait").append(jedtImgResource("edtIconLoading")))
.append($j("<div/>").addClass("jedtContent"))
.append($j("<div/>").addClass("jedtControls")
.append("<span class='jedtInstantSave' style='display:none;'> <input class='editbtn' type='button' style='font-size:1.25em;vertical-align:middle;' value='" + jedtResource("edtInstantSave") + "' onclick='jedtSave(this, true)' /></span>")
.append("<span class='jedtSave' style='display:none;'> <input class='editbtn' type='button' style='font-size:1.25em;vertical-align:middle;' value='" + jedtResource("edtSave") + "' onclick='jedtSave(this, false)' /></span>")
)
.append($j("<br style=\"clear:both;\"/>").addClass("jedtBreak"))
));
// add editor styles
$j("head").append("<style type=\"text/css\">" +
"fieldset.jedtFieldset {margin: 0;} \n" +
"td.actionRemove, td.actionAddNew, td.actionMove, td.actionEdit {cursor: pointer;} \n" +
"td.actionCell {vertical-align: top; width: 1%;} \n" +
"td.actionCell table td {padding-right: 0.3em;} \n" +
"td.actionContent {width: 99%;} \n" +
"div.jedtWait {display: none; text-align: center; margin-top: 1em;} \n" +
"div.jedtWait img {height: 40px; width: 40px;} \n" +
"div.jedtContent, br.jedtBreak {display: none;} \n" +
"div.jedtControls {display: none; float: right; padding-top: 0.4em} \n" +
"table.unknownFields tr td {padding-right: 0.2em;} \n" +
"</style>");
} catch (err2) {}
}
}
function jedtInitGlobalVars() {
// get raw data of current page
if (!jedtPageCharArray) {
jedtPageCharArray = (localTstMode) ?
localAjaxProxy("rawTemplateDecisionHorizontalDoc.tpl").split('') :
jkeyAjax(wgScript, {title: wgPageName, action: "raw", random: $j.random(0, 10000)}, true, false, jkeyAjaxSuccess, jkeyAjaxError).split('');
}
// parse page data
if (!jedtParsedPageData) {
// initialize parser
if (!jkeyParser) { // lazy loading
jkeyParser = new JKeyPageParser();
}
// parse raw data of current page
jedtParsedPageData = jkeyParser.initialize(jedtPageCharArray);
}
// retrieve all editor tpls
if (localTstMode) {
if (!jedtHtmlEditTpls.Lead) { // only "Lead" for testing
jedtHtmlEditTpls.Lead = $j(localAjaxProxy("rawLeadHtmlEditorTpl.htm"));
}
} else {
if (jedtBase_CountKeys(jedtHtmlEditTpls) === 0) { // nothing loaded, yet
for (var currTplName in jedtParsedPageData.tplNames) {
if (jedtParsedPageData.tplNames[currTplName] && (typeof(currTplName) === 'string') && (!jedtHtmlEditTpls[currTplName])) {
try {
jedtHtmlEditTpls[currTplName] = $j(jkeyAjax(wgScript, {title: "MediaWiki:" + currTplName.replace(' ', '_') + "/HtmlEditorTemplate", action: "raw", random: $j.random(0, 10000)}, true, false, jkeyAjaxSuccess, jkeyAjaxError));
} catch (err) {
if (err.variables.status !== 404) { // only "page not found" will be accepted
throw (err); // otherwise exception will be forwarded
}
}
}
}
}
}
}
function jedtChangeCtrls(toggleMode, jKeyOrDoc) {
switch (toggleMode) {
case ("hideEditBtn"):
jKeyOrDoc.find("div.jkeyLCtrls input.editbtn").hide();
break;
case ("showEditControls"):
jKeyOrDoc.find("span.jedtSave").show();
jKeyOrDoc.find("span.jedtInstantSave").show();
break;
case ("disableInstantSave"):
jKeyOrDoc.find("span.jedtInstantSave input").attr("disabled", "disabled");
break;
case ("enableInstantSave"):
jKeyOrDoc.find("span.jedtInstantSave input").removeAttr("disabled");
break;
case ("finalSave"):
jKeyOrDoc.find("div.jkeyLCtrls input.editbtn").hide();
jKeyOrDoc.find("span.jedtInstantSave input, span.jedtSave input").attr("disabled", "disabled");
break;
case ("rollback"):
jKeyOrDoc.find("div.jkeyLCtrls input.editbtn").remove();
break;
default:
throw (new JKeyException("NotImplementedException", {info: jedtResource("edtNiExNfoA") + toggleMode + jedtResource("edtNiExNfoB")}));
}
}
//// JKey editor main ////
function jedtSave(caller, instantSave) {
try {
var jKeyDiv = $j(caller).closest("div.decisiontree"),
jedtDiv = jKeyDiv.find("div.jedt"), doc;
// check edit initialized
if (!$j(jedtDiv.find("table.dt-body").get(0).rows).filter(".edtCouplet").length) {
alert(jedtResource("edtSavingFault")); // show msg
return false; // avoid href call
}
// show wait while instant save
jedtDiv.find("div.jedtWait").show();
jkeyScrollToElement(jKeyDiv.get(0));
// serialize & validate inputs
try {
jedtEditFormVars.wpTextbox1 = jedtSerialize();
} catch (err) {
jedtDiv.find("div.jedtWait").hide();
alert(err); // show msg
return false; // avoid href call
}
// handle save mode
if (instantSave) {
jedtChangeCtrls("disableInstantSave", jKeyDiv);
// collect parameters
if (!localTstMode) { // do post
jkeyAjax(wgScript + "?title=" + wgPageName + "&action=submit", jedtEditFormVars, false, true, function () {
jedtChangeCtrls("enableInstantSave", jKeyDiv);
jedtDiv.find("div.jedtWait").hide();
}, jkeyAjaxError);
}
}
else {
// hide all editor & player links on the page
doc = $j(); // set to whole document
jedtChangeCtrls("finalSave", doc);
doc.find("td.jkeyControls").hide();
// delete whole editorDiv for start (also jedtContent will be deleted)
doc.find("div.jedt").remove();
// collect parameters
doc.find("div.dt-header").append($j('<div/>').addClass("jkeyResultMsg").html(jedtResource("edtSaving")));
if (!localTstMode) { // do post
jkeyAjax(wgScript + "?title=" + wgPageName + "&action=submit", jedtEditFormVars, false, true, function () {
doc.find("div.jedtWait").hide();
location.reload(true);
}, jkeyAjaxError);
}
}
} catch (err2) {
jkeyExceptionAlert(err2);
}
return false; // avoid href call
}
function jedtInitKey(caller) {
var jKeyDiv = $j(caller).closest("div.decisiontree"),
jedtDiv = jKeyDiv.find("div.jedt"),
jKeyTable = jKeyDiv.find("table.dt-body:last"); // :last - player also can contain one
try {
// scroll to begin
jkeyScrollToElement(jKeyDiv.get(0));
// has user edit rights
if (!localTstMode && (!jedtEditFormVars.wpEditToken || (jedtEditFormVars.wpEditToken.length === 0))) {
jKeyDiv.find("div.jkeyLCtrls input.editbtn").remove();
alert(jedtResource("edtRightsFault"));
return false;
}
// hide table
jKeyTable.hide();
// disable all player links
jKeyDiv.find("td.jkeyControls").hide();
// change editor links
jedtChangeCtrls("hideEditBtn", jKeyDiv); // because following preloading & preparing needs time
// show wait & break
jedtDiv.find("div.jedtWait").show();
jedtDiv.find("br.jedtBreak").show();
// initialize global & couplet memory for this key
jedtInitGlobalVars();
jedtParsedData_InitCoupletMemoryForKey(jKeyDiv.get(0));
// move key table into editor
jKeyTable.css("width", "100%");
jedtDiv.find("div.jedtContent").append(jKeyTable);
// initialize edit action images
jKeyTable.find("tr:first").nextAll("tr").andSelf().each(function () {
var jThis = $j(this),
rowHasID = (jThis.find("td:first").attr("id").length);
jThis.find("td:first").before($j("<td " + (!rowHasID ? "" : "class='actionCell'") + "/>").append(!rowHasID ? "" : jedtActionCell_CreatePrimary(false)));
});
// handle jedt visibilities
jKeyTable.show();
jedtDiv.find("div.jedtWait").hide();
jedtDiv.find("div.jedtContent").show();
jedtDiv.find("div.jedtControls").show();
jedtChangeCtrls("showEditControls", jKeyDiv);
// scroll to begin
jkeyScrollToElement(jKeyDiv.get(0));
} catch (err) {
// rollback player
jKeyDiv.append(jKeyTable.show());
jKeyDiv.find("td.jkeyControls").show();
jKeyDiv.find("div.jkeyPlayer").remove();
// remove edt
jedtChangeCtrls("rollback", $j());
jedtDiv.remove();
// throw fault
jkeyExceptionAlert(err);
}
return false; // avoid href call
}
/*
* description: constructor, which is called after the html document was loaded
*/
$j(document).ready(function () {
jedtImgPreloader();
if (document.URL.toString().search("LocalTestFile.htm") !== -1) {
localTstMode = true;
}
if (wgUserName !== null) {
setTimeout(jedtInitEditor, 10); // start after page was loaded
}
});