I have a base document that loads like http://localhost/index.php?action=test. This document has a button that opens a div with an iframe which loads another document from the same domain http://localhost/index.php?action=search. Now I have the results and on click of a link in the iframe, I need to access a field (which is a select2 control) in the parent and set the value.
The generated html looks like this:
<tbody>
<tr>
<td class="fldlabel">
<div><label for="header[CTRYID]">Country</label></div>
</td>
<td>
<input tabindex="-1" id="header-CTRYID" data-label="Country" name="header[CTRYID]" class="ajaxselect srchtarget-CTRYID validate select2-offscreen" data-validate="required" value="" data-placeholder="Select Country" type="text">
<span class="hdricon">
<img class="imgicon" src="/images/icons/search.ico" alt="Search Country">
</span>
<div class="searchpanel" id="CTRYID-search" style="">
<div class="frametitle">Search Country </div>
<div class="srchbody">
<iframe src="index.php?action=search&source=CTRYID" class="srchframe">
#document
<!DOCTYPE html>
<html>
<head></head>
<body>
<div id="container">
<div id="content" style="overflow: hidden;" tabindex="5000">
<form method="post" action="index.php?action=search&source=CTRYID" name="country">
<div id="searchselect" class="srchrslt">
<div class="frametitle">Search Results</div>
<table border="1" style="margin-top: 5px;">
<tbody>
<tr class="gridrow searchrow" data-search="IN|India" data-target="CTRYID">
<td>IN</td>
<td>India</td>
<td>IND</td>
</tr>
</tbody>
</table>
</div>
</form>
</div>
</iframe>
</div>
</div>
</div>
</td>
</tr>
</tbody>
Below is the jquery code that I've been trying.
$('.searchrow').click(function (e) {
alert($('#srchtarget-CTRYID',window.parent.document).attr('id'));
e.preventDefault();
var srchdata = $(this).data('search').split("|");
var srchval = JSON.stringify({"id":srchdata[0],"text":srchdata[0]+"|"+srchdata[1]});
var target = "srchtarget-" + $(this).data('target');
$(target,window.document).select2().select2('val',srchval);
$(this).parent().find('.searchpanel').hide();
// $(this).parents().find(target).val(srchval);
});
I'm getting the values from php, only my jquery does not work. I have tried window.parent, window.parent.document, window.top.document (as you can see from the code above) but none of those seem to work. Any property that I access outside the iframe results as undefined (the alert in the above code).
UPDATE:
After playing around, I get the value with window.parent.document but I still could not get the value into the select2 control. My current code looks like below:
$('.searchrow').click(function (e) {
var srchdata = $(this).data('search').split("|");
var srchval = [];
srchval.push({"id": srchdata[0], "text": srchdata[0] + "|" + srchdata[1]});
var target = ".srchtarget-" + $(this).data('target');
var parentctrl = window.parent.document;
$(target,parentctrl).select2('data',srchval);
$(this).closest('.searchpanel').hide();
$('.searchpanel', parentctrl).hide();
});
I have checked the parent target element (unique class name in my case) is correctly populated in the variable and the value exists in the data variable (as JSON object).
UPDATE 2:
I have replaced the unique class with the id of the parent element (since select2 was replicating the class from the parent into the select2 control) so I get a real unique id for the parent. However, the result is the same. I still don't get to populate the results in the control. My updated target is as below and I get my target id is correctly populated:
var target = "#" + $(this).data('target');
I've searched, read and tried all solutions that came up in SO and in internet but none worked. Can anyone help?
I upgraded to v4 and the below code 'kinda' works for pushing the values (but the select2 control is duplicated with the option. possibly a bug in v4).
$('.searchrow').click(function (e) {
var srchdata = $(this).data('search').split("|");
var target = ".srchtarget-" + $(this).data('target');
var targetoption = target + " option[value='" + srchdata[0] + "']";
var parentctrl = window.parent.document;
$(targetoption,parentctrl).attr("selected","selected");
$(target,parentctrl).select2();
});
Related
I have a section called duplicator1. I want to clone that section and it works but my issue is when section is cloned id of elements are same, so how can I change id when section is cloned.
My js functions
var countCopies1;
var clone ;
function duplicate() {
var original = document.getElementById('duplicater1');
clone = original.cloneNode(true);
var countCopies = $('body').html().split('duplicater').length;
clone.id = "duplicater"+countCopies;
original.parentNode.appendChild(clone);
countCopies1 = countCopies;
}
My table with id duplicater1. When I duplicate it id changes to duplicater2, duplicater3 and so on, but my id customer, project, post, hours stay the same in new duplicated table. How can I change them & I need in duplicater2 id customer1, project1, post1, hours1.
I will be thankful if u help me!
<div id="duplicater1">
<br></br>
<table class="table table-bordered">
<thead>
<tr>
<th style="width:16%;text-align:center">{Customer}</th>
<th style="width:16%;text-align:center">{Project}</th>
<th style="width:16%;text-align:center">{Activity}</th>
<th style="width:16%;text-align:center">{Hours}</th>
<th style="width:16%;text-align:center">{Comment}</th>
<th style="width:5%"> </th>
</tr>
</thead>
<tbody>
<td>
<div class="form-inline" style="text-align:center"><select style="width:200px" id="customer" class="form-control" onchange="getCustomerAddWork(this)">{CUSTOMERS}</select></div>
</td>
<td>
<div class="form-inline" style="text-align:center"><select style="width:200px" id="project" class="form-control" onchange="getProjectAddWork(this)"></select></div>
</td>
<td>
<div class="form-inline" style="text-align:center"><select style="width:200px" id="post" class="form-control"></select></div>
</td>
<td>
<div class="form-inline" style="text-align:center">
<div class="form-group">
<input type="number" class="form-control" id="hours" placeholder="{Hours}">
</div>
</div>
</td>
<td>
<div class="form-inline" style="margin-bottom:1em;text-align:center">
<div class="form-group">
<textarea class="form-control" id="comment" placeholder="{Comment}"></textarea>
</div>
</div>
</td>
<td>
<button type="button" class="btn btn-danger" style="width:70px"
onclick="Remove()">{Delete}</button>
</td>
</tbody>
</table>
</div>
</div>
<div class="container-fluid bg-2 text-center" style="margin-top:5em;margin-bottom:3em;">
<button type="button" class="btn btn-success" onclick="duplicate()">{Add}</button>
<button type="button" class="btn btn-info" onclick="AddWork()">{Submit}</button>
<button type="button" class="btn btn-primary" onclick="Redirect()">{Cancel}</button>
</div>
</form>
Since you have jQuery, I would do something like this:
var original = $("#duplicater1");
function duplicate() {
var countCopies = $("[id^='duplicater']").length + 1;
var cloned = original.clone();
var cloned.attr("id", "duplicater" + countCopies);
$(cloned).find("[id]").each(function(){
var current = $(this);
var currentId = current.attr("id");
var ids = $("[id='" + currentId + "']");
if(ids.length > 1 && ids[0]==this){
var newId = currentId.substring(0, currentId - 1);
current.attr("id", newId + countCopies);
}
});
original.parent().append(cloned);
}
My table with id duplicater1. When I duplicate it id changes to
duplicater2, duplicater3 and so on, but my id customer, project, post,
hours stay the same in new duplicated table. How can I change them & I
need in duplicater2 id customer1, project1, post1, hours1.
Yes, as duplicate identifiers are not good markup you should indeed change them.
However, duplicate identifiers within unique identifiable containers are functionally not an issue (Though still should be changed).
To address your actual question, yes you can write a loop that goes through each element within the duplicator container and append a number to it and I'm sure there are answers showing you how to and they are perfectly fine.
I would however try to address the duplicate identifier issue in another way that doesn't require maintaining code to do this.
An approach I have been using in numerous web projects in those type of scenarios is to use data-id as an attribute to identify the containers and to allow you to group them as well as the elements inside.
Note, you can use classes or data-xxx or what ever takes your fancy, I personally just prefer data-id for these cases
Instead of using <div id="duplicater1/2/3"> just use <div data-id="duplicater"> to identify the "type" of component/form you are working with.
Inside, do the same with each element, such as <select data-id="customer"> or <select data-id="project">
This solves the cloning problem all together as you can now clone each
duplicator without the need to rename anything at all and you don't
need to maintain custom code renaming element identifiers
In regards to the bound events, you don't have to worry about them either as each element when it raises an event such as getProjectAddWork(this) is already within context.
Say you trigger the getProjectAddWork(this) event and need to get to your duplicator container your are in, you can simple do something similar to $(this).closest('[data-id="duplicator"]'); or to get to the outer form $(this).closest('form'); etc..
Sure, you can achieve the same by only renaming the duplicator id as you already do and then do $(this).closest('#duplicator'); but in my humble opinion I rather prevent duplicate identifiers and not having to maintain code to rename identifiers as well as base selectors on contextual awareness within their respective "component"
I use jQuery as you tagged your question with it but you can do the same with just plain JavaScript
I have a div structured this way:
<div class="sez-form ripart">
<table class="inc_prev"></table>
<div class="previsioni">A</div>
</div>
In table "inc_prev" I have a button that allows you to add another group of these. So by hitting the button you will get a structure like this:
<div class="sez-form ripart">
<table class="inc_prev"></table>
<div class="previsioni">A</div>
</div>
<div class="sez-form ripart">
<table class="inc_prev"></table>
<div class="previsioni">B</div>
</div>
Each "inc_prev" table has this html:
<table class="inc_prev">
<tbody>
<tr>
<td><label>Mese: </label><select id="mese[]" name="mese[]"></td>
<td><label>Anno: </label><select id="anno[]" name="anno[]"></td>
<td><label>Percentuale: </label><input class="importo" type="text" name="percent[]" maxlength="14" size="15" value="">%</td>
<td><img class="addRow" src="../images/plus.png"></td>
</tr>
</tbody>
</table>
This is my JS:
$(document).on('blur','.importo',function(){
var input_value = $(this).val();
var azione =$('#azione').val();
if ($(this).closest('.sez-form').find('.previsioni').length) {
$('.previsioni').load('bp/ripart_prev.php?perc='+input_value+'&id='+azione);
}else{
console.log('qui');
$(this).closest('.sez-form').append('<div class="previsioni"></div>');
$('.previsioni').load('bp/ripart_prev.php?perc='+input_value+'&id='+azione);
}
});
It appends the "previsioni" div if it's not there or update it loading content from DB. In the starting situation it works fine: previsioni div is added or updated in the right way. If I hit the plus button and add the second block when this JS gets triggered both the "previsioni" div get updated with the same content.
So my question is: "how do I change my JS so that when executed only the target "previsioni" is updated?" So if I blur the second "importo" only it's "previsioni" (B) gets updated? I am already using closest as mentioned here but this is not preventing the other previsioni to be updated too
Problem is $('.previsioni') will select all the existing elements with the class. You need to reuse the relationship to target the specific div. Here in the code snippet I have cached the $(this).closest('.sez-form').find('.previsioni') in an object.
Read inline comments
$(document).on('blur','.importo',function(){
var input_value = $(this).val();
var azione =$('#azione').val();
//Use the relationship again to traverse and cache it in a vraible the content
var previsioni = $(this).closest('.sez-form').find('.previsioni');
//If exist
if (previsioni.length) {
previsioni.load('bp/ripart_prev.php?perc='+input_value+'&id='+azione)
}else{
console.log('qui');
//Create div using JQuery
var div = $('<div class="previsioni"></div>');
//Load the content
div.load('bp/ripart_prev.php?perc='+input_value+'&id='+azione)
//Append the data
$(this).closest('.sez-form').append(div);
}
});
I'm refactoring a code on a generated web page and there is a div (tab) which can occur multiple times. There is a small section with check-boxes on each and every such div, which lets you choose other divs that will be shown.
Since there is a chance for other divs to be added to the page I wanted to make the code modular. Meaning that every checkbox id is identical to the class of the div, which it should toggle, with added "Div" at the end. So I use checked id, concat it with "." and "Div" and try to find it in closest fieldset.
Here is the almost working fiddle: http://jsfiddle.net/ebwokLpf/5/ (I can't find the way to make the onchange work)
Here is the code:
$(document).ready(function(){
$(".inChecks").each(function(){
changeDivState($(this));
});
});
function changeDivState(element){
var divClassSel = "." + element.attr("id") + "Div";
var cloField = element.closest("fieldset");
if(element.prop("checked")){
cloField.find(divClassSel).toggle(true);
} else {
cloField.find(divClassSel).toggle(false);
}
}
Aside for that not-working onchange, this functionality does what it's intended to do. However only on the jsfiddle. The same code does not work on my page.
When I used log on variables from the code, the result was as this
console.log(divClassSel) => inRedDiv
console.log($(divClassSel)) => Object[div.etc.]
console.log(cloField) => Object[fieldset.etc.]
//but
console.log(cloField.find(divClassSel)) => Object[]
According to firebug the version of the jQuery is 1.7.1
Since I can't find any solution to this is there any other way how to make it in modular manner? Or is there some mistake I'm not aware of? I'm trying to avoid writing a function with x checks for element id, or unique functions for every check-box (the way it was done before).
Remove the inline onchange and also you don't need to iterate on the elements.
Just write one event on class "inCheckes" and pass the current element reference to your function:
HTML:
<fieldset id="field1">
<legend>Fieldset 1</legend>
<table class="gridtable">
<tr>
<td>
<input id="inRed" class="inChecks" type="checkbox" checked="checked" />
</td>
<td>Red</td>
</tr>
<tr>
<td>
<input id="inBlue" class="inChecks" type="checkbox" />
</td>
<td>Blue</td>
</tr>
</table>
<div class="inDivs">
<div class="inRedDiv redDiv"></div>
<div class="inBlueDiv blueDiv" /></div>
</fieldset>
<fieldset id="field2">
<legend>Fieldset 2</legend>
<table class="gridtable">
<tr>
<td>
<input id="inRed" class="inChecks" type="checkbox" />
</td>
<td>Red</td>
</tr>
<tr>
<td>
<input id="inBlue" class="inChecks" type="checkbox" checked="checked" />
</td>
<td>Blue</td>
</tr>
</table>
<div class="inDivs">
<div class="inRedDiv redDiv"></div>
<div class="inBlueDiv blueDiv" /></div>
</fieldset>
JQUERY:
$(document).ready(function () {
$(".inChecks").change(function () {
changeDivState($(this));
})
});
FIDDLE:
http://jsfiddle.net/ebwokLpf/4/
As gillesc said in the comments changing the javascript code to something like this made it work.
$(document).ready(function(){
$(".inChecks").each(function(){
changeDivState($(this));
});
$(".inChecks").on("change", function() {
changeDivState($(this));
});
});
function changeDivState(element){
var divClassSel = "." + element.attr("id") + "Div";
var cloField = element.closest("fieldset");
if(element.prop("checked")){
cloField.find(divClassSel).toggle(true);
} else {
cloField.find(divClassSel).toggle(false);
}
}
You asked for an other way how to make it in modular manner:
You can create a jQuery plugin which handles the logic for one fieldset including changing the color when clicking different checkboxes.
This way all logic is bundled in one place (in the plugin) and you can refine it later on.
For example you can decide later on that the plugin should create the whole html structure of the fieldset (like jQuery UI slider plugin creates the whole structure for the slider element) and therefore change the plugin.
The code for the (first version) of your jQuery plugin could look something like this:
$.fn.colorField = function() {
var $colorDiv = this.find('.colorDiv'),
$inputs = this.find('input'),
$checked = $inputs.filter(':checked');
if($checked.length) {
// set initial color
$colorDiv.css('background', $checked.attr('data-color'));
}
$inputs.change(function() {
var $this = $(this),
background = '#999'; // the default color
if($this.prop('checked')) {
// uncheck the other checkboxes
$inputs.not(this).prop('checked', false);
// read the color for this checkbox
background = $(this).attr('data-color');
}
// change the color of the colorDiv container
$colorDiv.css('background', background);
});
};
The plugin uses the data-color-attributes of the checkboxes to change the color of the colorDiv container. So every checkbox needs an data-color attribute, but multiple divs for different colors are not necessary anymore.
The HTML code (for one fieldset):
<fieldset id="field1">
<legend>Fieldset 1</legend>
<table class="gridtable">
<tr><td><input id="inRed" class="inChecks" type="checkbox" checked="checked" data-color='#ff1005' /></td><td>Red</td></tr>
<tr><td><input id="inBlue" class="inChecks" type="checkbox" data-color='#00adff' /></td><td>Blue</td></tr>
</table>
<div class="colorDiv"></div>
</fieldset>
Now you can create instances with your colorField-plugin like this:
$(document).ready(function(){
$('#field1').colorField();
$('#field2').colorField();
});
Here is a working jsFiddle-demo
Im currently trying to get all input elements from a DIV.
$("[required]").each(function() {
});
I have this code which returns every element with a required attribute.
I know within the function of that each() I can use each item like:
$(this)
So I get the div ID's shown below, and try to get all the inputs from it via:
var id = $(this).attr('id');
console.log("### " + id);
console.log($("#" + id + " > :input").length);
Which returns 0 when I have 4 in put elements within that DIV (also theres a table in the div).
What I would ideally like to do is for each input element within my div, print its ID.
UPDATED
<div id="contactAddress" required="true">
<td>Addres line 1:</td>
<td colspan="2">
<input type="text"/>
</td>
<td>Addres line 2:</td>
<td colspan="2">
<input type="text" />
</td>
</tr>
</div>
console.log($(this).html());
Shows nothign but if i add anythign outsire the or like below...
<div id="contactAddress" required="true">
<input type="text" />
And run console.log($(this).html()); It shows it put not the table?
Any ideas im using Jquery Mobile
This below will find all inputs inside the div element. It will then leave a log of the id of this element.
$("div > input").each(function() {
console.log( $(this).attr("id") );
});
if you need the div id containing the inputs you could use .parent()
$("input").each(function() {
console.log( $(this).parent().attr("id") );
});
I have been working on a project recently and have been required to learn jQuery to do it. Not such an easy thing to learn for a beginner ha. Anyway I have been trying to have a few div tags that are switched between depending on which one the user has clicked on.
The first one, "Add field" should switch to a div that contains a button to add a new field. Now instead of putting a large amount of code here I instead put it into http://jsfiddle.net/9acEk/8/ so you could see a working example, or rather not working. My problem is that when I change a tab and click back on "Add field" tab the buttons no longer work. the page opens with a button that when clicked adds a text box. However even if I just click on the "Add field" tab the button no longer does anything, I have used alert boxs to display the code and it is exactly the same. I have no idea why this does not work after clicking on the tab, it makes no sense to me as the code, as mentioned, is exactly the same.
Apologies if the question makes no sense, any questions on it just ask me and I shall do my best to clear it up. Thanks a lot in advance to any help given, it is appreciated.
EDIT:
It seems the jsfiddle does not work(Sorry very new to that as well) so I shall instead put code here.
<html>
<body>
<table width ="100%" alight="right">
<td width ="51.5%"></td>
<td> <div id="addField" class="tabOptions">Add field</div></td>
<td><div id="fieldProperties" class="tabOptions">Field Properties</div></td>
<td> <div id="formProperties" class="tabOptions">Form Properties</div></td>
</table>
<hr>
<table align ="left"style="background-color: white" width="100%">
<tr>
<tr>
<div id="formName" class="formDetails">
<h2>Untitled</h2>
<h4>This is your form description</h4>
</div>
</tr>
<td width ="50%">
<ul id ="firstColumn">
<div id="identifier">
</div>
</ul>
</td>
<td>
<ul id ="secondColumn" width="5%">
<div id="placeholder">
<div id="mainPanel">
<li><input type="button" class="formCreationButton" id="textAdd" value="Single line text" /></li>
</div>
</div>
</ul>
</td>
<tr>
</table>
jQuery
var counter = 1;
var textAreaCounter = 1;
var textBoxCounter = 1;
var tempStorage = $('div#placeholder').html();
$(document).ready(function() {
$(".formDetails").live('click','div',function(){
var divID = this.id;
alert(divID);
alert(document.getElementById(divID).innerHTML);
});
$(".container").live('click','div',function(){
var divID = this.id;
if(divID != ""){
alert(divID);
var content = document.getElementById(divID).outerHTML;
// alert(content);
var text = document.getElementById(divID).innerHTML;
alert(text);
var textboxId = $('div.container')
.find('input[type="text"]')[0]
.id;
$('div#placeholder').html(content);
}
else{
}
});
$("#addField").live('click','div',function(){
$('div#placeholder').html(tempStorage);
});
$("#fieldProperties").live('click','div',function(){
var content = "<p>Content of fields should be here</p>";
$('div#placeholder').html(content);
});
$("#formProperties").live('click','div',function(){
var content = "<p>Content of form should be here</p>";
$('div#placeholder').html(content);
});
$('#textAdd').click(function() {
var newdiv = document.createElement('div');
newdiv.innerHTML = "Textbox " + textBoxCounter + " <br><div id='container " + textBoxCounter + "' class='container'><li><input type='text' value='TEXT' id='textBox " + textBoxCounter +"' name='textBox " + textBoxCounter +"')'></li></div></br>";
document.getElementById("identifier").appendChild(newdiv);
textBoxCounter++
counter++;
});
});
Change
$('#textAdd').click(function()
to
$('#textAdd').live('click',function() {
and it works fine .. working example here
A couple of things ....
You are using a very old version of jQuery - 1.4.4. I suggest that if your going to learn something new you learn the latest release .... and in that latest release the live() function has been replaced by on() - so your code would look like this :
$(document).on('click','#textAdd',function() {
Where document is any parent element present on page load
Working example here