Special HTML characters injected with JS - javascript

I have a button (named Benjamin):
<input type="submit" name="btn_submit" value="Next →" />
And on a click event it says 'Loading' and does cool stuff. However, if there is a problem, I want it to change back to its original text while displaying the error message elsewhere.
$('input[name=btn_submit]').click(function() {
$(this).val('Loading');
// Logicy Stuff...
// Error?
$(this).val('Next →');
return false;
});
Somehow, the literal text → is applied to the button, rather than the cool →. How do I fix this?

Html is evaluated with different rules that JavaScript is. Html entities only parsed by the html parser. Either use the unicode literal, like so:
$(this).val('Next \u2192');
Or better, keep track of the original value and then set it back:
var initalButtonValue = $(this).val();
$(this).val('Loading');
// Stuff
$(this).val(initialButtonValue);
Or perhaps even better, use HTML data attributes to store the states.
<input type="submit" name="btn_submit" value="Next →" data-normal-value='Next →' data-loading-value='Loading...' />
Then:
// Set to loading
$(this).val($(this).data("loading-value"));
// and back to normal
$(this).val($(this).data("normal-value"));

Put the actual → character in there instead of a HTML entity. Using an entity only works if you set HTML content - and form values are not HTML at all.
When using it inside <input value="..."> it only works because in this case the entity is replaced while the HTML is parsed, so the value gets the actual character.

How about storing the value of the element with $.data() and retrieving it later:
$('input[name=btn_submit]').click(function() {
$.data(this, 'value', this.value);
$(this).val('Loading');
// Logicy Stuff...
// Error?
$(this).val($.data(this, 'value'));
return false;
});
Here is a demo: http://jsfiddle.net/39thm/ (the setTimeout is just for demonstration)
Docs for $.data(): http://api.jquery.com/jquery.data
Also you are using thr $(this) selector more than once, if you use it a bunch then it's a good idea to cache the selection:
$('input[name=btn_submit]').click(function() {
var $this = $(this);
$.data(this, 'value', this.value);
$this.val('Loading');
// Logicy Stuff...
// Error?
$this.val($.data(this, 'value'));
return false;
});

if you know the code for the character, you can add it to a JavaScript string with .fromCharCode():
var s = "hello " + String.fromCharCode(1023); // just a made-up number
You can also embed characters in JavaScript strings if you know their hex code:
var s = "string \u1023 string";

$("input[name='btn_submit']").click(function() {
var elem = $(this);
elem.data( "orgText", elem.val() ).val('Loading');
window.setTimeout(
function(){
elem.val( elem.data("orgText") );
}, 1000 );
return false;
});​
jsFiddle

Related

Replacing widget element with a newly constructed DOM structure

<script>
(function( $ ) {
$.widget( "my.dropbox", {
errorText: function(text) {
$(this.element).next().html(text);
},
_create: function() {
var id = $(this.element).attr("id");
var customDropbox = $(
"<div class='form-group'>"+
"<label for='"+id+"'>"+getLabelFor(id)+"</label>"+
"<select id='"+id+"'></select>"+
"<div class='errors'></div>"+
"</div>"
);
customDropbox.attr("id", id);
$(this.element).replaceWith(customDropbox); // This removes original element from DOM
populateOptions(id);
},
});
}( jQuery ));
$(document).ready(function(){
$("#field1").dropbox(); //blank input field turns into a select with a label, populated options e.t.c..
$("#button1").on("click", function(){
$("#field1").dropbox("errorText", "This is a validation error message"); //throws an error saying dropbox is not initialized
});
});
</script>
<html>
<body>
<input id="field1" />
<button id="button1">Press me</button>
</body>
</html>
So I want a widget with public methods that will replace the original element with all the widget data associated with it. The problem with the above code is that the <select..> element is just a DOM element and if you call .dropbox(..) on it, it will say the widget is not initialized. Is there a way to make the select element into the widget object with the .errorText() method? All widget examples online add stuff around the original element but never replace it. As for the bigger picture, I'm trying to make a generic tool to configure forms dynamically. It's going to be all <input id="..."> in html but then javascript will query a database, get configuration for the field and turn it into a dropbox, checkbox or, say, a date picker with all the labels, validation, and other bells and whistles.
There is more than one issue with your widget code. I'll try to summarize them:
1. Copy the data
You're not copying the data to the newly created customDropbox, so before
this.element.replaceWith(customDropbox);
you should copy the data:
customDropbox.data(this.element.data());
Now the widget will remember that it was initialized.
2. this.element is gone
After
this.element.replaceWith(customDropbox);
you should update this.element so that it points to the newly created customDropbox:
this.element = customDropbox;
3. errorText message takes wrong element
Since the widgets element (this.element) is now pointing to the <div class='form-group'></div> element, the errorText function must be slightly modified to:
this.element.find(".errors").html(text);
4. id should be unique
Now, both the wrapper <div> and the <select> have the same id, which is not allowed in HTML so remove the one on the <select> tag. Luckily, <label> can work without the for attribute, just write it like this:
<label>labelForId <select></select></label>
Then to get the <select>-element, use this.element.find("select") in the widget.
Side note
`this.element` is already a jQuery element, so no need for the additional `$()` wrapping.
See this jsFiddle
function show(){
$("#field1").input({....});
}
function hide(){
$("#field1").input("hide");
}
<button onclick="show()">show</button>
<button onclick="hide()">hide</button>
i think to replace the origin element which initial dropbox() is not a good solution,
because this will force you to rely on the implemention details of jQuery ui factory,
it is easy to make a mistake or introduce bugs, sometimes harder for other people to understand your code
if jquery ui factory change the implemention in the future, you have to modify all your code to make it work
(sorry for my limit understand of jquery ui)
i think we can put the <input/> into a container and initial dropbox() on the container which inturn
replace <input/> with <select> datepicker ..etc.. we can build modules easily by doing so:
<form>
<div class="dropbox"><label for="someID">aaaaaa</label><input id="someID"/></div>
<div class="datepicker"></div>
<div class="othermodule"></div>
</form>
js:
$(".dropbox").dropbox(); // init dropbox you defined
$(".datepicker").datepicker(); // ...
$(".othermodule").othermodule(); // ...
$(".dropbox").dropbox("errorText", "error"); // invoke it smoothly
here is a simple demo: http://jsfiddle.net/m4A3D/
#Wouter Huysentruit's answer provides a list of good suggestion for me
<form>
<div class="dropbox">
<label for="someID">aaaaaa</label>
<input id="someID"/>
</div>
<div class="datepicker"></div>
<div class="othermodule"></div>
</form>
<button id="button1">Press me</button>
<script>
(function ($){
$.widget("my.dropbox", {
_create: function () {
var $input = this.element.find("input");
var sID = $input.attr("id");
var $select = $("<select>");
$select.attr("id", sID);
$input.replaceWith($select);
this.element.append("<div class='errors'></div>");
}, // end _create()
errorText: function (text) {
this.element.find(".errors").text(text);
} // end errorText()
});
}(jQuery));
$(".dropbox").dropbox();
$("#button1").click(function () {
$(".dropbox").dropbox("errorText", "this is error");
});
</script>

Optimizing code to define variables only once, code only works when the vars are in change function and for the code outside change I redefine?

Pretty sure I know the solution... would write .on('change','load', function(){}
correct? <-- Tested didn't work? so I am up to your solutions :)
Sushanth -- && adeneo both came up with great solutions, this is a good lesson in optimizing code... It's gonna be hard to choose which answer to go with, but I know this is going to help me rethink how I write... I dont know what I do without this forum, id have to learn this stuff in college.
This is purely a question out of curiosity and bettering my skills, as well as giving you guys a chance to display your knowledge on jQuery. Also to prevent any sloppy writing.
I have a radio based switch box, the markup looks like this, the id's and on/off values are generated by the values in my array with PHP...
<span class="toggle-bg">//This color is the background of the toggle, I need jQuery to change this color based on the state on/off
<input type="radio" value="on" id="_moon_page_header_area1" name="_moon_page_header_area">//this is my on value generated by the array
<input type="hidden" value="_moon_page_header_area" class="switch-id-value">// I create this input because I have multiple checkboxes that have the ID _moon_ARRAYVALUE_area1
<input type="radio" value="off" id="_moon_page_header_area2" name="_moon_page_header_area">// off value
<input type="hidden" value="_moon_page_header_area" class="switch-id-value">//_moon_ARRAYVALUE_area2
<span class="switch"></span>// the switch button that changes
</span>
Hope that makes sense and the comments are clear
Here is the jQuery
var value = $('.toggle-bg input.switch-id-value').val()
var moon1 = $('#'+value+'1').is(':checked');
var moon2 = $('#'+value+'2').is(':checked');
var static_slide = $('._moon_staticarea_height');
var toggle = $('.toggle-bg');
if(moon1){
toggle.css({'background-color': '#46b692'});
static_slide.hide()
} else
if (moon2){
toggle.css({'background-color': '#333'});
static_slide.show()
}
$('.toggle-bg').change(function () {
var value = $('.toggle-bg input.switch-id-value').val()
var moon1 = $('#'+value+'1').is(':checked');
var moon2 = $('#'+value+'2').is(':checked');
var static_slide = $('._moon_staticarea_height');
var toggle = $('.toggle-bg');
if(moon1){
toggle.css({'background-color': '#46b692'});
static_slide.slideUp()
} else
if (moon2){
toggle.css({'background-color': '#333'});
static_slide.slideDown()
}
});
it looks longer than it really is, its just repeating it self, one is on load so that it gives the correct color on load of the page, and then inside the change function we need to change colors..
How do I write it so I only have to use variables one time (so its cleaner) is there a better way to optimize it... Just NOW thinking after writing this I could put it in one function .on('load', 'change', function() {}
I just now thought of that, but I wrote all this so I am going to see what others think...
You'd do that by having the function in the change event handler, and on the end you chain on a trigger('change') to make it work on pageload :
$('.toggle-bg').on('change', function () {
var value = $('.toggle-bg input.switch-id-value').val(),
moon1 = $('#' + value + '1').is(':checked'),
slider = $('._moon_staticarea_height'),
toggle = $('.toggle-bg');
toggle.css('background-color', (moon1 ? '#46b692' : '#333'));
slider[moon1?'slideUp':'slideDown']();
}).trigger('change');
As radiobuttons can't be unchecked, it's either moon1 or moon2, which means checking one of them should be enough.
.on('change','load',
supposed to be
// Remove the comma separator if you want to bind the same handler to
// multiple events.
.on('change load',
And you can remove the one separately written out and enclose it in a function (if multiple instances of the class toggle-bg)
or just trigger the change event.(If there is a single instance of a class)
This will just run the same functionality when the page loads.
var toggle = $('.toggle-bg');
toggle.change(function () {
var value = $('input.switch-id-value', this).val(),
moon1 = $('#' + value + '1').is(':checked'),
moon2 = $('#' + value + '2').is(':checked'),
static_slide = $('._moon_staticarea_height');
if (moon1) {
toggle.css({
'background-color': '#46b692'
});
static_slide.slideUp()
} else if (moon2) {
toggle.css({
'background-color': '#333'
});
static_slide.slideDown()
}
}).change();

How to set outerHTML with jQuery

I have a UserControl. Ex:
<div id="divItem">
some html
</div>
The ajax request return new html of this UC from server. Ex:
<div id="divItem">
new html
</div>
I want to replace the old html by the new one. How could I do that. Thanks.
If you also return the div divItem
$("#divItem").replaceWith("NEW HTML");
Put the new HTML on the spot or replace the innerHTML, since they got the same container:
$("#divItem").html($("NEW HTML").html());
If you dont return the div divItem
Just put the new html:
$("#divItem").html("NEW HTML");
I guess replaceWith is what you search.
$('#divItem').replaceWith(serverResponse);
Placing data from AJAX calls into a DOM element can be done using .load().
$('#divItem').load('somePage.html');
If you want to replace 1 item with multiple items. You can try:
var item_1 = $('<div>').text('item 1');
var item_2 = $('<div>').text('item 2');
var item_3 = $('<div>').text('item 3');
// 1/.
// dont' use this way because it's hard to read
$('#divItem').prop('outerHTML', item_1.prop('outerHTML') + item_2.prop('outerHTML') + item_3.prop('outerHTML'));
// 2/.
// dont' use this way because it's same to the first's
$('#divItem')[0].outerHTML = item_1.prop('outerHTML') + item_2.prop('outerHTML') + item_3.prop('outerHTML');
// 3/.
// if you use this way, how can we continue replace "#divItem" with "item_2"?
var obj = $('#divItem').replaceWith(item_1);
// "replaceWith" returns an object which was replaced with "item_1"
// there is no way to continue with "item_2" and "item_3"
// sure, if you DON'T want to write a new line
item_1.after(item_2);
// or
item_2.insertAfter(item_1);
// 4/.
// if we write this, the result should be: "item 3item 2item 1"
$('#divItem').after(item_1).after(item_2).after(item_3);
// so, the correct **inline** solution should be:
$('#divItem').after(item_3).after(item_2).after(item_1).remove();
You just need
$('#divItem').html('new html');
This just replaces the div's innerHTML: http://api.jquery.com/html/

how to get outerHTML with jquery in order to have it cross-browser

I found a response in a jquery forum and they made a function to do this but the result is not the same.
Here is an example that I created for an image button:
var buttonField = $('<input type="image" />');
buttonField.attr('id', 'butonFshi' + lastsel);
buttonField.val('Fshi');
buttonField.attr('src', 'images/square-icon.png');
if (disabled)
buttonField.attr("disabled", "disabled");
buttonField.val('Fshi');
if (onblur !== undefined)
buttonField.focusout(function () { onblur(); });
buttonField.mouseover(function () { ndryshoImazhin(1, lastsel.toString()); });
buttonField.mouseout(function () { ndryshoImazhin(0, lastsel.toString()); });
buttonField.click(function () { fshiClicked(lastsel.toString()); });
And I have this situation:
buttonField[0].outerHTML = `<INPUT id=butonFshi1 value=Fshi src="images/square-icon.png" type=image jQuery15205073038169030395="44">`
instead the outer function I found gives buttonField.outer() = <INPUT id=butonFshi1 value=Fshi src="images/square-icon.png" type=image>
The function is:
$.fn.outer = function(val){
if(val){
$(val).insertBefore(this);
$(this).remove();
}
else{ return $("<div>").append($(this).clone()).html(); }
}
so like this I loose the handlers that I inserted.
Is there anyway to get the outerHTML with jquery in order to have it cross-browser without loosing the handlers ?!
You don't need convert it to text first (which is what disconnects it from the handlers, only DOM nodes and other specific JavaScript objects can have events). Just insert the newly created/modified node directly, e.g.
$('#old-button').after(buttonField).remove();`
after returns the previous jQuery collection so the remove gets rid of the existing element, not the new one.
Try this one:
var html_text = `<INPUT id=butonFshi1 value=Fshi src="images/square-icon.png" type=image jQuery15205073038169030395="44">`
buttonField[0].html(html_text);
:)
Check out the jQuery plugin from https://github.com/darlesson/jquery-outerhtml. With this jQuery plugin you can get the outerHTML from the first matched element, replace a set of elements and manipulate the result in a callback function.
Consider the following HTML:
<span>My example</span>
Consider the following call:
var span = $("span").outerHTML();
The variable span is equal <span>My example</span>.
In the link above you can find more example in how to use .outerHTML() plug-in.
This should work fine:
var outer = buttonField.parent().html();

jquery return value of input to var

I'm trying to make a variable equal the value of the text box. I have the text box value being set to a variable and returned as an alert (for now) but I can't figure out how to call that variable from other functions.
$('#max_char').keyup(function () {
var max_char = $(this).val();
alert(max_char + ' Handler for .keyup() called.');
});
var count_options = {
'maxCharacterSize': max_char,
'originalStyle': 'originalDisplayInfo',
'warningStyle': 'warningDisplayInfo',
'warningNumber': 40,
'displayFormat': '#input Characters | #left Characters Left | #words Words'
};
$('#textinput').textareaCount(count_options);
});
HTML
<textarea cols="68" rows="21" name="textinput" id="textinput"></textarea><br/>
<input type="textbox" id="max_char" name="max_char" value="-1" /> Max Characters <br/>
Any help would be great. Trying to add the var max_char to the maxCharacterSize of count_options
All you need to do is declare max_char in a higher scope, i.e. outside of the keyup function:
var max_char;
$('#max_char').keyup(function () {
max_char = +$(this).val();
alert(max_char + ' Handler for .keyup() called.');
});
Also note that I put a + in front of $(this).val() to convert it from a string into a number, since "1" + 1 == "11".
Update:
The reason the textareaCount plugin isn't working is because it is initialised once, on document ready. At this time, max_char is nothing because the user hasn't typed anything yet.
You'd have to either reconfigure or re-initialise the plugin on every keyup to get the effect you're after. Unfortunately the plugin doesn't document an easy way to do this. After digging through the plugin's source code, I think there are only 3 events it binds that you need to revert, before you can simply re-initialize it again. Try this out:
var count_options = {
'maxCharacterSize': 100, // Just some default value
'originalStyle': 'originalDisplayInfo',
'warningStyle': 'warningDisplayInfo',
'warningNumber': 40,
'displayFormat': '#input Characters | #left Characters Left | #words Words'
};
// Initialise the plugin on document ready
$('#textinput').textareaCount(count_options);
$('#max_char').keyup(function () {
var max_char = +$(this).val();
count_options.maxCharacterSize = max_char;
// Unbind the 3 events the plugin uses before initialising it
$('#textinput')
.next('.charleft').remove().end()
.unbind('keyup').unbind('mouseover').unbind('paste')
.textareaCount(count_options);
});
If I understand you correctly, if you declare the var within the global scope of javascript
Or if you directly access the input with
$("#max_char").val()
parseInt($('#max_char').val())

Categories

Resources