I have a drag drop box with dropzone.js. I allow multiple files upload (max 5 files at present). I have asked to add an ability for user to add description for each uploaded file.
The challenges I have:
Unable to determine how many files user dragged in zone
if I create text-boxes outside the zone, how do I tie them to each file correctly? I have set uploadMultiple to false and process one file at a time.
For example user uploaded 3 images of home, store & warehouse and 1 pdf and add description of Invoices, how do I ensure that Invoices doe not end up with home or store when processing that file?
I accomplished something like this by using a custom template for how Dropzone shows the file in the queue. I started with this example from the Dropzone author that explains how to use a custom template when displaying files in the queue. I expanded on the example by adding an extra form input to the template.
<div class="table table-striped" class="files" id="previews">
<div id="template" class="file-row">
<!-- This is used as the file preview template -->
<div>
<span class="preview"><img data-dz-thumbnail /></span>
</div>
<div>
<p class="name" data-dz-name></p>
<strong class="error text-danger" data-dz-errormessage></strong>
</div>
<!-- include a form field to collect the description -->
<div>
<label for="description">Description</label>
<textarea id="description"
data-name="description"
rows="3"></textarea>
</div>
<!-- remainder of template removed for brevity -->
</div>
</div>
Issue #1
When you add the form element, if you specify a name attribute, only the value from the form element associated with the last file will be submitted when the file uploads because you have multiple form elements all with the same name attribute.
To get around this, I did not include a name attribute but instead used a data-name attribute. Then I added the form element's value to the form data when the file got sent using this code:
myDropzone = new Dropzone('form#myuploadform')
myDropzone.on(
'sending',
function (file, xhr, formData) {
let description = file.previewElement.querySelector('textarea')
formData.append(description.getAttribute('data-name'),
description.value)
}
)
Issue #2
Because the id values are specified in the template, they will be the same value for every file added to the queue which violates the HTML spec since id values must be unique. Further since the for attribute of the LABEL element references the id of the TEXTAREA this also breaks accessibility because the second and subsequent LABELs will all reference the first TEXTAREA.
I fixed this by appending the UUID value Dropzone assigns to every file object to the id and for attributes as the file is being added to the queue, which is explained in this answer.
Related
I am working on a school project and I have to do a static digital menu website for a bar. Because it's static, I used JavaScript where necessary. Anyways, I divided everything into groups, each group is represented by a card with an image and a button. Here is an example:
This is the source code for a card:
<body>
<div id="cards">
<div class="card">
<img src="/Resources/Food.png" class="card_image">
<a href="javascript:showMenu()" class="button">
<p>FOOD</p>
</a>
</div>
</div>
</body>
As you can see, in order to add a single card, I had to manually write the whole structure of a card in the second div, with the class="card".
BUT, I must create it dynamically based on the structure of the subfolders inside the Root folder witch is called Resources, here's a scheme:
In order to achieve this I started using JavaScript since it's the only possible way I think:
<script type="text/javascript">
function showMenu()
{
var content = `
<div class="card">
<img src="/Resources/Food.png" class="card_image">
<a href="javascript:showMenu()" class="button">
<p>FOOD</p>
</a>
</div>`;
document.querySelector("#cards").innerHTML = content;
}
</script>
So, now that I've expressed what I need to do is this: in the JavaScript code you can see that the card was generated manually anyways but I need the content to generate based on the folder structure I have stored locally. In other words, the whole script should take in input the name/path of the ROOT folder which is called "Resources" and from there it should generate the groups based on it's content. For example, if I click the button on the FOOD Card, then it should delete the FOOD and DRINKS Cards and only add the Vegetables Card in this case...I know it sounds complicated but at the end of the day the problem lies in getting the subfolder names, and since the image has the same name of the subfolder, apply it on the <img> tag and also on the button. All this, using JavaScript. If you know that some other language would work much better I'm open to suggestions, but I built the entire website until now only using JavaScript.
Anyways, I tried to express the problem the best I could so if something is unclear, I can easily modify the post if needed. Thanks in advance!
You could put the image data into a JSON object, then bind related processing functions according to the requirement.
I am trying to make a spreadsheet addon where I have a textarea field where users will be putting the HTML for a table in a field, and I need my script to then take that HTML code, parse it and convert it into an array or object by which I can easily access the table's cells.
The problem I'm facing is that I don't seem to be able to turn the HTML code submitted as text back into a jQuery object I can loop through.
Tl;Dr:
How do I submit a table's HTML code from a form as text and turn it back into an HTML object so I can turn the table into an array/object?
I'm using $("#invoice-info").val() to get its content but using any other methods afterwards gives errors (All of them are either nonspecific or something about "Expected expression but got >", sorry I'm new to JavaScript so I have a hard time debugging it).
Here's the relevant HTML for the form itself:
<form onsubmit="return(false)">
<div class="block col-contain">
<div>
<textarea class="width-100" id="invoice-info" rows="10"></textarea>
<label for="invoice-info">Invoice Table</label>
</div>
</div>
<div class="block" id="button-bar">
<button class="blue" id="make-receipt" onclick='doTest()'>Generate</button>
</div>
</form>
You need to take the result of $("#invoice-info").val() and put it in a domNode. Because it returns a string. var tempDomNode = document.createElement('div'); tempDomNode.innerHTML =$("#invoice-info").val().
So you 'convert' the string into a domNode and then you will be able to use that domNode with or without jQuery to construct your array.
Note : you have to handle the case of a malformed sting (not valid as HTML)
Edit : just found this question on SO : https://stackoverflow.com/a/11047751/1836175 seems to address the same problem.
I have multiple reason codes (For ex: RC1, RC2...). For each of these reason codes, I want to give the user a text box in which they can enter some comments. Also give them the option of adding multiple text boxes for each reason code.
To allow the user to add a dynamic text box, I have a button which allows the user to do so. If there was only one reason code, I can easily just just append a text box to the pre-existing text box using jquery (Using something like this: JQuery adding class to cloned element).
However since I have multiple reason codes(over 200) it doesnt make sense of having button for each reason code in Jquery. Is there a way for me to search by a basic identifier.
I have pasted the contents of the HTML file generated by my JSP file.
<div id="Reasoncode1">
<div id="inputTextBox_Reasoncode1">
<input type="text" placeholder="Add some text"/><button class="button_Reasoncode1">
+</button>
</div>
</div>
<p>
Reason code2
</p>
<div id="Reasoncode2">
<div id="inputTextBox_Reasoncode2">
<input type="text" placeholder="Add some text"/><button class="button_Reasoncode2">
+</button>
</div>
</div>
My Jquery attempt is:
$(".button_Reasoncode1").click(function() {
$('#Reasoncode1').clone().insertAfter('#inputTextBox_Reasoncode1');
});
$(".button_Reasoncode2").click(function() {
$('#Reasoncode2').clone().insertAfter('#inputTextBox_Reasoncode2');
});
I dont want to do this for each and every reason code, i was wondering if there is a better approach to this.
My JSFiddle: https://jsfiddle.net/mvp71L61/
Assuming all buttons are statically added to the DOM,
$("button[class*='button_Reasoncode']").click(function() {
var rCode = $(this).attr('class').match(/\d+/g)[0];
$("div[id='Reasoncode'+rcode]").clone().insertAfter("input[id='inputTextBox_Reasoncode'+rcode]");
});
This is an AngularJS application (1.2.16). I browse to a dialog to edit some item. One of the controls is a multi-SELECT with the following visible values:
incident
work order
These visible values correspond to the following data values:
INCIDENT
WORK_ORDER
This is done through using the ng-options=" ... as ... for ... in ... " pattern, using an enumeration:
var FlexFieldSubjectTypeEnum = {
INCIDENT:{name:"INCIDENT", description:"incident"},
WORK_ORDER:{name:"WORK_ORDER", description:"work order"}
}
If have a form pretty much as follows:
<form ng-submit="save(formName)" name="formName" class="form-horizontal">
...
<div class="control-group">
<label class="control-label">Subject type:</label>
<div class="controls">
<select name="subjectType"
ng-options="type.name as type.description for type in getEnumAsArray('FlexFieldSubjectTypeEnum') | orderBy:'name'"
ng-model="entity.subjectType"
required></select>
</div>
</div>
Now, if the dialog loads the item ($scope.entity) from the backend and entity.subjectType is set to the first item in the list, the form validation marks it as unset. I have many other dialogs with similar constructs and have not seen this problem anywhere else.
If the item returned from the backend points to the second item (WORK_ORDER), this is nicely represented in the SELECT ("work order") and there is no validation error.
The problem does exist equally when using required or ng-required="true".
The problem does not exist if I remove the required attribute, but then the field also suddenly becomes optional, which is not what I wanted.
Your help much appreciated!
Almost a month later, with meanwhile an upgrade from Bootstrap v2.2.2 to v3.1.1 the problem disappeared.
I have two tabs in my smarty file. In tab1 I have a dropdown menu it contains list of cities. I have list of templates based on city it contains details about the city. in Second tab i should show the relevant city template based on the dropdown selection.
For example:
Dropdown:
<select name='city' id='city' class="medium" style="float:left" onchange="setCityTpl(this);">
<option value=''></option>
{html_options options=$city_filter selected=$city.name}
</select>
If I select City 1 in dropdown menu
I should set the tpl name in the smarty include file as city1.tpl
<div id="tab2" class="tab-content" style="display: none; visibility: hidden; padding-top:0px">
{include file=city1.tpl}
</div>
if I select City 2 in dropdown menu
I should set the tpl name in the smarty include file as city2.tpl
<div id="tab2" class="tab-content" style="display: none; visibility: hidden; padding-top:0px">
{include file=city2.tpl}
</div>
You can load url from javascript. So I think if user selects City1 from Dropdown1, your JS will load city1.tpl and City2 will load city2.tpl
Or you can do the follow: the js script call an url (selected-city.php) with a POST/GET value with "city1" or "city2". The selected-city.php retrieves the selected-city.tpl with a parameter named selected (which taken from POST/GET) and your tpl:
<div id....>
{include file=${selected}.tpl}
</div ...>
smarty is a php-based template engine, which means that it runs on the server side, while javascript runs on the client side (the user's browser). So, before the user actually sees your page, the smarty templates have finished processing and any inclusions are already done.
To achieve what you want, one way would be to include all files and hide the respective html elements (with display:none for example). Then, based on the user's selection, you would show the elements you wish (the second drop down in your case