I have the following html code:
<h3 id="headerid"><span onclick="expandCollapse('headerid')">⇑</span>Header title</h3>
I would like to toggle between up arrow and down arrow each time the user clicks the span tag.
function expandCollapse(id) {
var arrow = $("#"+id+" span").html(); // I have tried with .text() too
if(arrow == "⇓") {
$("#"+id+" span").html("⇑");
} else {
$("#"+id+" span").html("⇓");
}
}
My function is going always the else path. If I make a javacript:alert of arrow variable I am getting the html entity represented as an arrow. How can I tell jQuery to interpret the arrow variable as a string and not as html.
When the HTML is parsed, what JQuery sees in the DOM is a UPWARDS DOUBLE ARROW ("⇑"), not the entity reference. Thus, in your Javascript code you should test for "⇑" or "\u21d1". Also, you need to change what you're switching to:
function expandCollapse(id) {
var arrow = $("#"+id+" span").html();
if(arrow == "\u21d1") {
$("#"+id+" span").html("\u21d3");
} else {
$("#"+id+" span").html("\u21d1");
}
}
If you do an alert of arrow what does it return? Does it return the exact string that you're matching against? If you are getting the actual characters '⇓' and '⇑' you may have to match it against "\u21D1" and "\u21D3".
Also, you may want to try ⇑ and ⇓ since not all browsers support those entities.
Update: here's a fully working example:
http://jsbin.com/edogop/3/edit#html,live
window.expandCollapse = function (id) {
var $arrowSpan = $("#" + id + " span"),
arrowCharCode = $arrowSpan.text().charCodeAt(0);
// 8659 is the unicode value of the html entity
if (arrowCharCode === 8659) {
$arrowSpan.html("⇑");
} else {
$arrowSpan.html("⇓");
}
// one liner:
//$("#" + id + " span").html( ($("#" + id + " span").text().charCodeAt(0) === 8659) ? "⇑" : "⇓" );
};
Use a class to signal the current state of the span.
The html could look like this
<h3 id="headerId"><span class="upArrow">⇑</span>Header title</h3>
Then in the javascript you do
$( '.upArrow, .downArrow' ).click( function( span ) {
if ( span.hasClass( 'upArrow' ) )
span.text( "⇓" );
else
span.text( "⇑" );
span.toggleClass( 'upArrow' );
span.toggleClass( 'downArrow' );
} );
This may not be the best way, but it should work. Didnt test it tough
Check out the .toggle() effect.
Here is something similar i was playing with earlier.
HTML:
<div id="inplace">
<div id="myStatic">Hello World!</div>
<div id="myEdit" style="display: none">
<input id="myNewTxt" type="text" />
<input id="myOk" type="button" value="OK" />
<input id="myX" type="button" value="X" />
</div></div>
SCRIPT:
$("#myStatic").bind("click", function(){
$("#myNewTxt").val($("#myStatic").text());
$("#myStatic,#myEdit").toggle();
});
$("#myOk").click(function(){
$("#myStatic").text($("#myNewTxt").val());
$("#myStatic,#myEdit").toggle();
});
$("#myX").click(function(){
$("#myStatic,#myEdit").toggle();
});
Maybe you're not getting an exact match because the browser is lower-casing the entity or something. Try using a carat (^) and lower-case "v" just for testing.
Edited - My first theory was plain wrong.
Related
Let's say we have element with custom attribute
... bind-html="varName" ...
I want to find all elements with attribute beginning with "bind-",
then get second part of it's name, which is unknown, in this case "html".
And at last get it's value "varName".
How do i achieved this with Jquery? I don't want to use second attribute to describe attibute to bind (like .. bind="varName" attr="html" ..)
You can use a loop through each object's attributes this.attributes and use the attribute's name and value properties.
Running example:
$("input").each(function() {
$.each(this.attributes, function() {
if (this.name.indexOf('bind-') == 0) {
console.log(this.name + ' has the value: ' + this.value);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<input bind-koby='hello'>
<input bind-douek='stack'>
<input will-not-show='yes'>
<input bind-hello='overflow'>
well that what you are looking for like
<div bind-html="varName">hi there i am </div>
well hi thats me
var namer = $(" *[attr*='bind']").text();
console.log(namer);
<div class="bindable" data-bind="html:varName1"></div>
<div class="bindable" data-bind="css:varName2"></div>
<div class="bindable" data-bind="js:varName3"></div>
<div class="bindable" data-bind="whatEver:varName4"></div>
(function(){
let bindables = $('.bindable');
bindables.each(function(){
let bindData = $(this).data('bind');
let bindDataArray = bindData.split(":");
console.log(bindDataArray);
});
}());
now u will get array with data u want
You can get all elements and their attributes which contain bind- by using jquery .properties and .indexOf() like following example.
// $("*") selects all elements in your html
$("*").each(function() {
$.each(this.attributes, function() {
// checks whether element has an attribute starts with "bind-" or not
if(this.specified && this.name.indexOf("bind-") !== -1) {
console.log("Attr Name: "+ this.name + " Attr Value: " + this.value)
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span bindNot-html="bindNot">element1</span>
<div bind-html="varName1">element2</div>
<a bind-html2="varName2">element3</a>
<div bind-html3="varName3">element4</div>
<span bindNot-html="bindNot">element5</span>
I have a big problem with quotes in java script and html dom.
I want to use just double quotes("), not ' at all!
Here is my code:
<a onclick="aClicked("<span onclick="spanClicked("You clicked me")">I'm an Span</span>")">Add span</a>
<script type="text/javascript">
function aClicked(str) {
$(document).append(str);
}
function spanClicked(str) {
alert(str);
}
</script>
Can anyone help throw kind of these problems!?
Tanks.
here is my original code (it work correctly but I just want to simplfy it and underestand it):
"I call this function with ajax"
<?php
function getTags() {
$values = ['test1', 'test2'];
$valuesString = '';
$baseSpanString = '<span><span class="tag">?</span><a onclick="Tags.Update($(this).parent().parent(), $(this).parent(), "tag");">x</a></span>';
foreach ($values as $tmpValue) {
if(trim($tmpValue) == '') {
continue;
}
$valuesString .= str_replace('?', $tmpValue, $baseSpanString);
}
$xhtml = '
<div>
<input type="text" onkeydown="return Tags.Insert($(this).parent(), $(this), event, \''.str_replace('"', '\\\'', $baseSpanString).'\', \'tag\');"/>
<textarea style="display:none;">'.implode('-', $values).'</textarea>
'.$valuesString.'
</div>
';
return $xhtml;
}
?>
<script type="text/javascript">
Tags = {};
Tags.Update = function(div, span, tagClass) {
div = $(div);
if(!div.length) {
alert('Error');
return false;
}
$(span).remove();
var tagsSpan = $('.'+tagClass, div);
var tagsString = [];
if(tagsSpan.length) {
$.each(tagsSpan, function(index, val) {
tagsString.push($(val).text());
});
}
$('textarea', div).text(tagsString.join('-'));
};
Tags.Insert = function(div, input, event, baseSpanString, tagClass) {
if (event.keyCode == 13)
{
div = $(div);
input = $(input);
if(!div.length || !input.length) {
alert('Error');
return false;
}
var val = input.val();
if(val && val != '') {
input.val('');
var spanString = baseSpanString.replace('?', val);
div.append(spanString);
}
var tagsSpan = $('.'+tagClass, div);
var tagsString = [];
if(tagsSpan.length) {
$.each(tagsSpan, function(index, val) {
tagsString.push($(val).text());
});
}
$('textarea', div).text(tagsString.join('-'));
return false;
}
};
</script>
Two answers:
Your string question
The right way instead
Your string question
' is the feature specifically designed for this. But sometimes this stuff does legitimately come up...
The key is to be aware of what kind of text you're dealing with at each stage:
Within the " of the attribute (onclick="..."), you're writing HTML text, even though what you're writing in that HTML text is JavaScript. So you can use " for quotes if you insist on not using '.
If you need to use a string within your JavaScript code (such as the onclick in the string we're passing aClicked) and insist on not using ', put a \ before the ".
If you need to use a quote within an HTML string within an HTML string (such as the string being passed to spanClicked, which is an HTML string inside a JavaScript string inside an HTML string), then you need something that will end up being " after the entities in the first HTML string are processed. So that's "
So:
<a onclick="aClicked("<span onclick=\"spanClicked("You clicked me")\">I'm an Span</span>")">Add span</a>
Example:
function aClicked(str) {
$(document.body).append(str);
}
function spanClicked(str) {
alert(str);
}
<a onclick="aClicked("<span onclick=\"spanClicked("You clicked me")\">I'm an Span</span>")">Add span</a>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
The right way instead
But again, this is all just a way to make your code complicated unmaintainable; instead, just use jQuery, as you're already using jQuery:
Example:
$("a").on("click", function() {
var span = $("<span>I'm a span</span>");
span.on("click", function() {
spanClicked("You clicked me");
});
$(document.body).append(span);
});
function spanClicked(str) {
alert(str);
}
<a>Add span</a>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
As you are using jQuery use unobtrusive event handlers, for this .on() method can be used. When generating elements dynamically you need to use Event Delegation.
I would also recommend you to use semantically correct elements, thus used <button> element
$("#addSpan").on("click", function() {
$('#container').append("<span class=\"myspan\">I'm an Span</span><br/>");
})
$("#container").on("click", ".myspan", function() {
console.log("You clicked me");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" id="addSpan">Add span</button>
<div id="container">
</div>
Better make it as a function like this
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a onclick="adds();">Add span</a>
<script type="text/javascript">
function adds(){
aClicked("<span onclick='spanClicked(\"You clicked me\")'>I'm an Span</span>");
}
function aClicked(str) {
$(document.body).append(str);
}
function spanClicked(str) {
alert(str);
}
</script>
I'm trying to create an upload form. It's working well so far and i'm trying to sort out a couple of bugs that I dislike.
The line that I seem to be having trouble with is
$(element).find(">:first-child").attr("value", "");
When cloning the form, it clones the div and replaces the value with nothing leaving a blank form, this works well, if I were to delete that line I would get the previous form's value, so it would be nice for a blank form to show.
The issue i'm having is when you delete a form all the forms values delete, What I want is when you delete a form, leave the value alone for the other forms.
Here's a fiddle http://jsfiddle.net/d77pd/1/ or see code below
HTML
<button class="clone">Add an Image</button>
<div id="upload_image_sets">
<div id="clonedInput1" class="clonedInput">
<input type="text" id="upload_image_link_1" class="image" size="36" name="hero_options[upload_image_link_1]" value="' . $hero_options['upload_image_link_1'] . '" />
<input id="show_upload_image_link_button_1" class="button upload_images" type="button" value="Upload Image" />
<button class="remove">Remove</button>
</div>
</div>
JavaScript
function updateClonedInput(index, element) {
$(element).appendTo("#upload_image_sets").attr("id", "clonedInput" + index);
$(element).find(">:first-child").attr("id", "cs_product_menu_img_src_" + index);
$(element).find(">:first-child").attr("name", "hero_options[upload_image_link_" + index + "]");
$(element).find(">:first-child").attr("value", "");
$(element).find(">:first-child").next().attr("id", "cs_product_menu_img_src_" + index + "_button");
displayRemove();
}
function displayRemove() {
if ($('.clonedInput').length === 1) {
$('.remove').hide();
} else {
$('.remove').show();
}
}
displayRemove();
$(document).on("click", ".clone", function (e) {
e.preventDefault();
var cloneIndex = $(".clonedInput").length + 1;
var new_Input = $(this).closest('.clonedInput').length ? $(this).closest('.clonedInput').clone() : $(".clonedInput:last").clone();
updateClonedInput(cloneIndex, new_Input);
});
$(document).on("click", ".remove", function (e) {
e.preventDefault();
$(this).parents(".clonedInput").remove();
$(".clonedInput").each(function (cloneIndex, clonedElement) {
updateClonedInput(cloneIndex + 1, clonedElement);
})
});
Clone the form a few times, if you delete any form apart form the 1st one with the content, you'll notice the first form's content deletes, I want this left alone.
First approach:
call $(element).find(">:first-child").attr("value", ""); after calling updateClonedInput(cloneIndex, new_Input); from add function.
Working Demo First approach:
Second Approach:
I have modified some code. pass one more bool argument in function updateClonedInput.which will be set true when added and set false when dom is removed.This will prevent the value getting replaced on remove function:
function updateClonedInput(index, element,param) {
$(element).appendTo("#upload_image_sets").attr("id", "clonedInput" + index);
$(element).find(">:first-child").attr("id", "cs_product_menu_img_src_" + index);
$(element).find(">:first-child").attr("name", "hero_options[upload_image_link_" + index + "]");
if(param)
$(element).find(">:first-child").attr("value", "");
$(element).find(">:first-child").next().attr("id", "cs_product_menu_img_src_" + index + "_button");
displayRemove();
}
function displayRemove() {
if($('.clonedInput').length === 1) {
$('.remove').hide();
} else {
$('.remove').show();
}
}
displayRemove();
$(document).on("click", ".clone", function(e){
e.preventDefault();
var cloneIndex = $(".clonedInput").length + 1;
var new_Input = $(this).closest('.clonedInput').length ? $(this).closest('.clonedInput').clone() : $(".clonedInput:last").clone();
updateClonedInput(cloneIndex, new_Input,true);
});
$(document).on("click", ".remove", function(e){
e.preventDefault();
$(this).parents(".clonedInput").remove();
$(".clonedInput").each( function (cloneIndex, clonedElement) {
updateClonedInput(cloneIndex + 1, clonedElement,false);
})
});
Working Demo Second Approach
An alternate solution that creates a blank clone from the first element once, then uses this every time a new row is required. It also uses CSS to hide/show the Remove button based on the fact that you only need Remove buttons on all rows unless it's the only child.
Disclaimer: I have removed the id manipulation as I am unsure if you really need it. I can update if necessary.
Demo
HTML
<button class="clone">Add an Image</button>
<div id="upload_image_sets">
<div class="clonedInput">
<input type="text" class="image" size="36" name="hero_options[upload_image_link_1]" value="an initial value" />
<input class="button upload_images" type="button" value="Upload Image" />
<button class="remove">Remove</button>
</div>
</div>
CSS
.clonedInput .remove {
display:inline-block;
}
.clonedInput:only-child .remove {
display:none;
}
JavaScript
function resetForm($form) {
$form.find('input:text, input:password, input:file, select, textarea').val('');
$form.find('input:radio, input:checkbox').removeAttr('checked').removeAttr('selected');
}
var $blankClone = $('.clonedInput').clone();
resetForm($blankClone);
$(document).on('click', '.clone', function(e) {
e.preventDefault();
$blankClone.clone().appendTo('#upload_image_sets');
});
$('#upload_image_sets').on('click', '.remove', function(e) {
e.preventDefault();
$(this).closest('.clonedInput').remove();
});
resetForm() borrowed from Resetting a multi-stage form with jQuery
I'm working on something really simple, a short quiz, and I am trying to make the items I have listed in a 2-d array each display as a <li>. I tried using the JS array.join() method but it didn't really do what I wanted. I'd like to place them into a list, and then add a radio button for each one.
I have taken the tiny little leap to Jquery, so alot of this is my unfamiliarity with the "syntax". I skimmed over something on their API, $.each...? I'm sure this works like the for statement, I just can't get it to work without crashing everything I've got.
Here's the HTML pretty interesting stuff.
<div id="main_">
<div class="facts_div">
<ul>
</ul>
</div>
<form>
<input id="x" type="button" class="myBtn" value="Press Me">
</form>
</div>
And, here is some extremely complex code. Hold on to your hats...
$(document).ready (function () {
var array = [["Fee","Fi","Fo"],
["La","Dee","Da"]];
var q = ["<li>Fee-ing?","La-ing?</li>"];
var counter = 0;
$('.myBtn').on('click', function () {
$('#main_ .facts_div').text(q[counter]);
$('.facts_div ul').append('<input type= "radio">'
+ array[counter]);
counter++;
if (counter > q.length) {
$('#main_ .facts_div').text('You are done with the quiz.');
$('.myBtn').hide();
}
});
});
Try
<div id="main_">
<div class="facts_div"> <span class="question"></span>
<ul></ul>
</div>
<form>
<input id="x" type="button" class="myBtn" value="Press Me" />
</form>
</div>
and
jQuery(function ($) {
//
var array = [
["Fee", "Fi", "Fo"],
["La", "Dee", "Da"]
];
var q = ["Fee-ing?", "La-ing?"];
var counter = 0;
//cache all the possible values since they are requested multiple times
var $facts = $('#main_ .facts_div'),
$question = $facts.find('.question'),
$ul = $facts.find('ul'),
$btn = $('.myBtn');
$btn.on('click', function () {
//display the question details only of it is available
if (counter < q.length) {
$question.text(q[counter]);
//create a single string containing all the anwers for the given question - look at the documentation for jQuery.map for details
var ansstring = $.map(array[counter], function (value) {
return '<li><input type="radio" name="ans"/>' + value + '</li>'
}).join('');
$ul.html(ansstring);
counter++;
} else {
$facts.text('You are done with the quiz.');
$(this).hide();
}
});
//
});
Demo: Fiddle
You can use $.each to iterate over array[counter] and create li elements for your options:
var list = $('.facts_div ul');
$.each(array[counter], function() {
$('<li></li>').html('<input type="radio" /> ' + this).appendTo(list);
}
The first parameter is your array and the second one is an anonymous function to do your action, in which this will hold the current element value.
Also, if you do this:
$('#main_ .facts_div').text(q[counter]);
You will be replacing the contents of your element with q[counter], losing your ul tag inside it. In this case, you could use the prepend method instead of text to add this text to the start of your tag, or create a new element just for holding this piece of text.
I'm looking to expand on a recent script i've coded using jquery.
I have this following code
<script type='text/javascript'>
added_departments = new Array();
$("#departments_submit").click(function(){
var depo = $("#depo_list").val();
if(jQuery.inArray(depo, added_departments) != -1)
{
return false;
}
else
{
added_departments.push(depo);
$("#depo_added_list").append("<li>" + depo + "<a href='#' title='"+ depo +"' class='remove_depo'> [X] </a></li>");
var current_value = $("#departments").val();
if(current_value)
{
$("#departments").val(current_value + "," + depo);
}
else
{
$("#departments").val(depo);
}
return false;
}
});
</script>
The above code takes information selected in a select drop down box, adds it to a div to display publicly and also into a hidden form field that processes the data.
i've tried to create now something that will reverse this effect and remove certain selections from the div and the field. which is where i have this code
<script type='text/javascript'>
$(".remove_depo").click(function(){
var removing = $(this).title();
var current_val = $("#deparments").val();
if(current_val == removing) {
$("departments").replace(removing, "");
}
else {
$("departments").replace("," + removing, "");
}
});
</script>
It doesn't cause any errors, but it doesn't do anything either? So I'm really stuck. Any ideas?
EDIT: Updated code
$(".remove_depo").click(function(){
var removing = $(this).attr('title');
var current_val = $("#deparments").val();
if(current_val == removing) {
$("#departments").replace(removing, "");
}
else {
$("#departments").replace("," + removing, "");
}
});
Here is the html
<form method="post" action="javascript:void(0);">Select Departments To Be Added:
<div class="depo_adder">
<select id="depo_list"><option value="">--- INDIVIDUAL TAGS ---</option><option value="blah">blah</option></select>
<button id="departments_submit">Go!</button>
</div></form><form method="post" action="briefings/addbriefing.php">
<div class="form">
<strong>Departments: </strong>
<ul id="depo_added_list"><li>blah [X] </li></ul>
<input name="departments" id="departments" value="blah" type="hidden">
</div>
you're referring to $('departments') - this won't work. You need to specify either an identifierm eg $('#departments') or a class, eg $('.departments)
ah - other answer is also correct, .title() is not a function. You want
$('#foo').attr('title') to get the title.