/*
* Copyright (c) Perforce Software, Inc. 1997-2016
* Licensed Materials - All Rights Reserved.
*/
function TextField(psheet, parent, name, text) {
this.psheet = psheet;
this.name = name;
this.text = text;
this.initText = text;
this.labelId = "textfield_"+name;
this.rootId = this.labelId+"root";
this.inputId = this.labelId+"input";
this.createTextField(parent);
this.changeListeners = new IlvListenerList();
}
TextField.regularStyleClass = "textfield";
TextField.highlightedStyleClass = "textfield-highlighted";
TextField.changedStyleClass = "textfield-changed";
TextField.errorStyleClass = "textfield-error";
TextField.prototype.getName = function() {
return this.name;
};
TextField.prototype.getText = function() {
return this.getLabelText();
};
TextField.prototype.createTextField = function (parent) {
parentNode = document.getElementById(parent);
this.parent = parentNode;
parentNode.innerHTML = "<span id='"+this.rootId+"'><span id='"+this.labelId+"' class='"+TextField.regularStyleClass+"'>"+this.text+"</span></span>";
this.label = document.getElementById(this.labelId);
this.root = document.getElementById(this.rootId);
var textfield = this;
this.label.onmouseover = function () {
if (textfield) {
if (textfield.hasError())
this.className=TextField.errorStyleClass;
else if (textfield.hasChanged())
this.className=TextField.changedStyleClass;
else this.className=TextField.highlightedStyleClass;
}
};
this.label.onmouseout = function () {
if (textfield) {
if (textfield.hasError())
this.className=TextField.errorStyleClass;
else if (textfield.hasChanged())
this.className=TextField.changedStyleClass;
else this.className=TextField.regularStyleClass;
}
};
parentNode.onclick = function () {
textfield.psheet.setSelected(this);
textfield.showInput();
};
};
TextField.prototype.addChangeListener = function(listener) {
this.changeListeners.addListener(listener);
};
TextField.prototype.removeChangerListener = function(listener) {
this.changeListeners.removeListener(listener);
};
TextField.prototype.changed = function(oldText, newText) {
this.setError(false);
this.textChanged = true;
this.setLabelText(newText);
this.text = newText;
this.label.className=TextField.changedStyleClass;
this.changeListeners.notify(this, oldText, newText);
};
TextField.prototype.revert = function() {
this.text = this.initText;
this.textError = false;
this.setLabelText(this.text);
this.textChanged = false;
this.label.className=TextField.regularStyleClass;
};
TextField.prototype.showInput = function () {
this.parentClickSave = this.parent.onclick;
this.parent.onclick = null;
this.parent.className = PropertySheet.ValueCellEditing;
var label = this.label;
var root = this.root;
var input;
var text = this.getLabelText();
input = document.createElement('input');
input.id = this.inputId;
input.style.display = "none";
input.type = "text";
input.name = "textbox";
input.value = text;
input.autoComplete = "off";
root.appendChild(input);
var textfield = this;
input.onblur = function() {textfield.onBlur();};
input.onkeypress = function(e) {textfield.onKeyPress(e);};
input.className=TextField.regularStyleClass;
label.style.display="none";
input.size = input.value.length == 0 ? 8 : input.value.length;
this.oldText = input.value;
input.style.display="inline";
input.select();
try {
input.focus();
} catch (e) {
}
};
TextField.prototype.hasChanged = function() {
return this.textChanged;
};
TextField.prototype.hasError = function() {
return this.textError;
};
TextField.prototype.setError = function(value) {
if (value) {
this.textError = true;
this.label.className = TextField.errorStyleClass;
} else {
this.textError = false;
this.label.className = TextField.regularStyleClass;
}
}
TextField.prototype.onBlur = function() {
var input = document.getElementById(this.inputId);
this.hideInput();
var text = input.value;
if (this.oldText != text) {
this.changed(this.oldText, text);
}
};
TextField.prototype.setLabelText = function(text) {
var label = this.label;
if (label) {
if(label.innerText) {
label.innerText = text;
} else {
var txt = label.childNodes[0];
if (!txt) {
txt = document.createTextNode(text);
label.appendChild(txt);
} else {
txt.data = text;
}
}
}
};
TextField.prototype.getLabelText = function() {
var label = this.label;
if (label) {
if (label.innerText) {
return label.innerText;
} else {
var txt = label.childNodes[0];
if (!txt) {
return "";
} else {
return txt.data;
}
}
}
return null;
};
TextField.prototype.hideInput = function() {
var label = this.label;
var input = document.getElementById(this.inputId);
var root = this.root;
this.parent.className = PropertySheet.ValueCell;
if(root.removeChild)
root.removeChild(input);
else
input.style.display="none";
label.style.display="inline";
this.parent.onclick = this.parentClickSave;
};
TextField.prototype.onKeyPress = function(e) {
var input = document.getElementById(this.inputId);
var keyCode;
if (e)
keyCode = e.keyCode;
else
keyCode = event.keyCode;
if (keyCode==13) {
input.onblur();
return false;
} else if (keyCode==27) {
input.value = this.oldText;
return false;
}
return true;
};
function PropertySheet (ref, spanId) {
this.ref = ref;
this.spanId = spanId;
this.tableId = this.spanId + "_table";
this.commitId = this.tableId + "_commit";
this.deletedProperties = [];
this.addedProperties = [];
}
PropertySheet.Table = "psheet";
PropertySheet.TitleCell = "psheet-cell-title";
PropertySheet.NameCell = "psheet-cell";
PropertySheet.ValueCell = "psheet-cell-value";
PropertySheet.CellSelected = "psheet-cell-selected";
PropertySheet.Text = "psheet-text";
PropertySheet.prototype.setAbsoluteId = function (id) {
this.absoluteId = id;
};
PropertySheet.prototype.setView = function (view) {
this.view = view;
this.updateSelectionManager();
};
PropertySheet.prototype.getView = function () {
return this.view;
};
PropertySheet.prototype.setComponent = function (component) {
this.component = component;
this.updateSelectionManager();
}
PropertySheet.prototype.getComponent = function () {
return this.component;
};
PropertySheet.prototype.updateSelectionManager = function () {
if (this.view != null && this.component != null) {
if (this.component == "table") {
this.setSelectionManager(this.view.getTableView().getSelectionManager());
} else if (this.component == "sheet") {
this.setSelectionManager(this.view.getSheetView().getSelectionManager());
}
}
}
PropertySheet.prototype.setSelectionManager = function (selectionManager) {
this.selectionManager = selectionManager;
var psheet = this;
selectionManager.addSelectionChangedListener(
function(selection) {
psheet.displayPropertySheet(selection);
}
);
};
PropertySheet.prototype.addProperty = function () {
var table = document.getElementById(this.tableId);
if (table) {
var name = prompt(jviews.messages.demo.ganttFacelet.propertySheet.enterNameOfNewProperty, "");
if (name) {
var found = false;
var length = this.deletedProperties.length;
for(var i=0; i<length && !found; i++) {
var prop = this.deletedProperties[i];
if (prop == name) {
found = true;
}
}
if (found) {
//remove the property from the list
this.deletedProperties.splice(i-1, 1);
//show the deleted property
var selectedNameCell = document.getElementById("name_"+name);
var tr = selectedNameCell.parentNode;
if (IlvBrowserInfo.instance.ie5up) {
tr.style.display = "block";
} else {
tr.style.display = "table-row";
}
} else {
if (this.textfields[name]) {
alert(jviews.messages.demo.ganttFacelet.propertySheet.propertyExistsError);
return;
}
this.addedProperties[this.addedProperties.length] = name;
var names = [];
for(var i in this.textfields){
names[names.length] = this.textfields[i].getName();
}
names = names.concat([name]).sort();
var length = names.length;
var found = false;
for(var i=0; i<length && !found; i++) {
if (names[i] == name) {
found = true;
}
}
var tr =table.insertRow(i);
var td = document.createElement("td");
td.className = PropertySheet.NameCell;
td.id= "name_"+name;
td.appendChild(document.createTextNode(name));
td.onclick = function () {
psheet.setSelected(this);
};
tr.appendChild(td);
td = document.createElement("td");
td.id = "value_"+name;
td.className = PropertySheet.ValueCell;
tr.appendChild(td);
this.textfields[name] = new TextField(this, td.id, name, "");
var psheet = this;
this.textfields[name].addChangeListener(function () {psheet.showCommitButtons();});
this.textfields[name].setError(false);
this.textfields[name].textChanged = true;
this.showCommitButtons();
}
}
}
};
PropertySheet.prototype.removeProperty = function () {
if (this.selectedProperty) {
this.deletedProperties[this.deletedProperties.length] = this.selectedProperty;
var selectedNameCell = document.getElementById("name_"+this.selectedProperty);
var tr = selectedNameCell.parentNode;
tr.style.display = "none";
this.showCommitButtons();
}
};
PropertySheet.prototype.setSelected = function (cell) {
var oldSelectedNameCell = document.getElementById("name_"+this.selectedProperty);
if (oldSelectedNameCell) {
oldSelectedNameCell.className = PropertySheet.NameCell;
}
if (cell) {
var property = cell.id.substring(cell.id.indexOf("_")+1, cell.id.length);
this.selectedProperty = property;
if (property) {
this.selectedTextField = this.textfields[property];
var selectedNameCell = document.getElementById("name_"+this.selectedProperty);
selectedNameCell.className = PropertySheet.CellSelected;
}
} else {
this.selectedProperty = null;
this.selectedTextField = null;
}
};
PropertySheet.prototype.displayPropertySheet = function (selection) {
this.selection = selection;
this.selectedProperty = null;
this.deletedProperties = [];
this.addedProperties = [];
var p = "";
try {
if (selection.length == 1) {
var oldId = this.selectionId;
this.selectionId = selection[0].getObjectID();
p = "<table border='0' cellspacing='0' cellpadding='0'><tr><td>";
p += "<table class='"+PropertySheet.Table+"' id='"+this.tableId+"'>";
p += "<tr>";
p += "<td colspan='2' class='"+PropertySheet.TitleCell+"'>";
p+="<table width='100%' border='0' cellspacing='0' cellpadding='0'><tr><td class='"+PropertySheet.Text+"' style='font-weight:bold'>"+jviews.messages.demo.ganttFacelet.propertySheet.dataProperties+"</td>";
p += "<td align='right' class='"+PropertySheet.Text+"' id='addProperty' style='cursor:pointer'><span>+</span></td>";
p += "<td align='right' class='"+PropertySheet.Text+"' id='removeProperty' style='cursor:pointer'><span>x</span></td></tr></table></td>";
p += "</tr>";
var names = selection[0].getObjectPropertyNames().sort();
var length = names.length;
var type = selection[0].getObjectType();
for(var i=0; i<length; i++){
var name = names[i];
p += "<tr>";
p += "<td class='"+PropertySheet.NameCell+"' id='name_"+name+"'>" + name + "</td>";
p += "<td class='"+PropertySheet.ValueCell+"' id='value_"+name+"'></td>";
p += "</tr>";
}
p +="</table>";
p += "</td></tr><tr><td>";
p +="<span id='"+this.commitId+"' style='display:none;'></span>";
p += "</td></tr></table>";
var span = document.getElementById(this.spanId);
span.innerHTML = p;
var addButton = document.getElementById("addProperty");
var removeButton = document.getElementById("removeProperty");
var psheet = this;
addButton.onclick = function() {
psheet.addProperty();
};
removeButton.onclick = function () {
psheet.removeProperty();
};
//create textfields
this.commitButtonsShown = false;
var oldtf = this.textfields;
this.textfields = [];
for(var i=0; i<length; i++){
var name = names[i];
var value = this.format(type, name, selection[0].getObjectProperty(name));
var nameCell = document.getElementById("name_"+name);
nameCell.onclick = function () {
psheet.setSelected(this);
};
var tf = new TextField(this, "value_"+name, name, value);
var commit;
// previously errored on same object? Let's give a chance to retry
// so keep old value
if (oldId == this.selectionId && oldtf && oldtf[name] && oldtf[name].hasError()) {
tf.changed(value, oldtf[name].text);
tf.setError(true);
commit = true;
}
tf.addChangeListener(function () {psheet.showCommitButtons();});
this.textfields[name] = tf;
}
this.createCommitButtons();
// we have some pending errors let's show commit button
if (commit)
this.showCommitButtons();
} else {
var span = document.getElementById(this.spanId);
span.innerHTML = "";
}
} catch (e) {
alert(jviews.messages.demo.ganttFacelet.propertySheet.errorOccuredDuringRefresh+ e.toString());
}
};
PropertySheet.prototype.showCommitButtons = function () {
var span = document.getElementById(this.commitId);
span.style.display = "block";
var okId = this.tableId + "_ok";
var ok = document.getElementById(okId);
ok.focus();
};
PropertySheet.prototype.hideCommitButtons = function () {
var span = document.getElementById(this.commitId);
span.style.display = "none";
};
PropertySheet.prototype.createCommitButtons = function () {
var span = document.getElementById(this.commitId);
var okId = this.tableId + "_ok";
var koId = this.tableId + "_ko";
var p = "<input type='button' id='"+okId+"' autocomplete='off' class='psheet-text' value='"+jviews.messages.demo.ganttFacelet.propertySheet.commitBtn+"' />";
p += "<input type='button' id='"+koId+"' autocomplete='off' class='psheet-text' value='"+jviews.messages.demo.ganttFacelet.propertySheet.cancelBtn+"' />";
span.innerHTML = p;
var ok = document.getElementById(okId);
var psheet = this;
ok.onmouseup = function () {
psheet.commitChanges();
};
ok.onkeypress = function(e) {
var keyCode;
if (e) {
keyCode = e.keyCode;
} else {
keyCode = event.keyCode;
}
if (keyCode==13) {
this.onmouseup();
return false;
}
return true;
};
var ko = document.getElementById(koId);
ko.onmouseup = function () {
psheet.cancelChanges();
};
ko.onkeypress = function(e) {
var keyCode;
if (e) {
keyCode = e.keyCode;
} else {
keyCode = event.keyCode;
}
if (keyCode==13) {
this.onmouseup();
return false;
}
return true;
};
};
PropertySheet.prototype.cancelChanges = function () {
for(var i in this.textfields){
var tf = this.textfields[i];
if (tf.hasChanged()) {
tf.revert();
}
if (tf.hasError()) {
tf.setError(false);
}
}
var length = this.deletedProperties.length;
for (var i=0; i<length; i++) {
var p = this.deletedProperties[i];
var selectedNameCell = document.getElementById("name_"+p);
var tr = selectedNameCell.parentNode;
if (IlvBrowserInfo.instance.ie5up) {
tr.style.display = "block";
} else {
tr.style.display = "table-row";
}
}
length = this.addedProperties.length;
for (i=0; i<length; i++) {
p = this.addedProperties[i];
selectedNameCell = document.getElementById("name_"+p);
if(selectedNameCell) {
tr = selectedNameCell.parentNode;
tr.parentNode.removeChild(tr);
}
}
this.addedProperties = [];
this.deletedProperties = [];
this.hideCommitButtons();
};
PropertySheet.prototype.commitChanges = function () {
var nbChanges = 0;
var type = this.selection[0].getObjectType();
for(var i in this.textfields){
var tf = this.textfields[i];
if (tf.hasChanged()) {
nbChanges++;
var value = this.parse(type, tf.getName(), tf.getText())
this.selection[0].setObjectProperty(tf.getName(), value);
}
}
var length = this.deletedProperties.length;
for (var i=0; i<length; i++) {
var p = this.deletedProperties[i];
this.selection[0].setObjectProperty(p, null);
nbChanges++;
}
if (nbChanges > 0) {
this.selectionManager.psheet = this;
this.selectionManager.commitSelectionProperties(true, error_handler);
}
};
function error_handler(errors) {
var psheet = this.psheet;
// in any case erase flags
for (var i in psheet.textfields) {
var tf = psheet.textfields[i];
if (tf.hasChanged()) {
tf.textChanged = false; // no more change
tf.label.className=TextField.regularStyleClass;
tf.setError(false);
}
}
// are there any errors?
if (errors && errors.length > 0) {
// simple case we just got one selected object => one possible error object
// look for all failing properties
var propertyNames = errors[0].getObjectPropertyNames();
for (var i = 0; i < propertyNames.length; i++) {
var tf = psheet.textfields[propertyNames[i]];
tf.textChanged = true;
tf.setError(true);
// was that a delete property? Let's show it again
if (psheet.deletedProperties) {
var length = psheet.deletedProperties.length;
for (var j = 0; j < length; j++) {
var p = psheet.deletedProperties[j];
if (p == propertyNames[i]) {
var selectedNameCell = document.getElementById("name_"+p);
var tr = selectedNameCell.parentNode;
if (IlvBrowserInfo.instance.ie5up) {
tr.style.display = "block";
} else {
tr.style.display = "table-row";
}
psheet.deletedProperties.splice(j, 1);
break;
}
}
}
}
}
}
/**
* Formats a marshalled property value to a representation suitable for display.
* This is the inverse operation of <code>format</code>.
* The following should hold true:
* <ul>
* <li><code>value == parse(type, name, format(type, name, value))</code></li>
* <li><code>x == format(type, name, parse(type, name, x))</code></li>
* </ul>
* Note that in some cases, such as with numbers and dates, accuracy is
* lost when formatting.
*
* @param type Type of the object containing the property.
* @param name Name of the property.
* @param value Value of the property.
*/
PropertySheet.prototype.format = function(type, name, value) {
if (type=="activity" && (name == "endTime" || name == "startTime")) {
return this.formatDate(value);
}
return value;
}
/**
* Parses a display value and returns the corresponding marshalled value.
* This is the inverse operation of <code>format</code>.
* The following should hold true:
* <ul>
* <li><code>value == parse(type, name, format(type, name, value))</code></li>
* <li><code>x == format(type, name, parse(type, name, x))</code></li>
* </ul>
* Note that in some cases, such as with numbers and dates, accuracy is
* lost when formatting.
*
* @param type Type of the object.
* @param name Name of the property.
* @param value Value of the property.
*/
PropertySheet.prototype.parse = function(type, name, value) {
if (type=="activity" && (name == "endTime" || name == "startTime")) {
return this.parseDate(value);
}
return value;
}
/**
* Formats a marshalled representation of a date into a formatted string
* suitable for display.
*
* @param value A <code>string</code> value representing the number of
* milliseconds since the Unix epoch.
* @return A formatted <code>string</code> representation of the date, or an
* empty string when <i>date</i> is <code>null</code>.
*/
PropertySheet.prototype.formatDate = function(value) {
return value == null ? null :value;
}
/**
* Parses an string representation of a date and returns the corresponding
* marshalled representation.
*
* @param value A <code>string</code> value representing a formatted date.
* @return A <code>string</code> representing the number of milliseconds since
* the Unix epoch or <code>null</code> when <i>value</i> is an empty
* string.
*/
PropertySheet.prototype.parseDate = function(value) {
return value == "" ? null :value;
}