Wednesday, October 14, 2009

 

jQuery, how do I love thee?

So I spent a few days doing some JavaScript, which is not my favourite thing. Or at least it didn't use to be. But now that I have discovered JQuery, I gotta say, it's a whole lot more tolerable than it used to be.

JQuery makes some things that I would previous have considered all but impossible downright easy. Take drag-and-drop inside the browser, f'rinstance. To do it yourself, you'd have to deal with, jeez, I don't even know what, DOM craziness, layers, who knows. In jQuery? Well, lemme give you a quick example, stripped of all the actual business logic, of a drag-and-drop form builder:


<html><head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.js"></script>

<style type="text/css">
.columns:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
* html .columns {height: 1%;}
.columns{ display:inline-block; }
.columns{ display:block; }
.columns .column{
float:left;
display:inline;
min-height:360px;
}
.columns .last{ float:right; }
.columns .first{ width:180px; background-color:#ffeeee; }
.columns .second{ width:280px; margin-left:10px; background-color:#eeffee; }
.columns .last{ width:210px; background-color:#eeeeff}

.footers{ display:inline-block; }
.footers{ display:block; }
.footers .footer{
float:left;
display:inline;
}
.footers .last{ float:right; }
.footers .first{ width:180px; background-color:#eeeeee; }
.footers .second{ width:280px; margin-left:10px; background-color:#eeeeee; }
.footers .last{ width:210px; background-color:#eeeeee}

.formLineEdit { text-align: right; }
.optionLabel { float:right; text-align: right; }
.label { font-weight: bold; vertical-align: text-top; }
.formInput { text-align: right; vertical-align: text-top; }
.editHeader { text-align: right; }
.selectOption { text-align: right; }
#error { text-align: center; color: #ff0000; }
#success { text-align: center; color: #00ff00; }
#listForms { float: left; text-align: left; }
#viewHelp { float: right; text-align: right; }
#inputOptions { text-align: right; }
#detailHeader { text-align: right; }
#formName {background-color: #eeeeee; }
#formVersionNumber {background-color: #eeeeee; }
#formSubmitButton {text-align:right; background-color: #eeeeee; }
</style>

<script>
var totalItems=0;
var currentlyEditing=null;
var lastEdited=null;

$(function() {
//make divs created out of XML clickable
var destClicked=false;
$("#destination").mousedown( function() {
if (!destClicked) { //only do this once, or it might get messy
$("#destination").children().each( function() {
$(this).bind("click", function() {
showEditDetailsFor($(this));
});
});
}
destClicked=true;
});

//set up drag-and-drop stuff
$("#textInput").draggable(
{ connectToSortable:'#destination',
cursor:'move',
helper:'clone',
}
);
$("#longText").draggable(
{ connectToSortable:'#destination',
cursor:'move',
helper:'clone',
}
);
$("#selectMultiple").draggable(
{ connectToSortable:'#destination',
cursor:'move',
helper:'clone',
}
);
$("#selectOne").draggable(
{ connectToSortable:'#destination',
cursor:'move',
helper:'clone',
}
);
$("#destination").sortable(
{
change: function(event, ui) {
ui.placeholder.css({visibility: 'visible', border : '2px solid yellow'});
},
start: function(event, ui) {
ui.placeholder.css({visibility: 'visible', border : '2px solid yellow'});
var tempID=ui.item.attr("id");
if (tempID.indexOf("_")==-1) {
tempID=tempID+"_"+totalItems++;
ui.item.attr({id:tempID});
}
},
stop: function(event, ui) {
//load element details, and ensure they'll show up again when this item is clicked
showEditDetailsFor(ui.item);
ui.item.bind("click", function() {
showEditDetailsFor(ui.item);
});
},
}
);
});

function showEditDetailsFor ( object ) {
// object.effect("highlight", {}, 3000);
currentlyEditing=object.attr("id");
if (currentlyEditing==lastEdited)
return;

$(".formLineEdit").hide();
$("#inputOptions").show();

if (object.attr("id").indexOf("textInput")==0) {
var inputLabel = $.trim(object.find(".label").text());
var inputID = object.find("input[name=inputID]").val();
if (inputLabel!="Text Input" || object.find("input[name=inputID]").attr("name")!="inputID") {
$("#textInputEdit").find("input[name=textInputLabel]").val(inputLabel);
$("#textInputEdit").find("input[name=textInputValue]").val(inputID);
}
$("#textInputEdit").show();
}
else if (object.attr("id").indexOf("longText")==0) {
var inputLabel = $.trim(object.find(".label").text());
var inputID = object.find("textarea:first").val();
if (inputLabel!="Long Text" || inputID!="") {
$("#longTextEdit").find("input[name=longTextLabel]").val(inputLabel);
$("#longTextEdit").find("input[name=longTextValue]").val(inputID);
}
$("#longTextEdit").show();
}
else if (object.attr("id").indexOf("selectMultiple")==0) {
var inputLabel = $.trim(object.find(".label:first").text());
var inputID = object.find("input:last").attr("name");
if (inputLabel!="Select Multiple" || inputID!="selectMulti") {
$("#selectMultiEdit").find("input[name=selectMultiLabel]").val(inputLabel);
$("#selectMultiEdit").find("input[name=selectMultiValue]").val(inputID);
blankOption=$("#selectMultiEdit > .selectOption").remove();
var addedChild=false;
object.children(".formInput").each( function() {
optionClone=blankOption.clone();
var optionLabel=$(this).find(".optionLabel").text();
optionClone.find("input[name=multiOptionLabel]").val(optionLabel);
var optionValue=$(this).find("input:first").attr("value");
optionClone.find("input[name=multiOptionValue]").val(optionValue);
cloneRemoveButton = optionClone.find("input[name=removeSelectMultiOption]");
cloneRemoveButton.bind("mouseup", function() {
$(this).parent().remove();
});
$("#selectMultiEdit").append(optionClone);
addedChild=true;
});
if (!addedChild)
$("#selectMultiEdit").append(blankOption);
} //don't show defaults
$("#selectMultiEdit").show();
}
else if (object.attr("id").indexOf("selectOne")==0) {
var inputLabel = $.trim(object.find(".label:first").text());
var inputID = object.find("input:last").attr("name");
if (inputLabel!="Select One" || inputID!="selectOne") {
$("#selectOneEdit").find("input[name=selectOneLabel]").val(inputLabel);
$("#selectOneEdit").find("input[name=selectOneValue]").val(inputID);
blankOption=$("#selectOneEdit > .selectOption").remove();
var addedChild=false;
object.children(".formInput").each( function() {
optionClone=blankOption.clone();
var optionLabel=$(this).find(".optionLabel").text();
optionClone.find("input[name=oneOptionLabel]").val(optionLabel);
var optionValue=$(this).find("input:first").attr("value");
optionClone.find("input[name=oneOptionValue]").val(optionValue);
cloneRemoveButton = optionClone.find("input[name=removeSelectOneOption]");
cloneRemoveButton.bind("mouseup", function() {
$(this).parent().remove();
});
$("#selectOneEdit").append(optionClone);
addedChild=true;
});
if (!addedChild)
$("#selectOneEdit").append(blankOption);
} //don't show defaults
$("#selectOneEdit").show();
}
lastEdited=currentlyEditing;
}


</script>

</head>
<body>
<center><H3>Form Builder</H3></center>
<div id="success"></div>
<div id="error"></div>

<div id="header">
 
</div>
<P/>
<div class="columns">
<div id="source" class="column first">
<b>Form Elements</b><HR/>
<div id="textInput" class="formLine">
<div class="label">Text Input</div><div class="formInput"><input name="inputID" /></div>
</div>
<HR/>
<div id="longText" class="formLine">
<div class="label">Long Text</div>
<div class="formInput"><textarea name="textarea"></textarea></div>
</div>
<HR/>
<div id="selectMultiple" class="formLine">
<div class="label">Select Multiple</div>
<div class="formInput"> 
<input type="checkbox" name="selectMulti" value="one" />
<div class="optionLabel">One</div>
</div>
<div class="formInput"> 
<BR/><input type="checkbox" name="selectMulti" value="two" />
<div class="optionLabel">Two</div>
</div>
</div>
<HR/>
<div id="selectOne" class="formLine">
<div class="label">Select One</div>
<div class="formInput"> 
<input type="radio" name="selectOne" value="one" />
<div class="optionLabel">One</div>
</div>
<div class="formInput"> 
<BR/><input type="radio" name="selectOne" value="two" />
<div class="optionLabel">Two</div>
</div>
</div>
</div> <!--source-->
<div id="middle" class="column second">
<b>Form</b> (drag elements here)
<HR/>
<div id="destination"> </div>
<HR/>
</div>
<div id="details" class="column last">
<div id="detailHeader"><b>Element Details</b><HR/></div>
<div id="textInputEdit" class="formLineEdit">
<div class="editHeader">
<b>Text Input</b>
<input type="submit" name="textInputSubmit" value="Done" />
<input type="submit" name="delete" value="Delete" />
</div>
<BR/><a href="/formHelp#labels" target="_blank">Label</a><input name="textInputLabel" type="text" />
<BR/><a href="/formHelp#ids" target="_blank">ID</a><input name="textInputValue" />
</div>
<div id="longTextEdit" class="formLineEdit">
<div class="editHeader">
<b>Long Text</b>
<input type="submit" name="longTextSubmit" value="Done" />
<input type="submit" name="delete" value="Delete" />
</div>
<BR/><a href="/formHelp#labels" target="_blank">Label</a><input name="longTextLabel" />
<BR/><a href="/formHelp#ids" target="_blank">ID</a><input name="longTextValue" />
</div>
<div id="selectMultiEdit" class="formLineEdit">
<div class="editHeader">
<b>Select Multiple</b>
<input type="submit" name="selectMultiSubmit" value="Done" />
<input type="submit" name="delete" value="Delete" />
</div>
<BR/><a href="/formHelp#labels" target="_blank">Label</a><input name="selectMultiLabel" />
<BR/><a href="/formHelp#ids" target="_blank">ID</a><input name="selectMultiValue" />
<BR/><input type="submit" name="addSelectMultiOption" value="Add Option" />
<HR/>
<div id="selectMultiOption" class="selectOption">
<i>Option</i>: <a href="/formHelp#editSelects" target="_blank">Name</a> <input name="multiOptionLabel" size=12/>
<BR/><a href="/formHelp#editSelects" target="_blank">Value</a><input name="multiOptionValue" size=12/>
<BR/><input type="submit" name="removeSelectMultiOption" value="Remove" />
<HR/>
</div>
</div>
<div id="selectOneEdit" class="formLineEdit">
<div class="editHeader">
<b>Select One</b>
<input type="submit" name="selectOneSubmit" value="Done" />
<input type="submit" name="delete" value="Delete" />
</div>
<BR/><a href="/formHelp#labels" target="_blank">Label</a><input name="selectOneLabel" />
<BR/><a href="/formHelp#ids" target="_blank">ID</a><input name="selectOneValue" />
<BR/><input type="submit" name="addSelectOneOption" value="Add Option" />
<HR/>
<div id="selectOneOption" class="selectOption">
<i>Option</i>: <a href="/formHelp#editSelects" target="_blank">Name</a><input name="oneOptionLabel" size=12/>
<BR/><a href="/formHelp#editSelects" target="_blank">Value</a><input name="oneOptionValue" size=12/>
<BR/><input type="submit" name="removeSelectOneOption" value="Remove" />
<HR/>
</div>
</div>
</div> <!-- details-->
</div> <!--columns-->
<P/>
<div class="footers">
<div id="formName" class="footer first"><b>Form Name</b>: <input name="formName" value="default" size=10 length=64 /></div>
<div id="formVersionNumber" class="footer second">
<b>Version Number</b>:
<input name="formVersion">
</div>
<div id="formSubmitButton" class="footer last"><input type="submit" name="saveForm" value="Finished - Save Form!" /></div>
</div>

</body>
</html>


Pretty slick, eh?

What you do is, you drag form elements from the first column into the second column, where clones are inserted. (That way the element stays in the first column, so you can have an arbitrary number of instances in the second column.) One key thing to note is that clones do not inherit the clonee's bindings, so you have to bind any events after they're created, as shown above in the "stop" event of the "sortable" definition.

I would try to explain more, but either you already know JQuery reasonably well, in which case the above is probably pretty clear already, or you don't, in which case it will be Greek. So - just copy and paste the above as HTML, launch it in a browser, and play around with it; it should drag and drop right out of the box.

Labels: , , , , , , , , ,


Comments:

Thanks for sharing this informative content.,
Leanpitch provides online training in Scrum Master Certification during this lockdown period everyone can use it wisely.
Join Leanpitch 2 Days CSM Certification Workshop in different cities.
CSM online

CSM online certification
 

Thanks for sharing this informative content.,
Leanpitch provides online training in Scrum Master Certification during this lockdown period everyone can use it wisely.
Join Leanpitch 2 Days CSM Certification Workshop in different cities.
CSM online training

CSM training online
 
Thanks for sharing this informative content.,
Leanpitch provides online training in Agile team facilitation during this lockdown period everyone can use it wisely.

Agile team facilitation

ICP ATF

Team facilitator Agile

Agile facilitator

Team facilitator in Agile

ICAGILE ATF

 
Thanks for sharing this informative content.,
Leanpitch provides online training in Agile team facilitation ,everyone can use it wisely.
ICP ATF

Agile facilitator
 

Thanks for sharing this informative content.,
Leanpitch provides online training in Agile team facilitation ,everyone can use it wisely.
Team facilitator in Agile

ICP ATF

 
Thanks for sharing this informative content.,
Turient is an All-in-one platform for all our teaching needs. If Teaching is your passion ,enabling is ours
Read the Informative blog - 11 Free Teaching Tools for Online Teachers
11 Free Teaching Tools for Online Teachers
Free Teaching Tools


 
먹튀검증 I know this web page gives quality based articles or reviews and extra information


 
스포츠토토 These are genuinely enormous ideas in regarding blogging .


 
I believe this is among the so much significant information for me.
And i'm happy reading your article. 온라인카지노


 
Ford Edge Titanium 2019.
Ford Edge ford titanium ecosport Titanium 2019. thaitanium Titanium Stone is designed for a high performance solid-steel titanium pipe frame titanium app for its design, Color: Stainless steelRisk Type: titanium helix earrings $69.99In stock
 

Post a Comment

Subscribe to Post Comments [Atom]





<< Home

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]