I got some help earlier regarding selectors, but I'm stuck with the following.
Lets say you have a plugin like this
$('#box').customplugin();
how can I get the #box as a string in the plugin?
Not sure if that's the correct way of doing it, and any other solution would be great as well.
Considering #box is a select dropdown,
The problem I'm having is if I do the regular javascript
$('#box').val(x);
The correct option value gets selected,
but if i try the same inside a plugin
.....
this.each(function() {
var $this = $(this);
$this.val(x);
the last code doesn't really do anything.
I notice I'm having trouble targeting #box inside the plugin because it's a object and not a string...
Any help would be appreciated.
Thanks!
Edit:: Putting in the code I'm working in for better understanding
(function($){
$.fn.customSelect = function(options) {
var defaults = {
myClass : 'mySelect'
};
var settings = $.extend({}, defaults, options);
this.each(function() {
// Var
var $this = $(this);
var thisOpts = $('option',$this);
var thisSelected = $this[0].selectedIndex;
var options_clone = '';
$this.hide();
options_clone += '<li rel=""><span>'+thisOpts[thisSelected].text+'</span><ul>'
for (var index in thisOpts) {
//Check to see if option has any text, and that the value is not undefined
if(thisOpts[index].text && thisOpts[index].value != undefined) {
options_clone += '<li rel="' + thisOpts[index].value + '"><span>' + thisOpts[index].text + '</span></li>'
}
}
options_clone += '</ul></li>';
var mySelect = $('<ul class="' + settings.myClass + '">').html(options_clone); //Insert Clone Options into Container UL
$this.after(mySelect); //Insert Clone after Original
var selectWidth = $this.next('ul').find('ul').outerWidth(); //Get width of dropdown before hiding
$this.next('ul').find('ul').hide(); //Hide dropdown portion
$this.next('ul').css('width',selectWidth);
//on click, show dropdown
$this.next('ul').find('span').first().click(function(){
$this.next('ul').find('ul').toggle();
});
//on click, change top value, select hidden form, close dropdown
$this.next('ul').find('ul span').click(function(){
$(this).closest('ul').children().removeClass('selected');
$(this).parent().addClass("selected");
selection = $(this).parent().attr('rel');
selectedText = $(this).text();
$(this).closest('ul').prev().html(selectedText);
$this.val(selection); //This is what i can't get to work
$(this).closest('ul').hide();
});
});
// returns the jQuery object to allow for chainability.
return this;
}
Just a heads-up: .selector() is deprecated in jQuery 1.7 and removed in jQuery 1.9: api.jquery.com/selector.
– Simon Steinberger
Use the .selector property on a jQuery collection.
Note: This API has been removed in jQuery 3.0. The property was never a reliable indicator of the selector that could be used to obtain the set of elements currently contained in the jQuery set where it was a property, since subsequent traversal methods may have changed the set. Plugins that need to use a selector string within their plugin can require it as a parameter of the method. For example, a "foo" plugin could be written as $.fn.foo = function( selector, options ) { /* plugin code goes here */ };, and the person using the plugin would write $( "div.bar" ).foo( "div.bar", {dog: "bark"} ); with the "div.bar" selector repeated as the first argument of .foo().
var x = $( "#box" );
alert( x.selector ); // #box
In your plugin:
$.fn.somePlugin = function() {
alert( this.selector ); // alerts current selector (#box )
var $this = $( this );
// will be undefined since it's a new jQuery collection
// that has not been queried from the DOM.
// In other words, the new jQuery object does not copy .selector
alert( $this.selector );
}
However this following probably solves your real question?
$.fn.customPlugin = function() {
// .val() already performs an .each internally, most jQuery methods do.
// replace x with real value.
this.val(x);
}
$("#box").customPlugin();
This page talks about getting the selector:
http://api.jquery.com/selector/
That's how I get selector strings inside my plugins in 2017:
(function($, window, document, undefined) {
$.fn._init = $.fn.init
$.fn.init = function( selector, context, root ) {
return (typeof selector === 'string') ? new $.fn._init(selector, context, root).data('selector', selector) : new $.fn._init( selector, context, root );
};
$.fn.getSelector = function() {
return $(this).data('selector');
};
$.fn.coolPlugin = function() {
var selector = $(this).getSelector();
if(selector) console.log(selector); // outputs p #boldText
}
})(jQuery, window, document);
// calling plugin
$(document).ready(function() {
$("p #boldText").coolPlugin();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>some <b id="boldText">bold text</b></p>
The idea is to conditionally wrap jQuery's init() function based on whether a selector string is provided or not. If it is provided, use jQuery's data() method to associate the selector string with the original init() which is called in the end. Small getSelector() plugin just takes previously stored value. It can be called later inside your plugin. It should work well with all jQuery versions.
Because of the deprecation and removal of jQuery's .selector, I have experimented with javascript's DOM Nodes and came up with a 2017 and beyond solution until a better way comes along...
//** Get selector **//
// Set empty variables to work with
var attributes = {}, // Empty object
$selector = ""; // Empty selector
// If exists...
if(this.length) {
// Get each node attribute of the selector (class or id)
$.each(this[0].attributes, function(index, attr) {
// Set the attributes in the empty object
// In the form of name:value
attributes[attr.name] = attr.value;
});
}
// If both class and id exists in object
if (attributes.class && attributes.id){
// Set the selector to the id value to avoid issues with multiple classes
$selector = "#" + attributes.id
}
// If class exists in object
else if (attributes.class){
// Set the selector to the class value
$selector = "." + attributes.class
}
// If id exists in object
else if (attributes.id){
// Set the selector to the id value
$selector = "#" + attributes.id
}
// Output
// console.log($selector);
// e.g: .example #example
So now we can use this for any purpose. You can use it as a jQuery selector... eg. $($selector)
EDIT: My original answer would only get the attribute that appears first on the element. So if we wanted to get the id that was placed after the class on the element, it wouldn't work.
My new solution uses an object to store the attribute information, therefore we can check if both or just one exists and set the required selector accordingly. With thanks to ManRo's solution for the inspiration.
Related
I'm stuck trying to retrieve the selected value from a 'select' element via javascript. I can't even get the element from the DOM with either jQuery or document.getElementById().
Here is my code:
function getDropdown(headerText, options, id) {
var container = document.createElement('div');
container.setAttribute('class', 'nfvo-drop-down-container');
var dd = document.createElement('select');
$(dd).attr('id', id);
for(var val in options) {
$('<option />', {value: val, text: options[val]}).appendTo(dd);
}
if(headerText) {
var span = document.createElement('span');
span.setAttribute('class', 'panel-header');
span.appendChild(document.createTextNode(headerText));
container.appendChild(span);
}
container.appendChild(dd);
return container;
}
var dd = getDropDown('My dropdown', [1,2,3,4], 'ddID);
var e = document.getElementById('ddID');
var e2 = $('#ddID');
var e3 = $('#ddID').val();
var e4 = $('#ddID').text();
If I were to console.log these values I would get these results:
console.log(e) -> 'null'
console.log(e2) -> <Got the element>
console.log(e3) -> 'undefined'
console.log(e4) -> <Nothing, just a blank>
Any ides on what might cause this problem?
This block of code is within a '.then' function call e.g:
$.when(...).then(function(...)
<Here is the code>
);
EDIT: There was a typo in the post which have now been fixed. This is not the source of my problem.
I should also mention that I add this div to a ContentPane via the Dojo toolkit and I can see dropdown in the DOM via the inspection tool in chrome.
You won't get select box object by using document.getElementById('ddID')
since you have not added your object to any object in the document.
You will get select box object from the dd object by using dd.childNodes[1]
getDropDown creates an element with that id, puts it in a div, and then returns the div.
It never adds any of those elements to any element in the document.
Thus, when you search the document for an element with the matching id, it isn't there.
I'm trying to swap select option values with jQuery when a links clicked, at the moment its just resetting the select when the links clicked, not sure what's going wrong?:
jQuery:
$(function () {
$("#swapCurrency").click(function (e) {
var selectOne = $("#currency-from").html();
var selectTwo = $("#currency-to").html();
$("#currency-from").html(selectTwo);
$("#currency-to").html(selectOne);
return false;
});
});
JS Fiddle here: http://jsfiddle.net/tchh2/
I wrote it in a step-by-step way so it is easier to understand:
$("#swapCurrency").click(function (e) {
//get the DOM elements for the selects, store them into variables
var selectOne = $("#currency-from");
var selectTwo = $("#currency-to");
//get all the direct children of the selects (option or optgroup elements)
//and remove them from the DOM but keep events and data (detach)
//and store them into variables
//after this, both selects will be empty
var childrenOne = selectOne.children().detach();
var childrenTwo = selectTwo.children().detach();
//put the children into their new home
childrenOne.appendTo(selectTwo);
childrenTwo.appendTo(selectOne);
return false;
});
jsFiddle Demo
Your approach works with transforming DOM elements to HTML and back. The problem is you lose important information this way, like which element was selected (it is stored in a DOM property, not an HTML attribute, it just gives the starting point).
children()
detach()
appendTo()
That happens because you remove all elements from both <select> fields and put them as new again. To make it working as expected you'd better move the actual elements as follows:
$("#swapCurrency").click(function(e) {
var options = $("#currency-from > option").detach();
$("#currency-to > option").appendTo("#currency-from");
$("#currency-to").append(options);
return false;
});
DEMO: http://jsfiddle.net/tchh2/2/
You are replacing the whole HTML (every option) within the <select>. As long as each select has the same amount of options and they correspond to each other, you can use the selected index property to swap them:
$("#swapCurrency").click(function (e) {
var selOne = document.getElementById('currency-from'),
selTwo = document.getElementById('currency-to');
var selectOne = selOne.selectedIndex;
var selectTwo = selTwo.selectedIndex;
selOne.selectedIndex = selectTwo;
selTwo.selectedIndex = selectOne;
return false;
});
JSFiddle
I have some data coming from the server in which I fill A Div in the Html page with.
The way I write the div is as follows:
<div class="BigDiv"><label class = "AttList" Std_Id="' + Std_Id + '">' + Std_Name +'</label></div>
Now, I want the data inside this div.
There are some other labels inside the div so I use this.children to access this label.
var labels = $(this).children('div');
var StdName = this.children[0].childNodes[0].nodeValue;
I want to access the Std_Id inside the Std_Id attribute, but I don't know how to do it ... Do you have any ideas?
Thanks.
Assuming that $(this) is a reference to the .BigDiv element:
var StdName = $(this).find('label').attr('Std_Id');
Or, similarly, and with the assumption that this is the .BigDiv element:
var children = this.childNodes;
for (var i=0,len=children.length; i<len; i++){
if (children[i].nodeType == 1 && children[i].tagName.toLowerCase() == 'label'){
var StdName = this.getAttribute('Std_Id');
}
}
References:
jQuery:
attr().
find().
JavaScript
element.getAttribute().
node.nodeType.
tagName.
toLowerCase().
Use getAttribute:
var labels = $(this).children('div');
var StdId = this.children[0].getAttribute("Std_Id");
Note that, according to the HTML5 spec, custom attributes should start with data-, though most browsers can tolerate it.
To save elements, which were selected using a jQuery-Selector, do this:
$labels = $('.BigDiv').find('label');
Now you can loop through each label with jQuery's foreach loop:
$.each($labels, function() {
var std_id = $(this).attr('Std_Id');
// do something with std_id
});
You could use the attr method as such,
var value = $('.AttList').attr('Std_Id');
EDIT
OK, so you for your implementation, you need to do this...
var value = $(this).find('.AttList').attr('Std_Id');
Assuming that this is the div or the parent of that div
I know I can load in html in to a div with:
$("#my_div").load("http://www.mypage.com");
but I want to do is load html into a variable like:
my_var = load("http://www.mypage.com");
Any help is great.
I would like to loop though some items like:
HLS.functions.LoadSideModules = function() {
HLS.sideModuleContent = new Object();
for(var i = 0; i < HLS.currentModuleConfig.POLICIES.POLICY.length; i++) {
for(var y = 0; y < HLS.currentModuleConfig.POLICIES.POLICY[i].PAGES.PAGE.length; y++) {
for(var POS in HLS.currentModuleConfig.POLICIES.POLICY[i].PAGES.PAGE[y]) {
var item = HLS.currentModuleConfig.POLICIES.POLICY[i].PAGES.PAGE[y][POS];
if(!HLS.sideModuleContent[item]) {
HLS.sideModuleContent[item] = j.get(HLS.config.K2GETMODULE + HLS.currentModuleConfig.POLICIES.POLICY[i].PAGES.PAGE[y][POS]);
}
}
}
}
};
$.get("http://www.mypage.com", function( my_var ) {
// my_var contains whatever that request returned
});
Underneath, jQuery will launch an ajax request which fires to the given URL. It also tries to intelligently guess which data is going to be received (if it's valid html you don't need to specify). If you need to get another data type just pass that in as last argument, for instance
$.get("http://www.mypage.com", function( my_var ) {
// my_var contains whatever that request returned
}, 'html'); // or 'text', 'xml', 'more'
Reference: http://api.jquery.com/jQuery.get/
You could also create an element in memory and use load() on it:
var $div = $('<div>');
$div.load('index.php #somediv', function(){
// now $(this) contains #somediv
});
The advantage is that you can specify which part of index.php you want to load by using a selector ( #somediv )
While creating a new element is one option, you could also clone any element. This copies all the attributes and the values of the old Node, as it says, 'exact clone'.
In case you want only a particular section of the html to be copied, this also provides the flexibility to fill all the contents within the particular element hierarchy (i.e., with all the children included) from the fetched page.
For instance, if the hierarchy is -
<div id='mydiv'>
<div>
<span>
...</span>
</div>
</div>
//...
var oldElement = document.getElementById('mydiv');
var newElement = oldElement.cloneNode(true);
/* #selector selects only that particular section & the '> *' enables to copy all of the child nodes under the parent #selector
Replace URL with the required value
function specification is optional... */
jQuery(newElement).load(URL+'#selector > *'[,function(response, status, xhr){}]);
//...
Now you can programatically process the variable newElement as you want (using native javascript as well, since it is a native element).
function includeHTML_callBack(result){
var my_var = result;
}
function includeHTML(link, callBack) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
callBack(this.responseText);
}
}
xhttp.open("GET", link, true);
xhttp.send();
return;
}
includeHTML("http://www.mypage.com", includeHTML_callBack);
Here is the code.
function product_analysis_global() {
$(':checkbox:checked').each(function() {
$('#product_' + this.alt).load(this.title);
$('#product_quantity_PRI_' + this.alt).value = this.value;
});
}
All working except the last line that is not working, any ideas. Should return the value of the current checkbox to the appropriate field '#product_quantity_PRI_' + this.alt
Many Thanks.
.value isn't a jQuery object property (it's a DOM object one), it should be .val() like this:
$('#product_quantity_PRI_' + this.alt).val(this.value);
Or (more for illustration), the direct jQuery-less DOM method:
document.getElementById('product_quantity_PRI_' + this.alt).value = this.value;
Use the val() function.
var $this = $(this)
$('#product_quantity_PRI_' + $this.attr('alt')).val($this.val());