How do I go about locating & getting a value for an element like the following?
<input type="hidden" title="username" value="joe.doe">
Any suggestions much appreciated.
var userNameElm = $('input[title=username]');
it('is present but invisible', function() {
expect(userNameElm.isPresent()).toBeTruthy();
expect(userNameElm.isDisplayed()).toBeFalsy();
});
it('should have proper value attribute', function() {
expect(userNameElm.getAttribute('value')).toEqual('joe.doe');
});
If you are trying to access an element with data-* attributes as we would do in Bootstrap, we can select such elements as follows:-
var loginBtn = $('a[data-target="#login-modal"]');
This is same as the accepted answer except that it has "" around #login-modal. Without the "", it doesn't work.
Good Luck.
Related
I'm trying to pass a custom form attribute (category) through jQuery UI Autocomplete to use in a product search. The form looks like <form id="BulkOrderForm" category="samplecategory"><input></input>...</form> and contains inputs that use the autocomplete script. There can be several forms on each page, so I need to be able to get the category value from the form that contains the active input field.
Here's my source:
function autocomplete() {
$("input.wcbulkorderproduct").autocomplete({
element: function(){
var element = $('form#BulkOrderForm').attr('category');
return element;
},
source: function(request, response, element){
$.ajax({
url: WCBulkOrder.url+'?callback=?&action='+acs_action+'&_wpnonce='+WCBulkOrder.search_products_nonce,
dataType: "json",
data: {
term: request.term,
category: element
},
success: function(data) {
response(data);
}
});
}
});
}
Any thoughts on how this can be acheived?
If I'm understanding correctly, you're trying to use the active input's parent form in the ajax request. Here's a way to achieve that:
Html:
<form data-category="form1">
<input type="text" />
<input type="text" />
</form>
<form data-category="formB">
<input type="text" />
<input type="text" />
</form>
JS:
$('form').each(function () {
var category = $(this).data('category');
$(this).find('input').autocomplete({
source: function (request, response) {
response([category]);
}
});
});
Instead of using autocomplete on a catch-all selector that gets inputs from all forms, first select the forms themselves. For each one, extract the category, then select all child inputs and call autocomplete on that result. Then you can use the category variable in the ajax call - in the example I'm simply passing it to the callback to display.
http://jsfiddle.net/Fw2QA/
I'll give you another solution, you can lookup the parent form of the active input, and extract the attribute from it. Because I don't know if this category in your form is dynamic or no, or either if you can control all of the process involved in your code, I'll give you a more generic solution, although if that attribute is dynamic "Turch" solution is way better than mine, by letting the data functionality of jquery handle the attribute changes, if it's static, than you can just do it like this:
function autocomplete() {
var element = $("input.wcbulkorderproduct").autocomplete({
source: function(request, response){
$.ajax({
url: WCBulkOrder.url+'?callback=?&action='+acs_action+'&_wpnonce='+WCBulkOrder.search_products_nonce,
dataType: "json",
data: {
term: request.term,
category: element
},
success: function(data) {
response(data);
}
});
}
}).parents('form').first().attr('category');
//chained call, sets autocomplete, grabs the parent form and the attribute
//which is saved on the variable element, and is used on every call through
//javascript context inheritance.
}
UPDATE
A little example illustrating my suggestion (provided by #Turch > thanks), can be found here.
How can I select YUI node with this keyword?
Example:
<a href='javascript:test(this);'>Click Me!</a>
<script>
function test(el){
YUI().use('transition', function (Y) {
var selectedElement = Y.one(el);
});
}
</script>
Thanks a lot for help.
In your code, "this" will refer to the Window object, not the link. A better way to do this in YUI is:
Click Me!
<script>
YUI().use('transition', function(Y) {
Y.one('#my-link').on('click', function(e) {
e.halt();
var selectedElement = e.target;
});
});
</script>
This avoid JavaScript embedded in the markup, which is considered best practice. Also, it wraps all your code in the YUI sandbox, which is the recommended way.
Not sure if this is possible but I'm trying, and keep coming up short.
http://plnkr.co/edit/Gcvm0X?p=info
I want a 'E' (element) directive that is replaced with a more complex nested HTML node using the 'templateUrl' feature of directives.
HTML defining the directive (form tag included for complete mental image):
<form id="frm" name="frm">
<ds-frm-input-container
class="col-md-1"
frm-Name="frm"
frm-obj="frm"
input-name="txtFName"
ds-model="user.firstName"></ds-frm-input-container>
</form>
TemplateUrl contents which 'replaces' the above directive 'ds-frm-input-container' HTML element:
<div>
<input
required
ng-minlength=0
ng-maxlength=50
class="form-control"
ng-model="dsModel"
placeholder="{{dsPlaceHolder}}" />
<span ng-if="showErrs" class="label label-danger">FFFFF: {{dsModel}}</span>
</div>
Controller and Directive:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = "Nacho";
$scope.user = {};
$scope.user.firstName = "";
})
.directive('dsFrmInputContainer', function(){
var ddo = {
priority: 0,
restrict: 'AE',
scope:
{
frmName: '#',
inputName: '#',
dsPlaceHolder: '#',
dsModel: '=',
frmObj: '='
},
templateUrl: 'template1.html',
replace: true,
controller: function($scope)
{
$scope.showErrs = true;
},
compile: function compile(ele, attr) {
return {
pre: function preLink(scope, ele, attr, controller)
{
},
post: function postLink(scope, ele, attr, controller)
{
var txt = ele.find('input');
txt.attr('id', scope.inputName);
txt.attr('name', scope.inputName);
//BLUR
txt.bind('blur', function () {
console.log("BLUR BLUR BLUR");
angular.forEach(scope.frmObj.$error, function(value, key){
var type = scope.frmObj.$error[key];
for(var x=0; x < type.length; x++){
console.log(type[x]);
}
});
event.stopPropagation();
event.preventDefault();
});
}
};
},
};
return ddo;
});
The directive replaces just fine and the input element is named just fine. The form object however doesn't include the input element name in the error information. This makes it impossible for me to single out the input element during a 'blur' event that is setup in the directive.
I am doing this trying to reduce the show/hide logic 'noise' in the html for error messages (spans) and it should be reusable.
UPDATE (2014.01.28):
2014.01.28:
Added promises. There is a service that allows validation on button clicks. NOT USING built in angular validation anymore found some compatibility issues with another library (or viceversa).
ORIGINAL:
Here is my form validation directive vision completed (plnkr link below). Completed in concert with the help of the stack overflow community. It may not be perfect but neither are butterfingers but they taste good.
http://plnkr.co/edit/bek8WR?p=info
So here is a link that has the name variables set as expected on the given input form error object. http://plnkr.co/edit/MruulPncY8Nja1BUfohp?p=preview
The only difference is that the inputName is read from the attrs object and is not part of the scope. This is then read before the link function is returned, in the compile phase, to set the template DOM correctly.
I have just spent quite a while trying to sort this problem out, and while this is not exactly what you were looking for, his is my attempt. It uses bootstrap for all the styling, and allows for required and blur validation, but its definitely not finished yet. Any thoughts or advice much appreciated.
https://github.com/mylescc/angular-super-input
I am able to do this using an ID prefix as the selector, but I need to be able to do it with classes instead. It's an each function for opening up different modal windows on the same page. I need to avoid using ID names because I have some modal windows that will have multiple links on the same page, and when using IDs, only the first link will work.
So here's the function as it works with IDs:
$('div[id^=ssfamodal-help-]').each(function() {
var sfx = this.id,
mdl = $(this),
lnk = $('.link-' + sfx),
cls = $('.ssfamodal-close'),
con = $('.ssfamodal-content');
lnk.click(function(){
mdl.show();
});
cls.click(function(){
mdl.hide();
});
mdl.click(function() {
mdl.hide();
});
con.click(function() {
return false;
});
});
and I'm trying to change it to classes instead, like:
$('div[class^=ssfamodal-help-]').each(function() {
var sfx = this.attr('class'),
etc.
But I cannot get it to work without using IDs. Is it possible?
EDIT Fixed error with semi-colon at end of Vars, and updated Fiddle with the fix. Still not working though.
Here's a Fiddle
** UPDATE **
To be clearer, I need to be able to refer to the same modal more than once on the same page. E.g.:
MODAL 1
MODAL 2
MODAL 3
MODAL 4
LINK TO MODAL 1
LINK TO MODAL 2
LINK TO MODAL 3
LINK TO MODAL 4
OTHER STUFF
LINK TO MODAL 1
LINK TO MODAL 4
LINK TO MODAL 3
OTHER STUFF
LINK TO MODAL 2
ETC.
When using classes get rid of the ID habit :
className1, className2, className3 ... etc
simply use
className
HTML:
<div class="ssfamodal-help-base ssfamodal-backdrop">
<div id="help-content" class="ssfamodal-content">
<span class="ssfamodal-close">[x]</span>
Howdy
</div>
</div>
<div class="ssfamodal-help-base ssfamodal-backdrop">
<div id="help-content" class="ssfamodal-content">
<span class="ssfamodal-close">[x]</span>
Howdy Ho
</div>
</div>
<span class="link-ssfamodal-help-base">One</span>
<span class="link-ssfamodal-help-base">Two</span>
LIVE DEMO
var $btn = $('.link-ssfamodal-help-base'),
$mod = $('.ssfamodal-help-base'),
$X = $('.ssfamodal-close');
$btn.click(function(i) {
var i = $('[class^="link-"]').index(this); // all .link-** but get the index of this!
// Why that?! cause if you only do:
// var i = $('.link-ssfamodal-help-base').index();
// you'll get // 2
// cause that element, inside a parent is the 3rd element
// but retargeting it's index using $('className').index(this);
// you'll get the correct index for that class name!
$('.ssfamodal-help-base').eq(i).show() // Show the referenced element by .eq()
.siblings('.ssfamodal-help-base').hide(); // hide all other elements (with same class)
});
$X.click(function(){
$(this).closest('.ssfamodal-help-base').hide();
});
From the DOCS:
http://api.jquery.com/eq/
http://api.jquery.com/index/
http://api.jquery.com/closest/
Here I created a quite basic example on how you can create a jQuery plugin of your own to handle modals: http://jsbin.com/ulUPIje/1/edit
feel free to use and abuse.
The problem is that class attributes can consist of many classes, rather than IDs which only have one value. One solution, which isn't exactly clean, but seems to work is the following.
$('div').filter(function () {
var classes = $(this).attr('class').split(/\s+/);
for (var i = 0; i < classes.length; i++)
if (classes[i].indexOf('ssfamodal-help-') == 0)
return true;
return false;
}).each(function() {
// code
});
jsFiddle
Or, equivalently
$('div').filter(function () {
return $(this).attr('class').split(/\s+/).some(function (e) {
return e.indexOf('ssfamodal-help-') == 0;
});
}).each(function() {
// code
});
jsFiddle
If there is one-to-one relationship between the modal helps and the modal links which it appears there is...can simplfy needing to match class values by using indexing.
For this reason you don't need unique class names, rather they just overcomplicate things. Following assumes classes stay unique however
var $helps=$('div[id^=ssfamodal-help-]');
var $help_links=$('div[id^=link-ssfamodal-help-]');
$help_links.click(function(){
var linkIndex= $help_links.index(this);
$helps.hide().eq( linkIndex ).show();
});
/* not sure if this is what's wanted, but appeared original code had it*/
$helps.click(function(){
$(this).hide()
})
/* close buttons using traverse*/
$('.ssfamodal-close').click(function(){
$(this).closest('div[id^=ssfamodal-help-]' ).hide();
});
Also believe that this code is a little more readable than original apporach
DEMO
Can you try this,
$('div[class^=ssfamodal-help-]').each(function() {
var sfx = $(this).attr('class');
console.log(sfx);
/*console log:
ssfamodal-help-base ssfamodal-backdrop
ssfamodal-help-base2 ssfamodal-backdrop
*/
});
Demo: http://jsfiddle.net/xAssR/51/
why don't you write like
$('div.classname').each(function() {
// you can write your desired code here
var sfx = this.attr('class');
var aa= this.attr('id');
});
or
$('.classname').each(function() {
// you can write your desired code here
var sfx = this.attr('class');
var aa= this.attr('id');
});
where classname is the name of the class used for the div in html
Thanks.
I'm at a loss for how to do something extremely simple: Get the current value of a AutoComplete YUI3 widget. I have the following markup:
<label for="targets">Target:</label>
<input id="targets" type="text"></input>
<label for="packets">Packet:</label>
<input id="packets"></input>
I have the following Javascript:
YUI().use("autocomplete", function(Y) {
Y.one('body').addClass('yui3-skin-sam');
var tgt = new Y.AutoComplete({
inputNode: '#targets',
source: '/telemetry/targets?target={query}',
render: true
})
var pkt = new Y.AutoComplete({
inputNode: '#packets',
source: '/telemetry/packets?target='+tgt.get('value')+',packet={query}',
render: true
})
});
tgt.get('value') always returns an empty string no matter what I have typed into the #targets input. What am I doing wrong?
tgt.get('value') is the right way to get the current value of the inputNode, but in this case it's being called immediately when the value of the source attribute is set at instantiation, not when the request is made later. Since no text has been entered at this point, the value is empty.
If you want the "target" parameter of the second AutoComplete instance to be set to the current value of the first AutoComplete instance's inputNode, the best thing to do would be to set a custom requestTemplate for the pkt instance:
var pkt = new Y.AutoComplete({
inputNode: '#packets',
source: '/telemetry/packets',
requestTemplate: function () {
return '?query=' + encodeURIComponent(pkt.get('query')) +
'&target=' + encodeURIComponent(tgt.get('value'));
},
render: true
});
This will ensure that the query string of each request is generated at request time rather than at instantiation time.