I'm using jQuery Multiple File Upload Plugin
and I have the following:
$(function(){ // wait for document to load
$('#attachFiles').MultiFile({
list: '#attList',
STRING: { remove: '<img src="cross.gif" title="Remove this attachment" border="0">' },
afterFileAppend: function(element, value, master_element) {
$(".amount").each(function(){
var i = $(this).attr("i");
var curVal = $("#attachment_" + i).val();
if($("#attachment_" + i).is(":checked") && curVal == "X") {
$("#attachment_" + i).attr("value", value);
$("#attachment_" + i).attr("title", "Attachment " + value + " linked");
aCounter++;
};
});
if(aCounter==0) {
alert("You need to select...");
//Remove should be here
}
}
});
});
If I add a file named test.pdf then one named test2.pdf my goal is to automatically remove test2.pdf if my aCounter variable is 0 (that would mean the user did not check off any additional check boxes named attachment_#.
I can't seem to figure out how to remove just the file that was added.
If I understand correctly, the value of the file that I add gets added to id="attachfiles" which is a
<input type="file" name="userfile[]" id="attachFiles" class="file" size="1" accept="pdf|jpg|jpeg">
So I'm assuming I should be able to somehow remove the most recently added item somehow.
Any assistance or guidance would be great.
The jQuery Multiple File plugins that I've used do NOT use some array to hold the set of files. They use a series of
<input type="file" ... style="position:absolute; left:-3000px;" />
<input type="file" ... style="position:absolute; left:-3000px;" />
elements that are hidden after the user selects a file. The displayed input element is replaced with a new one. This also seems to be the case with your plugin. You should be able to find the most recent file by doing some selector
$("#mydiv input[type='file']").last()
or something similar and removing it from the DOM.
You can probably also do a trigger('click') on the appropriate delete button.
Related
I'm having a kind of problem that I think is related to how I generate my HTML... I use a JavaScript function to generate some HTML, but then it begins to misfunction... let me first paste some of my code
First, my raw HTML
<div id="effect">
<label for="s_effect">Effect: </label>
<select name="s_effect" id="s_effect" onchange="ne();">
<option value="">Select your Effect</option>
</select>
<div id="effect_description"></div>
<div id="effect_options"></div>
</div>
Then, I have a function that loads "s_effect" based on an array (that's fine and working, np).
Then, my ne() (new effect) function:
function ne(){
reset();
e = g('s_effect');
if(newEffect(e.options[e.selectedIndex].value)){
console.log("new effect created");
updateScreen();
}
}
It basically "resets" parts of the screen (error tracking and that, stuff not related with my problem), then calls to updateScreen() (note: g function is just a synonym for document.getElementById)
It goes to this function (sorry it's a lot of code...)
function updateScreen(){
if(project.effect instanceof Effect){
lock("instant");
lock("event");
showDescription();
generateOptions();
}else if(project.effect == null){
unlock("instant");
unlock("event");
}
if(project.check()){
generateButton();
}else{
npButton();
}
}
That basically, locks some part of the window, then get some HTML on calls below.
generateDescription(), the part is giving trouble, does the following:
function generateOptions(){
g('effect_options').innerHTML = '';
effectID = project.effect.calculateId();
if(effectID === false)
return false;
g('effect_options').innerHTML = project.effect.parameters.HTMLOptions;
return true;
}
It calls to an object attribute that basically dumps some HTML code:
<div>
<label for="1_color">Color: </label><input type="color" id="1_color" name="1_color" onchange="updateColor('1_color');" value="#FFFFFF">
<input type="text" name="1_color_rgb" id="1_color_rgb" onchange="updateColor('1_color_rgb');" value="#FFFFFF">
</div>
<div id="extra"></div>
<div>
<input type="button" value="Add Node" onclick="addNode();">
</div>
Finally, addNode() makes an innerHTML += [new div on "extra"] but increasing the number (2_color, 2_color_rgb, and so on).
function addNode(){
var count = ++(project.effect.parameters.colorCount);
g('extra').innerHTML +=
'<div><label for="' + count + '_color">Color: </label><input type="color" id="' + count + '_color" name="' + count + '_color" onchange="updateColor(\'' + count + '_color\');" value="#FFFFFF" />' +
'<input type="text" name="' + count + '_color_rgb" id="' + count + '_color_rgb" onchange="updateColor(\'' + count + '_color_rgb\');" value="#FFFFFF" /></div>' +
}
To this point everything is working fine, even "updateColor" works (it updates the value of each input so you can choose a color by filling any input).
The problem comes when I modify any x_color or x_color that has been added via button... It adds a new "node" but restarts the values of previous inputs.
I debugged it, and by the point is doing the adding, the innerHTML of "extra" shows all inputs with "#FFFFFF" values (initial), but on the screen, the values are right...
Any help with this may be appreciated.
PS: I'm using chrome.
Thank you!
Just to clarify, as #Forty3 answered, the problem was the fact that I was modifying the innerHTML each time, making my browser to re-render extra each time.
As he suggested, I edited my function, now looks like
function addNode(){
var count = ++(project.effect.parameters.colorCount);
var nDiv = document.createElement("div");
nDiv.innerHTML = "whatever I was putting...";
g('extra').appendChild(nDiv);
}
Now it works fine.
Thank you all for the support.
The issue, it appears, is that by reassinging the .innerHTML property of the g('extra') DOM element, you are telling the browser to re-render the element based on the HTML -- not the DOM elements and values contained within.
In other words, when you add a color, the g('extra').innerHTML gets updated with the new HTML to render an additional color selection block (i.e. 2_color). When a user then picks a new color, the browswer will update the value for the 2_color DOM element but doesn't necessarily update the innerHTML property for g('extra'). Then, when another color block is added, the innerHTML is updated once more and the browser re-renders it thereby "resetting" the values.
Instead of constructing the additional controls using HTML string, use DOM manipulation (e.g. .createElement() and .append()) in order to add your new options.
What I want to be able to is on button click I want to check a Server-Side directory for the existence of certain files.
If they exist I wish to display a checkbox corresponding to that file.
So far I have managed to use PHP and AJAX to check if the files exist or not and write to and array: 1 if the file exists, and a 0 if not.
Now...what I need to do at this stage is call upon this array, from my PHP file, or write this array to a div on my main HTML page. However when I go to echo it navigates away from my Main.html, opening a new page and writing on that.
Big question is can I write the array on my main html page from my PHP_Function.php file.
I have the following HTML code:
<form action="PHP_Function.php">
<input type="submit" class="learnButton" name="insert" value="Find Available Evidence" />
</form>
<form action="available_evidence">
<input type="checkbox" name="vehicle" value="Bike"> Facebook<br>
<input type="checkbox" name="vehicle" value="Car" checked> Facebook Messenger<br>
<input type="checkbox" name="vehicle" value="Bike"> Twitter<br>
</form>
With the following array within PHP_function.php file:
if(in_array("Facebook.xml", $dirArray)){
$IfPresentArray[0]="1";
}else {
$IfPresentArray[0]="0";
}
foreach ($IfPresentArray as $value) {
echo "$value<br />\n";
}
I am very new to PHP and HTML, and I have been banging my head off the wall with this for a while now.
Any help would be greatly appreciated.
You are using AJAX so all your communication will need to go back and forth over that medium. In brief, your PHP script (the one called by ajax) will echo JSON values (typically created by json_encode($myarray)) and this will then be available to your javascript over on your client-side.
A quick google for "jquery ajax json example" should get you some good, helpful ideas of how it fits together.
Here's the client-side from one of those google links above - note the .done part
<script type="text/javascript">
$(document).ready(function(){
$(':submit').on('click', function() { // This event fires when a button is clicked
var button = $(this).val();
$.ajax({ // ajax call starts
url: 'serverside.php', // JQuery loads serverside.php
data: 'button=' + $(this).val(), // Send value of the clicked button
dataType: 'json', // Choosing a JSON datatype
})
.done(function(data) { // Variable data contains the data we get from serverside
$('#wines').html(''); // Clear #wines div
if (button == 'all') { // If clicked buttons value is all, we post every wine
for (var i in data.red) {
$('#wines').append('Red wine: ' + data.red[i] + '<br/>');
}
for (var i in data.white) {
$('#wines').append('White wine: ' + data.white[i] + '<br/>');
}
}
else if (button == 'red') { // If clicked buttons value is red, we post only red wines
for (var i in data) {
$('#wines').append('Red wine: ' + data[i] + '<br/>');
}
}
else if (button == 'white') { // If clicked buttons value is white, we post only white wines
for (var i in data) {
$('#wines').append('White wine: ' + data[i] + '<br/>');
}
}
});
return false; // keeps the page from not refreshing
});
});
</script>
You can store your array inside a $_SESSION variable, but you'll have to use a session_start(); on both pages.
On your php page, use: $_SESSION['array'] = $array; and then on your main page retrieve the array by the inverse: $array = $_SESSION['array'];.
You can now use said array on your main page.
To retrieve a specific value: $value1 = $_SESSION['array'][0];
For further reference:
Array as session variable
I have a file called bpSearch. Inside bpSearch, I have a MODAL window, called addNewModal. Within addNewModal, I have 2 INPUT fields called partnerName and partnerCode. I have a button that once clicked, opens into another MODAL window, called searchPartnerModal.
Here is the a portion of the FORM inside addNewModal:
<form action="bpSearch.php" method="get">
<input type="text" readonly id="partnerName" name="partnerName" />
<input type="text" readonly id="partnerCode" name="partnerCode" />
Go
</form>
When the user clicks GO, it opens searchPartnerModal.
searchPartnerModal is where the user will enter either a code or a name (doesn't have to be both). But upon hitting SEARCH, I use an AJAX call that returns JSON that I parse and eventually return in a UL field called pNames. We're still inside searchPartnerModal.
Here is the FORM inside searchPartnerModal:
<form action="bpSearch.php" method="get">
<input type="text" id="pNameSearch" name="pNameSearch" />
<input type="text" id="pCodeSearch" name="pCodeSearch" />
<input type="button" class="btn" id="pSearch" name="pSearch" value="search" />
</form>
When the user enters a name, I use jquery to send it over to a PHP script that will then return the data in a UL tag.
Here is the jquery that will search if the user enters a name:
$('#pSearch').on('click', function()
{
var partnername = $('#pNameSearch').val();
if($.trim(partnername) != '')
{
$.post('api/pNameSearch.php', {partnername: partnername}, function(data)
{
var obj = JSON.parse(data);
$('#pNames').empty();
var htmlToInsert = obj.map(function (item)
{
return '<li><a id="getPInfo" href="javascript:;"
onclick="getPInfo()" data-selname="'+item.FULL_NAME+'"
data-selcode="'+item.PARTNER_CODE+'">'
+ item.FULL_NAME + ' - '
+ item.PARTNER_CODE + '</a></li>';
}).join('');
$('#pNames').html(htmlToInsert);
});
};
});
With this code, I am able to send the name to search the database table for a valid name. The data is returned via JSON and is parsed and displayed inside the UL tag (called pNames) as LI tags, each with an A tag with their own data-attributes, called data-selname and data-selcode.
Now what I need to do is once the user clicks on one of the returned data links inside pNames, I need to send it back to the previous modal window, addNewModal.
This is where I'm stuck.
If you look inside the Jquery above, after I parsed the JSON, you will see that I created another Javascript function inside the A tag of each returned piece of data, called getPInfo().
Here is what I got so far for the function getPInfo() :
function getPInfo()
{
var selname = ($('#getPInfo').attr('data-selname'));
var selcode = ($('#getPInfo').attr('data-selcode'));
}
At this point, I can alert both variables (selname and selcode) and get them to display in an alert window.
What I want to do is send both of those variables back to addNewModal in the respective INPUT fields, called partnerName and partnerCode.
So selname will go to partnerName and selcode will go to partnerCode.
I didn't display the PHP script that returned the data.
Change the anchor id=getPInfo to class=getPInfo since you have multiple anchors. Next, handle the click event of the anchor and extract the data attributes and set the corresponding form elements in the addNewModal form. Following should work based on the markup i see so far.
$(function(){
$('body').on('click', 'a.getPInfo', function (e) {
var $a = $(e.srcElement || e.target);
$('#partnerName').val($a.attr('data-selname'));
$('#partnerCode').val($a.attr('data-selcode'));
$('#searchPartnerModal').modal('hide'); //assuming bootstrap modal
});
});
I'd like to save the newly entered values, so I could reuse them. However, when I try to do the following, it does not work:
// el is a textbox on which .change() was triggered
$(el).attr("value", $(el).val());
When the line executes, no errors are generated, yet Firebug doesn't show that the value attribute of el has changed. I tried the following as well, but no luck:
$(el).val($(el).val());
The reason I'm trying to do this is to preserve the values in the text boxes when I append new content to a container using jTemplates. The old content is saved in a variable and then prepended to the container. However, all the values that were entered into the text boxes get lost
var des_cntr = $("#pnlDesignations");
old = des_cntr.html();
des_cntr.setTemplate( $("#tplDesignations").html() );
des_cntr.processTemplate({
Code: code,
Value: val,
DivisionCode: div,
Amount: 0.00
});
des_cntr.prepend(old);
This is the template:
<div id="pnlDesignations">
<script type="text/html" id="tplDesignations">
<div>
<label>{$T.Value} $</label>
<input type="text" value="{$T.Amount}" />
<button>Remove</button>
<input type="hidden" name="code" value="{$T.Code}" />
<input type="hidden" name="div" value="{$T.DivisionCode}" />
</div>
</script>
</div>
You want to save the previous value and use in the next change event?
This example uses .data to save the previous value. See on jsFiddle.
$("input").change(function(){
var $this = $(this);
var prev = $this.data("prev"); // first time is undefined
alert("Prev: " + prev + "\nNow: " + $this.val());
$this.data("prev", $this.val()); // save current value
});
jQuery .data
If you want old/Initial text box value, you can use single line code as follows.
var current_amount_initial_value = $("#form_id").find("input[type='text']id*='current_amount']").prop("defaultValue");
If you want current value in the text box, you can use following code
$("#form_id").find("input[type='text']id*='current_amount']").val();
I am using ASP.Net MVC along with Jquery to create a page which contains a contact details section which will allow the user to enter different contact details:
<div id='ContactDetails'>
<div class='ContactDetailsEntry'>
<select id="venue_ContactLink_ContactDatas[0]_Type" name="venue.ContactLink.ContactDatas[0].Type">
<option>Email</option>
<option>Phone</option>
<option>Fax</option>
</select>
<input id="venue_ContactLink_ContactDatas[0]_Data" name="venue.ContactLink.ContactDatas[0].Data" type="text" value="" />
</div>
</div>
<p>
<input type="submit" name="SubmitButton" value="AddContact" id='addContact' />
</p>
Pressing the button is supposed to add a templated version of the ContactDetailsEntry classed div to the page. However I also need to ensure that the index of each id is incremented.
I have managed to do this with the following function which is triggered on the click of the button:
function addContactDetails() {
var len = $('#ContactDetails').length;
var content = "<div class='ContactDetailsEntry'>";
content += "<select id='venue_ContactLink_ContactDatas[" + len + "]_Type' name='venue.ContactLink.ContactDatas[" + len + "].Type'><option>Email</option>";
content += "<option>Phone</option>";
content += "<option>Fax</option>";
content += "</select>";
content += "<input id='venue_ContactLink_ContactDatas[" + len + "]_Data' name='venue.ContactLink.ContactDatas[" + len + "].Data' type='text' value='' />";
content += "</div>";
$('#ContactDetails').append(content);
}
This works fine, however if I change the html, I need to change it in two places.
I have considered using clone() to do this but have three problems:
EDIT: I have found answers to questions as shown below:
(is a general problem which I cannot find an answer to) how do I create a selector for the ids which include angled brackets, since jquery uses these for a attribute selector.
EDIT: Answer use \ to escape the brackets i.e. $('#id\\[0\\]')
how do I change the ids within the tree.
EDIT: I have created a function as follows:
function updateAttributes(clone, count) {
var f = clone.find('*').andSelf();
f.each(function (i) {
var s = $(this).attr("id");
if (s != null && s != "") {
s = s.replace(/([^\[]+)\[0\]/, "$1[" + count + "]");
$(this).attr("id", s);
}
});
This appears to work when called with the cloned set and the count of existing versions of that set. It is not ideal as I need to perform the same for name and for attributes. I shall continue to work on this and add an answer when I have one. I'd appreciate any further comments on how I might improve this to be generic for all tags and attributes which asp.net MVC might create.
how do I clone from a template i.e. not from an active fieldset which has data already entered, or return fields to their default values on the cloned set.
You could just name the input field the same for all entries, make the select an input combo and give that a consistent name, so revising your code:
<div id='ContactDetails'>
<div class='ContactDetailsEntry'>
<select id="venue_ContactLink_ContactDatas_Type" name="venue_ContactLink_ContactDatas_Type"><option>Email</option>
<option>Phone</option>
<option>Fax</option>
</select>
<input id="venue_ContactLink_ContactDatas_Data" name="venue_ContactLink_ContactDatas_Data" type="text" value="" />
</div>
</div>
<p>
<input type="submit" name="SubmitButton" value="AddContact" id='addContact'/>
</p>
I'd probably use the Javascript to create the first entry on page ready and then there's only 1 place to revise the HTML.
When you submit, you get two arrays name "venue_ContactLink_ContactDatas_Type" and "venue_ContactLink_ContactDatas_Data" with matching indicies for the contact pairs, i.e.
venue_ContactLink_ContactDatas_Type[0], venue_ContactLink_ContactDatas_Data[0]
venue_ContactLink_ContactDatas_Type[1], venue_ContactLink_ContactDatas_Data[1]
...
venue_ContactLink_ContactDatas_Type[*n*], venue_ContactLink_ContactDatas_Data[*n*]
Hope that's clear.
So, I have a solution which works in my case, but would need some adjustment if other element types are included, or if other attributes are set by with an index included.
I'll answer my questions in turn:
To select an element which includes square brackets in it's attributes escape the square brackets using double back slashes as follows: var clone = $("#contactFields\[0\]").clone();
& 3. Changing the ids in the tree I have implemented with the following function, where clone is the variable clone (in 1) and count is the count of cloned statements.
function updateAttributes(clone, count) {
var attribute = ['id', 'for', 'name'];
var f = clone.find('*').andSelf();
f.each(function(i){
var tag = $(this);
$.each(attribute, function(i, val){
var s = tag.attr(val);
if (s!=null&& s!="")
{
s = s.replace(/([^\[]+)\[0\]/, "$1["+count+"]");
tag.attr(val, s);
}
});
if ($(this)[0].nodeName == 'SELECT')
{ $(this).val(0);}
else
{
$(this).val("");
}
});
}
This may not be the most efficient way or the best, but it does work in my cases I have used it in. The attributes array could be extended if required, and further elements would need to be included in the defaulting action at the end, e.g. for checkboxes.