Pass object from Smarty to jQuery - javascript

I have a smarty template that uses jQuery clones; i.e. a click on a button will call jQuery and jQuery will add a select field to a page. However, the select field is supposed to be dynamically populated within the smarty template.
I have outlined below what i'm trying to achieve.
addProject.php
// Load supervisor list into an object and pass it to smarty
$smarty->assign_by_ref('supervisor', $supervisor->results());
$smarty->display('superusers/addProject.tpl');
superusers/addProject.tpl
<div>
<p class="add add-data add-another-supervisor2"><i class="sprite plus2"></i> <span>Add <b class="hide">another</b> supervsior</span></p>
</div>
<script src="js/cloneformcontrols.js"></script>
js/cloneformcontrols.js
$("#main").on("click", ".add-data", function() {
var mytarget = $(this).closest('.clonable').find('.clone:last');
var myparent = $(this).closest('.clonable');
var filename = "../smarty/templates/default/superusers/clones/add-supervisor.tpl";
var theCloneHtml = '<div class="clone" id="cloneID' + formNameIncrement + '">';
var theCloneId = 'cloneID' + formNameIncrement;
if ($(this).hasClass('add-another-supervisor2')) {filename = "../smarty/templates/default/superusers/clones/add-another-supervisor.tpl";}
myparent.addClass('data-added');
mytarget.after($(theCloneHtml).load(filename, function() {
$(this).hide().fadeIn('slow');
updateNameAttribute(theCloneId); // need to update the name atribute or validation won't work
}));
formNameIncrement++;
});
clones/add-another-supervisor.tpl
<div class="standard-row add-admin-row input-row">
<label class="ib ib217"> <span class="plain-select">
<select class="inp" data-myname="supervisor[]" name="supervisor[]">
<option value="">Select one</option>
{section name="i" loop=$supervisor}
<option value="{$supervisor[i]->id}">{$supervisor[i]->name}</option>
{/section}
</select>
</span> </label>
<p class="add remove-this-data fl"><i class="sprite delete2"></i> <span> </span></p>
</div>
The only part that is not working is the clones/add-another-supervisor.tpl page doesn't receive the object $supervisor and therefore none of the select options get filled.
Does anyone know how I can fix this?

Related

make diffrence between objects that created with clone() in java script

Good Day Friends. I have a problem... Thanks, if you help me
I have a couple of inputs into a div. I copied that div with Clone function in java script (by click a button) and right now, I have two divs. but my problem:
1- I don't know, How can I get the values of inputs correctly (the input's names are the same)?
2- and I have a select input in div, that some inputs add or remove by choose each option of select input. Now after copied div, choose one option in div2, create changes in div1... and I don't want it !!
<div class="levels">
<div class="add_senario_level">
<span>Level 1</span>
<form>
<select name="condition" onchange="show_div(this,'shop during');">
<option selected="selected" disabled="disabled">choose condition</option>
<option>shop after registration</option>
<option>shop during</option>
</select>
<div id="shop_during" style="display:none;">
<input type="number" id="shop_during_num" name="shop_during_num" placeholder="Enter number">
<select id="shop_during_time" name="shop_during_time">
<option selected="selected">hour after registeration</option>
<option>day after registeration</option>
<option>week after registeration</option>
<option>month after registeration</option>
</select>
</div>
<div>
<button type="button" class="newLevel"> Add New Level </button>
</div>
</form>
</div>
</div>
<script>
$(document).ready(function()
{
$(".newLevel").click(function()
{
$(".add_senario_level").clone().appendTo(".levels");
});
});
function show_div(obj, id)
{
txt = obj.options[obj.selectedIndex].text;
if (txt.match(id))
{
document.getElementById("shop_during").style.display = 'block';
}
else
{
document.getElementById("shop_during").style.display = 'none';
}
}
</script>
You can use jQuery's find function to find a child element and the attr function to get and set attribute values. You will want to do this to change on the id and name attributes for the input and select like below:
HTML
<input type="number" id="shop_during_num0" name="shop_during_num0" class="shop_input" placeholder="Enter number">
JavaScript
$(".newLevel").click(function()
{
const count = $('.add_senario_level').length;
const clone = $(`#add_senario_level${count - 1}`).clone();
const input = clone.find(`#shop_during_num${count - 1}`);
const select = clone.find(`#shop_during_time${count - 1}`);
input.attr('name', `shop_during_num${count}`);
input.attr('id', `shop_during_num${count}`);
select.attr('name', `shop_during_time${count}`);
select.attr('id', `shop_during_time${count}`);
clone.appendTo(".levels");
});
In the show_div method, you can use $(obj) to reference the select that called the function and show or hide the correct element with
$(obj).parent().find('#shop_during').css('display', 'block');

How to change innerHTML content such as(input field names,ids,onclick) attributes

I want to copy all content of a div into another div, but before copying I need to change all input fields names and ids. See the code below.
<div id="first_div">
<input type="text" name="firstname" id="firstname">
<select name="marital_status" id="marital_status">
<option value="1" selected='selected'>Select</option>
<option value="2">Single</option>
<option value="3">Married</option>
</select>
</div>
<div id="second_div">
</div>
Now I want to copy content of first_div into second_div,but before copying I need to change input field firstname into last_name, how to do it?
As I see you tagged jQuery in the question, you could use jQuery clone method to get started quickly : https://api.jquery.com/clone/
var clone = $("#first_div").clone();
then modifying the clone innerHTML like so
clone.find("#firstname").attr("id", "lastname"); // modifying div id
// do the same for every element you want to modify id, etc
//then finally append it to the second_div
$("#second_div").html(clone.html());
If you want a vanilla Javascript version:
var clone = document.getElementById('first_div').cloneNode(true);
clone.querySelector('#firstname').id = 'lastname';
document.getElementById('second_div').innerHTML = clone.innerHTML;
If you don't have jQuery added to your solution, it would be good to not add it at all, if only using for that.
By using pure javaScript
var fdiv = document.getElementById("first_div");
var clnNode = fdiv.cloneNode(true);
var clnInput = clnNode.querySelector('#firstname');
clnInput.setAttribute('id', 'lastname')
var secDiv = document.getElementById('second_div')
secDiv.innerHTML = clnNode.innerHTML;
Simply copy the inner html and replace the id:
var html = document.getElementById('first_div').innerHTML;
html = html.replace(/firstname/g, 'last_name');
document.getElementById('second_div').innerHTML = html;
<div id="first_div">
<input type="text" name="firstname" id="firstname">
<select name="marital_status" id="marital_status">
<option value="1" selected='selected'>Select</option>
<option value="2">Single</option>
<option value="3">Married</option>
</select>
</div>
<div id="second_div">
</div>

How to add same from input area when user press a button?

I am doing a form right now, I want to automatically add another input area, same as the line above, when user press a button.
<div class="row" id="1">
<div class="form-group col-lg-2">
<select class="form-control" id="select">
<option selected>Tag Name</option>
<option value="p">p</option>
<option value="br">br</option>
</select>
</div>
<div class="form-group col-lg-2">
<select class="form-control" id="class">
<option selected>Tag Class</option>
<option value="Day">Day</option>
<option value="BlockTime">BlockTime</option>
<option value="BlockTitle">BlockTitle</option>
<option value="Session">Session</option>
<option value="Person">Person</option>
<option value="Firm">Firm</option>
</select>
</div>
<div class="form-group col-lg-7">
<textarea class="form-control" rows="3" id="textArea">Please put the content inside this html tag.</textarea>
</div>
<div class="form-group col-lg-1">
<input type="button" class="btn btn-default" onclick="addLine()" value="Add">
</div>
</div>
This is a line of input area, I want to add the same html below the input area we have now when user press the "Add" button. Maybe using JQuery?
It should looks like this one.
This is what I tried:
function addLine() {
$('#1').clone().attr('id', '').appendTo('form');
}
For now, it seems work, but how should I do if I want to add id to the new created element, say, 2, 3, 4?
Also I am not sure am I did it the right, or best way.
Solution by jQuery
var n = 8 // adjust it in some way
var inputArea = ['<div class="form-group col-lg-'+n+'">',
'<textarea class="form-control" rows="3" id="textArea-'+n+'">',// let's be nice and not use same IDs twice
'Please put the content inside this html tag.',
'</textarea></div>'].join('')
$('.row').append(inputArea);
However make sure that your back end is ready to handle that input.
EDIT:
The solution might not be fancy and using clone() is completely fine too.
To keep track of ids I would add a simple variable like n that I would increment every time a new input area is added, and then add it to id.
So, init
var n = 0;
In addLine:
n++;
Set the id (doable in addLine too)
$target.attr('id', 'inputArea-'+n);//Assuming that $target is the inputArea in question
You can copy from a blueprint structure in the DOM and append your copy after the button.
var addline = function() {
var invisibleNewLine = jQuery('#blueprint').clone();
var visibleNewLine = invisibleNewLine.removeClass('invisible');
jQuery('#target').append(visibleNewLine);
};
jQuery('#add-line').click(addline);
Remove the onClick handler on the element and bind the event using jQuery.
<button id="add-line" class="btn btn-default">Add</button>
See the fiddle here: JSFiddle

Can't get value of textarea using Javascript

I have a form which is using the SheepIt jQuery plugin, for duplication of form rows. One of the elements in the row is a <select> element. When a certain value is chosen in the select value, a modal (I'm using Fancybox on my site) containing a <textarea> appears, allowing users to provide additional information. My idea was to take this text and add it to the form in a hidden form element, but I can't for the life of me get the text using jQuery. I've tried using .val(), .text(), and .html(), but I keep getting an empty string. I even tried using vanilla Javascript using similar methods to above, but I still can't get it to work. I have a hidden element (<input type="hidden" id="row_id" value="" />) in that same block of HTML and have no problem retrieving it using $("#row_id").val(). Any suggestions?
My Code
HTML
<!-- sheepIt Form -->
<div id="meta_fields" class="well sheepit-form">
<!-- Form template-->
<div id="meta_fields_template" class="sheepit-row">
<input id="meta_fields_#index#_field_label" name="meta[meta_fields][#index#][field_label]" type="text" placeholder="Field Label" />
<select id="meta_fields_#index#_field_type" name="meta[meta_fields][#index#][field_type]" class="field-choice">
<option value="">--Field Type--</option>
<option value="text">Single Line Text Box</option>
<option value="textarea">Multi Line Text Box</option>
<option value="checkbox">Checkbox</option>
<option value="select">Dropdown List</option>
</select>
<input id="meta_fields_#index#_field_id" name="meta[meta_fields][#index#][field_id]" type="hidden" />
<input id="meta_fields_#index#_field_required" name="meta[meta_fields][#index#][field_required]" value="0" type="hidden" />
<input id="meta_fields_#index#_field_required" name="meta[meta_fields][#index#][field_required]" value="1" type="checkbox" />
<label for="meta_fields_#index#_field_required">Required?</label>
<a id="meta_fields_remove_current" class="item small">
<i class="icon-remove"></i>
</a>
</div>
<!-- /Form template-->
<!-- No forms template -->
<div id="meta_fields_noforms_template">No fields defined!</div>
<!-- /No forms template-->
<!-- Controls -->
<div id="meta_fields_controls" class="sheepit-buttons">
<span id="meta_fields_add"><button class="btn btn-success btn-small"><i class="icon-plus-sign"></i> <span>Add Row</span></button></span>
<span id="meta_fields_remove_last"><button class="btn btn-warning btn-small"><i class="icon-remove"></i> <span>Remove Row</span></button></span>
<span id="meta_fields_remove_all"><button class="btn btn-danger btn-small"><i class="icon-trash"></i> <span>Remove All Rows</span></button></span>
</div>
<!-- /Controls -->
</div>
<!-- /sheepIt Form -->
<script type="text/x-handlebars" id="select-options-form">
<p class="lead">Please provide options for the dropdown list. One option per line</p>
<div>
<textarea id="options" style="width:500px;height:200px"></textarea>
<input type="hidden" id="row_id" value="" />
</div>
<div class="pull-right">
<button class="btn btn-success closeModal">
<i class="icon-ok"></i>
Complete
</button>
</div>
</script>
NOTE: This is not a true Handlebars template. I'm using the <script> tag to hold the HTML fragment that is inserted into the modal. I wasn't sure if having a div with style="display:none" was causing JS to think that there were two elements in the page (that was my original markup).
Javascript
// called from <select> event handler
function checkFieldList(e)
{
e.preventDefault();
var value = $(this).val();
if(value !== 'select') {
// TODO: do some processing here
return false;
}
// get the sheepIt row id -- easiest by parsing out the element ID
var row_id = parseInt($(this).prop("id").split("_")[2], 10);
return openModal(row_id);
}
function openModal(row_id)
{
// load in content and open in modal
var modalContent = $("#select-options-form");
modalContent.find("#row_id").val(row_id);
$.fancybox({
"width" : 600,
"height" : 300,
"modal" : true,
"content" : modalContent.html(),
"afterShow" : bindModalClose,
"beforeClose" : closeModal
});
}
function bindModalClose()
{
$(".closeModal").on('click', function(e) {
e.preventDefault();
$.fancybox.close();
});
}
function closeModal()
{
//add link after select dropdown and wire an event handler
var row_id = $("#row_id").val(),
dropdown = $("#meta_fields_" + row_id + "_field_type");
addOptionsLink(dropdown, row_id);
// retrieve content in <textarea>
// all the following return empty string
var text = $("#options").val();
// var text = $("#options").html();
// var text = $("#options").text();
// var text = document.getElementById("options").value;
// var text = document.getElementById("options").innerHTML;
// var text = document.getElementById("options").innerText;
console.log(text);
// 3. insert that content into hidden form field
}
function addOptionsLink(dropdown, row_id)
{
dropdown.after('View Options');
$(".load_options").on('click', function(e) {
e.preventDefault();
return openModal(row_id);
});
}
And...of course right after I resort to asking the question on StackOverflow, it's working just fine now with the $("#options").val(); solution. It's been a long week...

jquery dynamic subselection combining last and form elements

Update
Tidied up the solution in progress and added some extra details
I have a form area which creates clones based on a template. In order to make sure the form transmits in an order, the script goes through the form at send time appending a number which defines the current batch set. Below is an over simplified representation of what is going on:
<form>
<div class="batch-template">
<div class="batch-piece">
<a class="clone" />
<input name="test-input">
<input name="another-test-input">
<select name="a-drop-down">
</div>
</div>
<div class="batch-paste-area">
</div>
</form>
When the page starts:
The contents of "batch-template" are stored to an object variable
The original template is removed from the page
An instance of the template is appended to the "batch-paste-area"
The following is an example of the output created after clicking twice.
<form>
<div class="batch-template">
</div>
<div class="batch-paste-area">
<div class="batch-piece">
<a class="clone" />
<input name="test-input">
<input name="another-test-input">
<select name="a-drop-down">
</div>
<div class="batch-piece">
<a class="clone" />
<input name="test-input">
<input name="another-test-input">
<select name="a-drop-down">
</div>
</div>
</form>
When it comes to submitting the form: prior to serialization, I would like the script to loop through each "batch-piece" within "batch-paste-area" and add a count value to the end of each form field name. Continuing with the set above, the result (to a browser) would seem like that shown below:
<form>
<div class="batch-template">
</div>
<div class="batch-paste-area">
<div class="batch-piece">
<a class="clone" />
<input name="test-input1">
<input name="another-test-input1">
<select name="a-drop-down1">
</div>
<div class="batch-piece">
<a class="clone" />
<input name="test-input2">
<input name="another-test-input2">
<select name="a-drop-down2">
</div>
</div>
</form>
So far, I can either loop through EVERY input within the paste area or just select the last.
Selecting the last batch-piece is simple:
var intCount = 1;
$('.batch-paste-area .batch-piece').each(function(){
/*
* Would like to be able to loop through form fields here
* Below is an attempt to select all form fields for current set
*/
$(this + ' input, '+ this + ' select').each(function() {
var strName = $(this).attr('name') + intCount;
$(this).attr('name', strName);
});
intCount++;
});
Frustratingly, I had actually tried the correct solution in advance but had forgotten to use the comma at the time!
var intCount = 1;
$('.batch-paste-area .batch-piece').each(function(){
/*
* Would like to be able to loop through form fields here
* Below is an attempt to select all form fields for current set
*/
$(this).find("input, select").each(function() {
var strName = $(this).attr('name') + intCount;
$(this).attr('name', strName);
});
intCount++;
});

Categories

Resources