jQuery .val() not returning what is expected - javascript

I am trying to implement the following code snippet into my project: http://jsfiddle.net/Zmf6t/. But I am running into a bit of difficulty; I have wrapped the JavaScript in the jQuery(document).ready() callback function, and checking it in the Chrome debugger shows that the script is running. However, when I get to the if( jQuery(this).val() == "-1" ) (as my <select> value has -1 as its value), the debugger reports that the elements value property is "-1", but the statement within the if is never evaluated. Instead the else property is evaluated.
Does anyone have any idea why this might be happening? I cannot seem to isolate the issue to provide a minimal working example; my jQuery is as below:
jQuery(document).ready( function() {
jQuery('#test').change( function() {
if( jQuery(this).val() == "-1" )
{
jQuery(this).addClass( "empty-combo" );
}
else
{
jQuery(this).removeClass( "empty-combo" );
}
});
jQuery('#test').change();
});

Change your condition to:
if( jQuery(this).val() == null )
It worked.

Related

CkEditor - Uncaught TypeError: Cannot read property 'getSelection' of undefined

I am implementing the CKEditor in my app. When I am trying to instantiate CKEditor to the textarea I am getting following error
Cannot read property 'getSelection' of undefined
at below line of ckeditor
getNative: function() {
return void 0 !== this._.cache.nativeSel ? this._.cache.nativeSel : this._.cache.nativeSel = B ? this.document.$.selection : this.document.getWindow().$.getSelection() }
Any help is much appreciated.
I have a list of articles.
every time I clicked on any article a "dialog / modal" should be open.
in such dialog or modal there was a ckeditor element for the content of my article.
when I clicked on the first it worked like a charm.
the problem was after clicking on the 2nd, 3rd, 4th etc.
Then I started to have this error.
TypeError: Cannot read property 'getSelection' of undefined
at CKEDITOR.dom.selection.getNative (ckeditor.js:448)
at new CKEDITOR.dom.selection (ckeditor.js:446)
at a.CKEDITOR.editor.getSelection (ckeditor.js:443)
at new CKEDITOR.plugins.undo.Image (ckeditor.js:1182)
at CKEDITOR.plugins.undo.UndoManager.save (ckeditor.js:1177)
at a.<anonymous> (ckeditor.js:1173)
at a.n (ckeditor.js:10)
at a.CKEDITOR.event.CKEDITOR.event.fire (ckeditor.js:12)
at a.CKEDITOR.editor.CKEDITOR.editor.fire (ckeditor.js:13)
at a.setData (ckeditor.js:275)
The solution for me was easy, tell the computer to destroy the ckeditor instance when the dialog / modal is closed. easy!..
Now is working like a charm =)
$mdDialog.show({
parent: parentEl,
targetEvent: $event,
templateUrl: '/md-templates/blog-article.html',
controller: DialogController,
scope: $scope,
preserveScope: true,
onRemoving: function (event, removePromise) {
if (CKEDITOR.instances.body) CKEDITOR.instances.body.destroy();
}
});
I got same error, and I solved by initialize CKEditor, in
$(document).function(ready());
$(document).ready(function () {
CKEDITOR.replace('editor1', {
language: 'tr',
height: '300'
});
});
I think when you initialize before page load, it doesn't find dom element(textarea)
This is likely your application is attempting to access and set the data of the CKEditor before the editor is ready. This can be the result of a race condition, causing the error to be intermittent. There are a few things you can do to prevent this issue.
First, the CKEditor endorsed method of testing if the editor is loaded first.
if ( CKEDITOR.status == 'loaded' ) {
// The API can now be fully used.
doSomething();
} else {
// Wait for the full core to be loaded and fire its loading.
CKEDITOR.on( 'load', doSomething );
CKEDITOR.loadFullCore && CKEDITOR.loadFullCore();
}
Second, if you are unable to control the timing associated with setting of the editor value, you could wrap the CKEDITOR.dom.window object in an async/await Promise that tests if the editor is loaded first, and if not, listens for the editor to load, and then complete setting the value. (note, this code is not fully tested)
CKEDITOR.dom.window = (function(window) {
if ( CKEDITOR.status == 'loaded' ) {
// The API can now be fully used.
return window;
} else {
return (async function() {
return await function() {
return new Promise(resolve => {
CKEDITOR.on( 'load', () => {
resolve(window);
});
});
};
})();
CKEDITOR.loadFullCore && CKEDITOR.loadFullCore();
}
})(CKEDITOR.dom.window);
You can have a try
CKEditor.destroy();
change the function f.$.onload inside ckeditor.js to the below
f.$.onload=function(){var toutMs =5000;
if(CKEDITOR.document.getHead().$.childElementCount > 6)
{
toutMs=0;
}
setTimeout(function(){
A(b,!0)
},toutMs)
}

JQuery/Backbone remove not working in Jasmine

I'm testing a Backbone View in Jasmine. When I call the view's remove method, the element isn't actually removed.
I have this event handler in my view:
onModelChange: function() {
this.$el.html('');
this.render();
}
I have to have it written that way because manually setting the html is the only way to remove it. Calling remove doesn't do anything, and when the view renders itself again it just renders the new content appended to the old content. I even tried calling remove from the developer tools in Chromium but that didn't work either. However, remove does work when I manually test it in the browser, but it doesn't work in Jasmine and it's screwing up my tests.
I think the answer to the problem lies in the jQuery source:
remove: function( selector, keepData /* Internal Use Only */ ) {
var elem,
elems = selector ? jQuery.filter( selector, this ) : this,
i = 0;
for ( ; (elem = elems[i]) != null; i++ ) {
if ( !keepData && elem.nodeType === 1 ) {
jQuery.cleanData( getAll( elem ) );
}
if ( elem.parentNode ) {
if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
setGlobalEval( getAll( elem, "script" ) );
}
elem.parentNode.removeChild( elem ); // right here to be specific
}
}
return this;
},
The remove function is relying on the node's parent to do the removing. I'm guessing that when the tests run in karma, the backbone view's node has no parent. To explore a bit more, I debugged the test. In the console, if I query for a view element's child and I remove it, it works.

Select from json on click

I'm trying to select a row from a json array using jquery. This is what i have:
$(document).ready(function() {
$.getJSON( "js/collectie.json", function(data) {
jsoncollectie = data;
})
$( "#collectie li" ).click(function(){
var thumb_id = $(this).data("id");
for(var i = 0; i < jsoncollectie.stoelen.length; i++){
if(jsoncollectie.stoelen[i].ref == thumb_id){
$("#detailimage").attr('src', jsoncollectie.stoelen[i].image);
$("#detailimage").attr('title', jsoncollectie.stoelen[i].title);
$("#title").html('<h4> '+jsoncollectie.stoelen[i].naam+' </h4>');
$("#secondaryimage").attr('src', jsoncollectie.stoelen[i].secondaryimage);
$("#secondaryimage").attr('title', jsoncollectie.stoelen[i].secondarytitle);
$("#description").html('<p> '+jsoncollectie.stoelen[i].description+' </p>');
}
}
});
});
Now when i click on a list item (#collectie li) the console outputs "ReferenceError: jsoncollectie is not defined". I don't know why it's doing that and i'm pretty sure it worked two weeks ago. Don't know much about javascript/jquery yet, but i'm slowly learning.
$(document).ready(function()
{
// Provide access to data outside of the getJSON call
var m_oJsonCollectie = null;
// Get the data
$.getJSON( "js/collectie.json", function(data)
{
// Set the data
m_oJsonCollectie = data;
// Apply the click handler
$( "#collectie li" ).click(function()
{
var thumb_id = $(this).data("id");
for(var i = 0; i < m_oJsonCollectie.stoelen.length; i += 1)
{
if(m_oJsonCollectie.stoelen[i].ref == thumb_id)
{
$("#detailimage") .attr('src', m_oJsonCollectie.stoelen[i].image);
$("#detailimage") .attr('title', m_oJsonCollectie.stoelen[i].title);
$("#title") .html('<h4> '+ m_oJsonCollectie.stoelen[i].naam+' </h4>');
$("#secondaryimage").attr('src', m_oJsonCollectie.stoelen[i].secondaryimage);
$("#secondaryimage").attr('title', m_oJsonCollectie.stoelen[i].secondarytitle);
$("#description") .html('<p> '+ m_oJsonCollectie.stoelen[i].description+' </p>');
}
}
});
});
});
JS have block level scope, so you wont get the values outside of the function unless you provide access to them or they are declared in global scope (which is considered bad practice).
This pattern should help you keep your data accessible, and only applies the click handler if the getJSON call is successful.
Check that your getJSON request is being received and returned by using deferred methods
// Syntax that will shed light to your issue :
$.getJSON
(
"js/collectie.json",
function (oJSON) { /*success*/ }
)
.done(function() { /* succeeded */ })
.fail(function() { /* failed */ })
.always(function() { /* ended */ });
I came to this conclusion due to comments and the fact that a variable only declared in the success handler for getJSON was undefined. Since the JSON containing variable was undefined, the success handler must never have been called. Chances are that the path to the JSON you are trying to get is incorrect.
Documentation for the methods to accomplish :
getJSON
done
fail
always
UPDATE
Knowing that the response is 304, and the results are undefined are the important details here. This issue has been addressed by jQuery already here
This is actually correct, given the ifModified header has not been set to false.
To fix this issue, use ajaxSetup() to modify the header.
NOTE : the use of this method is not recommended by jQuery, but in this case it works.
// place this is document ready handler before making any calls.
$.ajaxSetup({ ifModified : false });

Jquery ChangeEvent global variable

i have this code.
var anyChange = false;
function init(){
$('.saveSettingsEvent').bind("change",function(){
anyChange = true ;
}
);
}
...
onload='init()
The event is fired , but the variable (anyChange ) remains 'true' , only inside anonymous function .
I use :
Jquery 1.8.2
JqueryMobile 1.2
where I'm wrong ?
Thnx !
I wrote an example for you.
var anyChange = false;
$(function() {
$('.saveSettingsEvent').bind('change',function(){
anyChange = true ;
});
$('button').click(function() {
alert(anyChange);
});
});
http://jsfiddle.net/YuUVd/2/
It works as expected. anyChange is set to true and stays true.
So, if you need more help, we need more information.
I assume, that some other code sets your variable back to false or your change event is never triggered...
Real Solution
( Pending )
Workaround
I make a custom Tag with custom attribute at the end of the Body.
When the event is triggered , sets True the attribute res
$(function() {
$('.saveSettingsEvent').bind('change',function(){
$("#anychange").attr('res','true');
});
});
if
var resToSave = $("#anychange").attr('res');
if(resToSave == 'true'){
// Do Something
...
// Reset attr
$("#anychange").attr('res','false');
}

Get text from field on keyup, but with delay for further typing

I have a form which is submitted remotely when the various elements change. On a search field in particular I'm using a keyup to detect when the text in the field changes. The problem with this is that when someone types "chicken" then the form is submitted seven times, with only the last one counting.
What would be better is something like this
keyup detected - start waiting (for one second)
another keyup detected - restart waiting time
waiting finishes - get value and submit form
before I go off and code my own version of this (I'm really a backend guy with only a little js, I use jQuery for everything), is there already an existing solution to this? It seems like it would be a common requirement. A jQuery plugin maybe? If not, what's the simplest and best way to code this?
UPDATE - current code added for Dan (below)
Dan - this may be relevant. One of the jQuery plugins I'm using on the page (tablesorter) requires this file - "tablesorter/jquery-latest.js", which, if included, leads to the same error with your code as before:
jQuery("input#search").data("timeout", null) is undefined
http‍://192.168.0.234/javascripts/main.js?1264084467
Line 11
Maybe there's some sort of conflict between different jQuery definitions? (or something)
$(document).ready(function() {
//initiate the shadowbox player
// Shadowbox.init({
// players: ['html', 'iframe']
// });
});
jQuery(function(){
jQuery('input#search')
.data('timeout', null)
.keyup(function(){
jQuery(this).data('timeout', setTimeout(function(){
var mytext = jQuery('input#search').val();
submitQuizForm();
jQuery('input#search').next().html(mytext);
}, 2000)
)
.keydown(function(){
clearTimeout(jQuery(this).data('timeout'));
});
});
});
function submitQuizForm(){
form = jQuery("#searchQuizzes");
jQuery.ajax({
async:true,
data:jQuery.param(form.serializeArray()),
dataType:'script',
type:'get',
url:'/millionaire/millionaire_quizzes',
success: function(msg){
// $("#chooseQuizMainTable").trigger("update");
}
});
return true;
}
Sorry i haven't tested this and it's a bit off the top of my head, but something along these lines should hopefully do the trick. Change the 2000 to however many milliseconds you need between server posts
<input type="text" id="mytextbox" style="border: 1px solid" />
<span></span>
<script language="javascript" type="text/javascript">
jQuery(function(){
jQuery('#mytextbox')
.data('timeout', null)
.keyup(function(){
clearTimeout(jQuery(this).data('timeout'));
jQuery(this).data('timeout', setTimeout(submitQuizForm, 2000));
});
});
</script>
Here's your fancy jquery extension:
(function($){
$.widget("ui.onDelayedKeyup", {
_init : function() {
var self = this;
$(this.element).keyup(function() {
if(typeof(window['inputTimeout']) != "undefined"){
window.clearTimeout(inputTimeout);
}
var handler = self.options.handler;
window['inputTimeout'] = window.setTimeout(function() {
handler.call(self.element) }, self.options.delay);
});
},
options: {
handler: $.noop(),
delay: 500
}
});
})(jQuery);
Use it like so:
$("input.filterField").onDelayedKeyup({
handler: function() {
if ($.trim($(this).val()).length > 0) {
//reload my data store using the filter string.
}
}
});
Does a half-second delay by default.
As an update, i ended up with this which seems to work well:
function afterDelayedKeyup(selector, action, delay){
jQuery(selector).keyup(function(){
if(typeof(window['inputTimeout']) != "undefined"){
clearTimeout(inputTimeout);
}
inputTimeout = setTimeout(action, delay);
});
}
I then call this from the page in question's document.ready block with
afterDelayedKeyup('input#search',"submitQuizForm()",500)
What would be nice would be to make a new jquery event which uses this logic, eg .delayedKeyup to go alongside .keyup, so i could just say something like this for an individual page's document.ready block.
jQuery('input#search').delayedKeyup(function(){
submitQuizForm();
});
But, i don't know how to customise jquery in this way. That's a nice homework task though.
Nice job, Max, that was very helpful to me! I've made a slight improvement to your function by making it more general:
function afterDelayedEvent(eventtype, selector, action, delay) {
$(selector).bind(eventtype, function() {
if (typeof(window['inputTimeout']) != "undefined") {
clearTimeout(inputTimeout);
}
inputTimeout = setTimeout(action, delay);
});
}
This way you can use it for any type of event, although keyup is probably the most useful here.
I know this is old, but it was one of the first results when I was searching for how to do something like this so I though I would share my solution. I used a combination of the provided answers to get what I needed out of it.
I wanted a custom event that worked just like the existing jQuery events, and it needed to work with keypress + delete, backspace and enter.
Here's my jQuery plugin:
$.fn.typePause = function (dataObject, eventFunc)
{
if(typeof dataObject === 'function')
{
eventFunc = dataObject;
dataObject = {};
}
if(typeof dataObject.milliseconds === 'undefined')
dataObject.milliseconds = 500;
$(this).data('timeout', null)
.keypress(dataObject, function(e)
{
clearTimeout($(this).data('timeout'));
$(this).data('timeout', setTimeout($.proxy(eventFunc, this, e), dataObject.milliseconds));
})
.keyup(dataObject, function(e)
{
var code = (e.keyCode ? e.keyCode : e.which);
if(code == 8 || code == 46 || code == 13)
$(this).triggerHandler('keypress',dataObject);
});
}
I used $.proxy() to preserve the context in the event, though there could be a better way to do this, performance-wise.
To use this plugin, just do:
$('#myElement').typePause(function(e){ /* do stuff */ });
or
$('#myElement').typePause({milliseconds: 500, [other data to pass to event]},function(e){ /* do stuff */ });

Categories

Resources