var InPlaceEditor = {};
InPlaceEditor.Local = Class.create();
Object.extend(Object.extend(InPlaceEditor.Local.prototype, Ajax.InPlaceEditor.prototype), {
enterHover: function() {},
leaveHover: function() {},
onComplete: function() {},
handleFormSubmission: function(e) {
var value = $F(this._controls.editor);
RSpec.addStockStep(value);
this.element.innerHTML = value;
this.leaveEditMode();
if (e) Event.stop(e);
}
});
var RSpec = {
stockSteps: function() {
return $('stock_steps').childElements().map(function(li){
return li.innerHTML;
}).sort();
},
addStockStep: function(stockStep) {
if(!this.stockSteps().include(stockStep)) {
$('stock_steps').appendChild(Builder.node('li', {}, stockStep));
}
},
makeParamEditors: function() {
$$('span.param').each(function(span) {
span.removeClassName('param');
span.addClassName('param_editor');
new InPlaceEditor.Local(span, null, {});
});
},
setId: function(e) {
if(!this.currentId) this.currentId = 0;
this.currentId++;
e.id = "id_" + this.currentId;
},
applyUi: function() {
this.setUpTogglers();
this.makeParamEditors();
var currentId = 0;
$$('ul.steps').each(function(ul) {
RSpec.setId(ul);
var footer = document.createElement("p");
var addStepLink = document.createElement("a");
addStepLink.href = "#";
addStepLink.appendChild(document.createTextNode('Add step'));
footer.appendChild(addStepLink);
ul.parentNode.appendChild(footer);
Sortable.create(ul, {
scroll: window
});
/* Disable for now - it messes with the autocomplete's visibility (zIndex galore)
Droppables.add(footer, {
hoverclass: 'wastebin',
onDrop: function(li, droppable, evt) {
li.remove();
}
});
*/
Event.observe(addStepLink, 'click', function() {
var form = Builder.node('form', {});
var li = Builder.node('li', {className: 'new'});
var input = Builder.node('input', {}, 'New step here');
var autoComplete = Builder.node('div', {className: 'auto_complete'}, '');
li.appendChild(form);
form.appendChild(input);
form.appendChild(autoComplete);
ul.appendChild(li);
Sortable.destroy(ul);
Sortable.create(ul);
Event.observe(form, 'submit', function(e) {
var value = input.value;
Element.remove(this);
li.innerHTML = value.gsub(/(\$[a-z]*)/, '#{1}');
RSpec.makeParamEditors();
if (e) Event.stop(e);
});
var ac = new Autocompleter.Local(input, autoComplete, RSpec.stockSteps(), {});
input.focus();
});
})
},
setUpTogglers: function() {
$$('dt').each(function(dt) {
var dd = dt.parentNode.getElementsByTagName('dd')[0];
dt.onclick = function(){
dd.toggle();
}
});
}
};
var StoryDom = {
narrativeText: function(s) {
return s.split(/\n/m).map(function(line){
if(line == "" || line.match(/^\s+$/) ) {
return null;
} else {
return " " + (line.gsub(/^\s+/, '').gsub(/
/, "\n").gsub(/
/, "\n"));
}
}).compact().join("");
},
stepText: function(s) {
return s.gsub(/]*>([^<]*)<\/span>/, "#{1}");
},
scenario: function(dl) {
var scenario = ' Scenario: ' + dl.getElementsByTagName('dt')[0].innerHTML + '\n';
scenario += $A(dl.getElementsByTagName('li')).map(function(li){
return ' ' + StoryDom.stepText(li.innerHTML);
}).join("\n") + "\n";
return scenario;
},
story: function() {
var dl = $$('dl.story')[0];
var story = 'Story: ' + dl.getElementsByTagName('dt')[0].innerHTML + '\n\n';
story += this.narrativeText(dl.getElementsByTagName('p')[0].innerHTML) + '\n';
story += $A(dl.getElementsByTagName('dl')).map(function(scenarioDl){
return StoryDom.scenario(scenarioDl);
}).join("\n");
return story;
},
save: function() {
new Ajax.Request('stories', {
postBody: this.story()
});
}
};
Event.observe(window, 'load', function() {
RSpec.applyUi();
});