1 <script type="text/javascript">
2 var snapToGrid = false;
4 // Dimensions of the template space, in pixels
5 var templateDimensions;
7 // Previous dimensions of the template space, in cm
8 var previousTemplateDimensions;
10 // Number of pixels per cm
13 // Id of the background used
14 var backgroundId = -1;
16 // Number of pixels, both horizontal and vertical, that are between the top left corner
17 // and the position where items are inserted
18 var initialOffset = pixelsPerCm;
20 // Id of the next element to be inserted
23 // Common parts of many elements
24 var elementCommon1 = '<table border="2" cellpadding="0" cellspacing="0" style="cursor:move;" width="200"><tbody><tr><td align="center">';
25 var elementCommon2 = '</td></tr></tbody></table>';
27 // Last selected item (holds the div for that item)
28 var lastSelectedDiv = null;
30 // Translation dictionary from key to name in current language.
31 var translate = ${translateName};
33 // List of badge template items
37 function Item(itemId, key) {
40 this.x = initialOffset;
41 this.y = initialOffset;
42 this.fontFamily = "Times New Roman";
45 this.textAlign = "Center";
47 this.fontSize = "medium";
49 this.text = "(Type your text)" // Only for fixed text items
51 // The following attributes have no meaning to the server
52 this.selected = false;
53 this.fontFamilyIndex = 0;
55 this.textAlignIndex = 2; //Center
57 this.fontSizeIndex = 3; //Medium
60 Item.prototype.toHTML = function () {
61 return '<table border="2" cellpadding="0" cellspacing="0"' +
62 ' width="' + this.width + '"' +
63 ' style="background-color: '+(this.selected ? "#ccf" : "#fff")+';cursor:move; font-weight:' + (this.bold ? 'bold' : 'normal') + '; font-style:' + (this.italic ? 'italic' : 'normal') +
64 '; text-align: ' + this.textAlign.replace('Justified', 'justify') + ';"' +
65 '><tbody><tr><td><span style="color:' + this.color + '; font-family: ' + this.fontFamily + '; font-size:' + this.fontSize + ';">' +
66 (this.key == "Fixed Text" ? this.text : translate[this.key]) +
67 '</span></td></tr></tbody></table>';
71 function Dimensions(width, height) {
76 // This function creates a new draggable div
77 function createDiv() {
79 // -a unique id, which is a natural number (0, 1, 2, ...)
80 // -a type (stored in the name attribute)
81 // -absolute x,y position
82 // -an inner HTML with its content
85 var newDiv = $('<div/>', {
89 left: initialOffset + 'px',
90 top: initialOffset + 'px',
92 }).appendTo('#templateDiv');
95 containment: '#templateDiv',
96 stack: '#templateDiv > div',
98 drag: function(e, ui) {
100 ui.position.left = Math.floor(ui.position.left / 10) * 10;
101 ui.position.top = Math.floor(ui.position.top / 10) * 10;
104 stop: function(e, ui) {
105 items[this.id].x = ui.position.left;
106 items[this.id].y = ui.position.top;
113 // This function inserts the selected element in the blank space where badge template designing takes place
114 function insertElement() {
115 var newDiv = createDiv();
116 // We set the inner html of the div depending on the type of item inserted
117 switch($('#elementList').val()) {
121 if (!lastSelectedDiv) {
122 markSelected(newDiv);
128 function removeElement() {
129 if (lastSelectedDiv) {
130 items[lastSelectedDiv.attr('id')] = false;
131 lastSelectedDiv.remove();
132 $('#selection_text').html('');
133 lastSelectedDiv = null;
134 $('#removeButton').prop('disabled', true);
138 function markSelected(newSelectedDiv) {
139 // Change the text that says which item is selected
140 var id = newSelectedDiv.attr('id');
141 $('#selection_text').html(translate[items[id].key]);
143 // TODO: add check to see if there's a table inside and not an image
145 // Change the background color of the old selected item and the new selected item
146 if (lastSelectedDiv) {
147 var lastId = lastSelectedDiv.attr('id');
148 items[lastId].selected = false;
149 lastSelectedDiv.find('> table').css('backgroundColor', '#fff');
152 var newSelectedItem = items[id];
153 newSelectedItem.selected = true;
154 newSelectedDiv.find('> table').css('backgroundColor', '#ccf');
155 lastSelectedDiv = newSelectedDiv;
156 $('#removeButton').prop('disabled', false);
158 // Change the selectors so that they match the properties of the item
159 $('#alignment_selector').prop('selectedIndex', newSelectedItem.textAlignIndex);
160 $('#font_selector').prop('selectedIndex', newSelectedItem.fontFamilyIndex);
161 $('#size_selector').prop('selectedIndex', newSelectedItem.fontSizeIndex);
162 $('#style_selector').prop('selectedIndex', newSelectedItem.styleIndex);
163 $('#color_selector').prop('selectedIndex', newSelectedItem.colorIndex);
164 $('#width_field').val(newSelectedItem.width / pixelsPerCm);
165 if (newSelectedItem.key == "Fixed Text") {
166 $('#fixed_text_field').val(newSelectedItem.text).prop('disabled', false);
167 $('#changeText').prop('disabled', false);
169 $('#fixed_text_field').val("").prop('disabled', true);
170 $('#changeText').prop('disabled', true);
174 function updateRulers() {
175 if (templateDimensions.width > previousTemplateDimensions.width) {
176 var hRuler = $('#horizontal_ruler');
177 for (var i = Math.ceil(previousTemplateDimensions.width / pixelsPerCm); i < Math.ceil(templateDimensions.width / pixelsPerCm); i++) {
180 }).html('<img src="${ baseURL }/images/ruler/rulerh' + i + '.png" align="center"/>').appendTo(hRuler);
183 else if (templateDimensions.width < previousTemplateDimensions.width) {
184 for (var i = Math.ceil(previousTemplateDimensions.width / pixelsPerCm); i > Math.ceil(templateDimensions.width / pixelsPerCm); i--) {
185 $('#rulerh' + (i - 1)).remove();
189 if (templateDimensions.height > previousTemplateDimensions.height) {
190 var vRuler = $('#vertical_ruler');
191 for (var i = Math.ceil(previousTemplateDimensions.height / pixelsPerCm); i < Math.ceil(templateDimensions.height / pixelsPerCm); i++) {
194 }).append('<td><img src="${ baseURL }/images/ruler/rulerv' + i + '.png" align="center"/></td>').appendTo(vRuler);
197 else if (templateDimensions.height < previousTemplateDimensions.height) {
198 for (i = Math.ceil(previousTemplateDimensions.height / pixelsPerCm); i > Math.ceil(templateDimensions.height / pixelsPerCm); i--) {
199 $('#rulerv' + (i - 1)).remove();
204 // This function displays all the items in the 'items' array on the screen
205 // If there are already some items being displayed, it does not erase them
206 function displayItems() {
207 $.each(items, function(i, item) {
208 var newDiv = createDiv();
213 newDiv.html(item.toHTML());
215 markSelected(newDiv);
221 function changeTemplateSize() {
222 var tpl = $('#templateDiv');
223 tpl.width($('#badge_width').val() * pixelsPerCm);
224 tpl.height($('#badge_height').val() * pixelsPerCm);
225 previousTemplateDimensions.width = templateDimensions.width;
226 previousTemplateDimensions.height = templateDimensions.height;
227 templateDimensions = new Dimensions($('#badge_width').val() * pixelsPerCm, $('#badge_height').val() * pixelsPerCm);
229 if (backgroundId != -1) {
230 var url = $('#background').attr('src');
231 $('#background').remove();
232 displayBackground(url);
238 if (lastSelectedDiv) {
239 lastSelectedDiv.css('left', 0);
240 items[lastSelectedDiv.attr('id')].x = 0 + "px";
244 if (lastSelectedDiv) {
245 lastSelectedDiv.css('left', (templateDimensions.width - lastSelectedDiv.width() - 1) + "px"); // -1 because of the table border
246 items[lastSelectedDiv.attr('id')].x = (templateDimensions.width - lastSelectedDiv.width() - 1) + "px";
250 if (lastSelectedDiv) {
251 lastSelectedDiv.css('left', ((templateDimensions.width - lastSelectedDiv.width() - 1) / 2) + "px");
252 lastSelectedDiv.css('top', ((templateDimensions.height - lastSelectedDiv.height() - 1) / 2) + "px");
253 items[lastSelectedDiv.attr('id')].x = ((templateDimensions.width - lastSelectedDiv.width() - 1) / 2) + "px";
254 items[lastSelectedDiv.attr('id')].y = ((templateDimensions.height - lastSelectedDiv.height() - 1) / 2) + "px";
258 if (lastSelectedDiv) {
259 lastSelectedDiv.css('top', 0);
260 items[lastSelectedDiv.attr('id')].y = 0 + "px";
264 if (lastSelectedDiv) {
265 lastSelectedDiv.css('top', (templateDimensions.height - lastSelectedDiv.height() - 1) + "px");
266 items[lastSelectedDiv.attr('id')].y = (templateDimensions.height - lastSelectedDiv.height() - 1) + "px";
273 if (lastSelectedDiv) {
274 var item = items[lastSelectedDiv.attr('id')];
275 item.fontFamily = $('#font_selector').val();
276 item.fontFamilyIndex = $('#font_selector').prop('selectedIndex');
277 lastSelectedDiv.html(item.toHTML());
281 if (lastSelectedDiv) {
282 var item = items[lastSelectedDiv.attr('id')];
283 item.color = $('#color_selector').val();
284 item.colorIndex = $('#color_selector').prop('selectedIndex');
285 lastSelectedDiv.html(item.toHTML());
288 alignment: function() {
289 if (lastSelectedDiv) {
290 var item = items[lastSelectedDiv.attr('id')];
291 item.textAlign = $('#alignment_selector').val();
292 item.textAlignIndex = $('#alignment_selector').prop('selectedIndex');
293 lastSelectedDiv.html(item.toHTML());
297 if (lastSelectedDiv) {
298 var item = items[lastSelectedDiv.attr('id')];
299 item.fontSize = $('#size_selector').val();
300 item.fontSizeIndex = $('#size_selector').prop('selectedIndex');
301 lastSelectedDiv.html(item.toHTML());
305 if (lastSelectedDiv) {
306 var item = items[lastSelectedDiv.attr('id')];
307 switch($('#style_selector').val()) {
328 item.styleIndex = $('#style_selector').prop('selectedIndex');
329 lastSelectedDiv.html(item.toHTML());
333 if (lastSelectedDiv) {
334 var item = items[lastSelectedDiv.attr('id')];
335 item.text = unescapeHTML($('#fixed_text_field').val());
336 $('#fixed_text_field').val(item.text);
337 lastSelectedDiv.html(item.toHTML());
341 if (lastSelectedDiv) {
342 var item = items[lastSelectedDiv.attr('id')];
343 item.width = $('#width_field').val() * pixelsPerCm;
344 lastSelectedDiv.html(item.toHTML());
351 if ($('#template_name').val() == '') {
352 alert("Please choose a name for the template");
356 template.push($('#template_name').val());
357 template.push(templateDimensions, pixelsPerCm);
358 template.push(backgroundId);
360 template.push(items);
361 $('#templateData').val(Json.write(template));
362 $('#saveForm').submit();
365 function displayBackground(backgroundURL) {
370 position: 'absolute',
373 height: templateDimensions.height + 'px',
374 width: templateDimensions.width + 'px',
377 $('#loadingIcon').hide();
378 }).appendTo('#templateDiv');
381 function removeBackground() {
382 if (backgroundId != -1) {
384 $('#background').remove();
388 function unescapeHTML(str) {
389 // taken from Prototype
390 return str.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '').replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&');
393 $(document).ready(function() {
394 // select items on mousedown
395 $('#templateDiv > div').live('mousedown', function() {
396 markSelected($(this));
399 // toggle grid/snap mode
400 $('#snap_checkbox').change(function() {
401 snapToGrid = this.checked;
404 $('#bgForm').ajaxForm({
407 success: function(data) {
408 if(data.status != 'OK') {
409 alert($T('An error occurred.'));
410 $('#loadingIcon').hide();
413 if (backgroundId != -1) {
414 $('#background').remove();
416 backgroundId = data.id;
417 displayBackground(data.url);
419 beforeSubmit: function() {
420 $('#loadingIcon').show();
424 $('#removeBackground').click(function(e) {
429 $('.moveButton').click(function(e) {
431 var dir = $(this).data('direction');
435 $('.attrButton').click(function(e) {
437 var attr = $(this).data('attr');
441 $('.attrSelect').change(function() {
442 var attr = $(this).data('attr');
446 $('#changeTemplateSize').click(function(e) {
448 changeTemplateSize();
451 $('#insertButton').click(function(e) {
456 $('#removeButton').click(function(e) {
461 $('#saveButton').click(function(e) {
468 <!-- CONTEXT HELP DIVS -->
469 <div id="tooltipPool" style="display: none">
470 <!-- Where is key? -->
471 <div id="features" class="tip">
472 <b>FullName can have four different formats:</b><br>
473 - <b>FullName</b>: Mr. DOE, Jonh<br>
474 - <b>Full Name (w/o title)</b>: DOE, Jonh<br>
475 - <b>FullName B</b>: Mr. Jonh Doe<br>
476 - <b>FullName B Full Name (w/o title)</b>: Jonh Doe<br>
479 <!-- END OF CONTEXT HELP DIVS -->
482 <div style="width:100%">
485 <table class="groupTable" cellpadding="0">
488 <td class="groupTitle" colspan="6">${titleMessage}</td>
491 <td class="titleCellTD">
492 <span class="titleCellFormat"> ${ _("Name")}</span>
495 <input id="template_name" size="50" name="Template Name">
499 <td class="titleCellTD">
500 <span class="titleCellFormat"> ${ _("Background")}<br><small>(${ _("picture file in jpeg, png or gif")})</small></span>
502 <form id="bgForm" action="${ saveBackgroundURL }" method="POST" enctype="multipart/form-data">
503 <td height="20px" NOWRAP align="left" colspan="3">
504 <input name="file" size="58" type="file">
505 <input class="btn" value="${ _("Send File")}" type="submit">
506 <input class="btn" type="button" value="${ _("Remove background")}" id="removeBackground">
509 <td width="100%" align="left" colspan="4">
510 <img id="loadingIcon" src=${loadingIconURL} width="20px" height="20px" style="display:none;">
514 <td class="titleCellTD" NOWRAP>
515 <span class="titleCellFormat">Badge Width (cm, decimals ok) </span>
518 <input id="badge_width" name="Badge Width" size="5">
520 <td class="titleCellTD" NOWRAP>
521 <span class="titleCellFormat">Badge Height (cm, decimals ok) </span>
524 <input id="badge_height" name="Badge Height" size="5">
525 <input class="btn" value="${ _("Change")}" type="button" id="changeTemplateSize">
533 <table class="groupTable" border="0" cellpadding="0" cellspacing="0">
539 <td width="220px" rowspan="2" valign="top"> <!-- Width attribute necessary so that the template design space doesn't move depending on selection text-->
540 <span class="titleCellFormat">${ _("Elements")}</span>
544 <input name="insertButton" id="insertButton" class="btn" value="${ _("Insert")}" type="button">
545 <input name="removeButton" id="removeButton" class="btn" value="${ _("Remove")}" type="button" disabled="disabled">
549 <select name="Template Elements List" id="elementList">
551 </select>${contextHelp('features' )}
556 ${ _("Selection")}: <span id="selection_text"></span>
567 <input name="Move Template Element Top Button" class="btn moveButton" value="${ _("Top")}" type="button" data-direction="top">
573 <input name="Move Template Element Left Button" class="btn moveButton" value="${ _("Left")}" type="button" data-direction="left">
576 <input name="Move Template Element Center Button" class="btn moveButton" value="${ _("Center")}" type="button" data-direction="center">
579 <input name="Move Template Element Right Button" class="btn moveButton" value="${ _("Right")}" type="button" data-direction="right">
585 <input name="Move Template Element Bottom Button" class="btn moveButton" value="${ _("Bottom")}" type="button" data-direction="bottom">
593 <input id="snap_checkbox" type="checkbox"/><label for="snap_checkbox">${ _("Snap to grid")}</label>
599 <td align="left" valign="bottom" height="22px"> <!-- height of the horizontal ruler images -->
600 <table border="0" cellpadding="0" cellspacing="0">
602 <tr id="horizontal_ruler">
610 <td valign="top" align="right" width="22px"> <!-- width of the vertical ruler image -->
611 <table border="0" cellpadding="0" cellspacing="0" align="right">
612 <tbody id="vertical_ruler">
617 <td align="left" valign="top">
618 <div id="templateDiv" style="width:425px;height:270px;position:relative;left:0px;top:0px"> <!-- put here the initial dimensions of templateDiv -->
619 <table border="1" style="border-style: none;" width="100%" height="100%" cellspacing="0" cellpadding="0">
632 <table class="groupTable" cellpadding="0" cellspacing="0">
637 <td colspan="3" rowspan="1" class="titleCellFormat"> ${ _("Attributes")}</td>
644 <td class="titleCellTD">
645 <span class="titleCellFormat"> ${ _("Font")} </span>
649 <select id='font_selector' name="Template Element Font" class="attrSelect" data-attr="font">
650 <optgroup label="${ _('Normal Fonts') }">
651 <option>Times New Roman</option>
652 <option>Courier</option>
653 <option>Sans</option>
655 <optgroup label="${ _('Special Character Fonts') }">
656 <option>LinuxLibertine</option>
657 <option>Kochi-Mincho</option>
658 <option>Kochi-Gothic</option>
659 <option>Uming-CN</option>
661 <option>Bitstream Cyberbit</option>
662 <option>Free Serif</option>
668 <td class="titleCellTD">
669 <span class="titleCellFormat"> ${ _("Color")} </span>
673 <select id='color_selector' name="Template Element Color" class="attrSelect" data-attr="color">
674 <option value="black"> ${ _("black")}</option>
675 <option value="red"> ${ _("red")}</option>
676 <option value="blue"> ${ _("blue")}</option>
677 <option value="green"> ${ _("green")}</option>
678 <option value="yellow"> ${ _("yellow")}</option>
679 <option value="brown"> ${ _("brown")}</option>
680 <option value="gold"> ${ _("gold")}</option>
681 <option value="pink"> ${ _("pink")}</option>
682 <option value="gray"> ${ _("gray")}</option>
683 <option value="white"> ${ _("white")}</option>
691 <td class="titleCellTD">
692 <span class="titleCellFormat"> ${ _("Style")} </span>
696 <select id='style_selector' name="Template Element Style" class="attrSelect" data-attr="style">
697 <option value="normal"> ${ _("Normal")}</option>
698 <option value="bold"> ${ _("Bold")}</option>
699 <option value="italic"> ${ _("Italic")}</option>
700 <option value="bold_italic"> ${ _("Bold & Italic")}</option>
704 <td class="titleCellTD">
705 <span class="titleCellFormat"> ${ _("Size")} </span>
709 <select id='size_selector' name="Template Element Size" class="attrSelect" data-attr="size">
710 <option value="xx-small"> ${ _("xx-small")}</option>
711 <option value="x-small"> ${ _("x-small")}</option>
712 <option value="small"> ${ _("small")}</option>
713 <option value="medium" SELECTED> ${ _("medium")}</option>
714 <option value="large"> ${ _("large")}</option>
715 <option value="x-large"> ${ _("x-large")}</option>
716 <option value="xx-large"> ${ _("xx-large")}</option>
722 <td class="titleCellTD">
723 <span class="titleCellFormat"> ${ _("Alignment")} </span>
726 <select id='alignment_selector' name="Template Element Alignment" class="attrSelect" data-attr="alignment">
727 <!-- Note: the value of the options is used directly in the style attribute of the items -->
728 <option value="Left"> ${ _("Left")}</option>
729 <option value="Right"> ${ _("Right")}</option>
730 <option value="Center"> ${ _("Center")}</option>
731 <option value="Justified"> ${ _("Justified")}</option>
734 <td class="titleCellTD">
735 <span class="titleCellFormat"> ${ _("Width (cm)")} </span>
738 <input id="width_field" size="5" name="Element Size">
739 <input class="btn attrButton" value="${ _("Change")}" type="button" data-attr="width">
743 <td class="titleCellTD" NOWRAP>
744 <span class="titleCellFormat"> ${ _("Text (for Fixed Text)")} </span>
747 <input id="fixed_text_field" size="30" name="Element Size" disabled="disabled">
750 <input class="btn attrButton" value="${ _("Change")}" type="button" data-attr="text" id="changeText" disabled="disabled">
758 <table class="groupTable">
761 <td colspan="4" align="center" width="100%">
762 <input class="btn" name="Save Template Button" value="${ _("Save")}" type="button" id="saveButton">
763 <input class="btn" name="Cancel Button" value="${ _("Cancel")}" type="button" onclick="location.href='${cancelURL}'">
769 <form id="saveForm" action="${saveTemplateURL}" method="POST">
770 <input name="templateId" value="${templateId}" type="hidden">
771 <input id="templateData" name="templateData" type="hidden">
775 <script type="text/javascript">
776 // We load the template if we are editing a template
777 if (${ editingTemplate }) {
778 var template = ${ templateData };
779 $('#template_name').val(template[0]);
780 $('#templateDiv').width(template[1].width).height(template[1].height);
782 // We give the toHTML() method to each of the items
783 $.each(items, function(i, item) {
784 item.toHTML = Item.prototype.toHTML;
786 templateDimensions = new Dimensions(template[1].width, template[1].height);
788 templateDimensions = new Dimensions(425, 270); //put here the initial dimensions of templateDiv
791 previousTemplateDimensions = new Dimensions(0,0);
793 $('#badge_width').val(templateDimensions.width / pixelsPerCm);
794 $('#badge_height').val(templateDimensions.height / pixelsPerCm);
796 updateRulers(); // creates the initial rulers
797 changeTemplateSize();
799 // This function displays the items, if any have been loaded, on the screen
802 if (${ editingTemplate } && ${ hasBackground }) {
803 backgroundId = ${ backgroundId };
804 displayBackground("${ backgroundURL }");