How to get parent of first jQuery object? - javascript

I have the following code which is run at the end of a long table that has several button.enter-match elements:
$("button.enter-match")
.button()
.on('click', function() {
$("form.enter-match").dialog({
modal: true,
height: 'auto',
width: 200,
close: function() {
$("form.enter-match input[name='code']").val('');
},
open: function() {
$("form.enter-match input[name='code']").val('').focus();
},
buttons: {
Set: function() {
pid = $(this).parents("[data-pid]").data('pid');
if ($("form.enter-match input[name='code']").val() == '') {
alert('Code empty!');
return false;
}
$.post(
request_url,
{
'action': 'set_match',
'pid': pid,
'code': $("form.enter-match input[name='code']").val()
},
function (data) {
error_handler(data);
if (data['error'] == null) {
$("tr#pid-" + pid + " td.code:first div").html('<i>' + $("form.enter-match input[name='code']").val() + '</i>');
$("form.enter-match").dialog('close');
}
},
'json'
);
}
}
});
});
The line pid = $(this).parents("[data-pid]").data('pid'); does not get the pid data value because form#enter_match is created at the very top of the document to be reused in the code as needed. It therefore will not have a parent with the [data-pid] attribute, however, button.enter-match will. How do I get the value in [data-pid] for this particular button.enter-match from within the $("form.enter-match").dialog() portion of the code?

Could not figure out a way to get the next object up, so I simply moved pid = $(this).parents("[data-pid]").data('pid'); to the next scope up under the line .on('click', function() { which solved the problem in all instances.
Thanks to all who pointed out my bad coding practice with regards to IDs and classes. I've updated my coding style to reflect the better principals.

Related

AJAX Reload Interval (Polling) Assistance

I have several files I'm pulling minor text from (a single word most), and then stylizing that with another script.
Currently they load and display as they should. However, the text files update at random times, so I'd like them to be reloaded, and the subsequent script applied to them again.
I've tried different setTimeout as well as setInterval commands, but I think the issue is my placement or use. After several hours of research I'm certain it's just the syntax that's out of place.
This runs locally but is pulled through a program that excecutes the script as if remote. (no cross domain issues)
Here's one example segment that pulls a file and loads to the html the subsequent script reads to display:
$(function follow_pull() {
$.ajax({
url : "most_recent_follower.txt",
dataType: "text",
success : function (data) {
$("#follow").append(data).serialize();
},
setTimeout(fuction(){
follow_pull()
}, 10000);
});
});
Here's the segment that loads those files into the script to display:
$(window).ready(function ledload() {
var options = {
pixelSize: 5,
stepDelay: 62,
horizontalPixelsCount:650,
verticalPixelsCount:5,
pixelRatio: 0.8,
pathToPixelImage: 'ticker/pixel.png',
backgroundColor: '#000',
disabledPixelColor : '#020202',
enabledPixelColor: '#ff522b'
};
$('.canvasld, .crl').leddisplay($.extend(options, {pixelSize: 3}));
},
setTimeout(fuction(){
ledload()
}, 10000););
Any direction is appreciated. I can post the entire file if need by, but I figured someone would get what I'm doing and know how to direct me best.
For context I'm using a script that takes the text, and makes it look like an LED and scrolls as if it's a ticker. This is being used for a broadcaster on Twitch.
So reviewing what you provided in your comment, I found a way to get it working.
First, is the html below. Here are the differences:
I created a new element <div class="led"></div>. I also gave the .crl css to that element, and instead made .crl have display: none. This is because the .leddisplay function takes the element and replaces it with it's own HTML to render the LEDs. So you need to keep the div you are using to store your info separate from the div you are using to render it. (I would recommend just using JS variables to store that info, but I'm not trying to rewrite your code, just trying to get it working.)
But then how do you get the text into the LED display? With .leddisplay you can input the text you want as the second parameter of the function. You can see how I did that in postload().
To update your info, you were using append(). This adds to the divs, but you want to update them, so I replaced every .append() with .text() to replace the text rather than add on to it.
Finally, the heart of the solution. The leddisplay plugin doesn't have a way to update the led. So you have to 'destroy' it, and then rerun it, as I have done in the setTimeout() of postload(). But by itself, starts the scrolling all over again every 10 seconds. So what I do is track the current position, then after rerunning it, I resume the scrolling from there. However to make that work, I needed to update the plugin code. Below the HTML is the explanation for that.
HTML:
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
</head>
<style>
.led {
padding-top: 2px;
padding-bottom: 2px;
background-color: #444;
}
.crl {
display: none;
}
</style>
<div class="top-bar"></div>
<div class="crl">Newest Subscriber - <span id="sub"></span>
LAST DONATION - <span id="donation"></span>
LATEST BITS - <span id="bits"></span>
rECENT FOLLOWEr - <span id="follow"></span>
Sub Goal - <span id="subgoal"></span> / 80</div>
<div class="led"></div>
<div class="bottom-bar"></div>
<script type="text/javascript">
$.ajaxSetup({
async: false,
cache: false
});
$(function follow_pull() {
$.ajax({
url : "most_recent_follower.txt",
dataType: "text",
success : function (data) {
console.log(data);
$("#follow").text(data);
setTimeout(function(){
follow_pull()
}, 10000);
},
});
});
$(function donator_pull() {
$.ajax({
url : "most_recent_donator.txt",
dataType: "text",
success : function (data) {
console.log(data);
$("#donation").text(data);
setTimeout(function(){
donator_pull()
}, 10000);
},
});
});
$(function cheerer_pull() {
$.ajax({
url : "most_recent_cheerer.txt",
dataType: "text",
success : function (data) {
console.log(data);
$("#bits").text(data);
setTimeout(function(){
cheerer_pull()
}, 10000);
},
});
});
$(function subscriber_pull() {
$.ajax({
url : "most_recent_subscriber.txt",
dataType: "text",
success : function (data) {
console.log(data);
$("#sub").text(data);
setTimeout(function(){
subscriber_pull()
}, 10000);
},
});
});
$(function count_pull() {
$.ajax({
url : "total_subscriber_count.txt",
dataType: "text",
success : function (data) {
console.log(data);
$("#subgoal").text(data);
setTimeout(function(){
count_pull()
}, 10000);
},
});
});
$(function ledload() {
$.getScript( "ticker/jquery.leddisplay.js", function( data, textStatus, jqxhr ) {
console.log( data ); // Data returned
console.log( textStatus ); // Success
console.log( jqxhr.status ); // 200
console.log( "Load was performed." );
});
});
$(function postload() {
var options = {
pixelSize: 5,
stepDelay: 62,
horizontalPixelsCount:650,
verticalPixelsCount:5,
pixelRatio: 0.8,
pathToPixelImage: 'ticker/pixel.png',
backgroundColor: '#000',
disabledPixelColor : '#020202',
enabledPixelColor: '#ff522b'
};
$(".led").leddisplay($.extend(options, {
pixelSize: 3
}), $('.crl').text());
setTimeout(function () {
//get the current position
var x = $(".led").leddisplay('getCurrentPosition')
//destroy the led setup
$('.led').leddisplay('destroy');
//create it again
postload();
//set the position to where it left off at
$(".led").leddisplay('setCurrentPosition', x)
}, 10000);
});
</script>
Inside the plugin, look for customMethods towards the bottom. I added 2 more methods to it: getCurrentPosition and setCurrentPosition, so it should look like this:
jquery.leddisplay.js, customMethods:
var customMethods = {
init: function(){
var _arg = arguments;
return this.each(function() {
var $this = $(this);
if ($this.data('leddisplay'))
return;
$this.data('leddisplay', true);
var methods = resolveMethods(this);
methods.init.apply($this, _arg);
});
},
destroy: function(){
var _arg = arguments;
return this.each(function() {
var $this = $(this);
if (!$this.data('leddisplay'))
return;
$this.data('leddisplay', null);
var methods = resolveMethods(this);
methods.destroy.apply($this, _arg);
});
},
start: function(){
},
stop: function(){
},
getCurrentPosition: function(){
return $(this).data('currentPosition');
},
setCurrentPosition: function(x){
$(this).data('currentPosition', x);
}
}
After you make these changes, it should work as expected.
First I'd pull ledload() out of the $window.ready(). This way, it can be referenced by it's name. Also, I'm pretty sure you don't need the $(...) wrapper for the follow_pull() function...
function ledload() {
var options = {
pixelSize: 5,
stepDelay: 62,
horizontalPixelsCount:650,
verticalPixelsCount:5,
pixelRatio: 0.8,
pathToPixelImage: 'ticker/pixel.png',
backgroundColor: '#000',
disabledPixelColor : '#020202',
enabledPixelColor: '#ff522b'
};
$('.canvasld, .crl').leddisplay($.extend(options, {pixelSize: 3}));
}
function follow_pull() {
$.ajax({
url : "most_recent_follower.txt",
dataType: "text",
success : function (data) {
$("#follow").append(data).serialize();
ledload();
setTimeout(function(){
follow_pull();
}, 10000);
}
});
};
follow_pull() calls ledload() when it successfully gets the data. Then it sets up a 10 second delay before it does it all over again.
If you still wanted ledload to run on $(window).ready(), you can add this line as well:
$(window).ready(ledload);
P.S. I don't see what .serialize() is doing...Is that supposed to get passed into ledload()?
You're on the right track, but you need to move the setTimeouts slightly, like so:
$(function follow_pull() {
$.ajax({
url : "most_recent_follower.txt",
dataType: "text",
success : function (data) {
$("#follow").append(data).serialize();
setTimeout(fuction(){
follow_pull()
}, 10000);
},
});
});
This way, once the data has successfully loaded, it will call follow_pull again after 10 seconds.
For the other bit, you need to move it like so:
$(window).ready(function ledload() {
var options = {
pixelSize: 5,
stepDelay: 62,
horizontalPixelsCount: 650,
verticalPixelsCount: 5,
pixelRatio: 0.8,
pathToPixelImage: 'ticker/pixel.png',
backgroundColor: '#000',
disabledPixelColor: '#020202',
enabledPixelColor: '#ff522b'
};
$('.canvasld, .crl').leddisplay($.extend(options, {
pixelSize: 3
}));
setTimeout(fuction() {
ledload()
}, 10000);
});
The AJAX ready function only takes one argument, but you were passing the setTimeout as a second argument, so it was being ignored.

Materialize CSS on chip delete

I have been trying to get the tag of a deleted chip from the div in the Materialize chips class, but nothing is working.
Here is what I have already tried.
$('.chips').on('chip.delete', function(e, chip){
console.log(chip);
console.log(e);
console.log(chip.tag);
});
None of the above is working.
With just only console.log(chip), I get undefined error in JavaScript console, but the function is firing when I delete the chip. I am just not able to get the value of tag of deleted chip. I want to store the tag in a variable.
I am creating chips dynamically on Materialize date select:
$('#pm_date').change(function () {
var chipvalue = $(this).val();
if (chipvalue !== "") {
// checking if tag already exits
if ($("#date_chip_select:contains(" + chipvalue + ")").length > 0) {
alert('Date already selected');
} else {
var appendstring = "<div class='chip' id='date_chip_child_" + chip_id + "'>" + chipvalue + "<i class='material-icons close'>close</i></div>";
}
}
});
Here is the fiddle: https://jsfiddle.net/hq22mne4/1/
chips.js, which is part of materialize, doesn't seem to expose any methods for adding or removing chips programmatically. It seems to exclusively listen for an enter keydown event and then internally add the chip.
So, I stitched together a workaround that does just that. I set potential chip's value within your onchange event:
$("#datechips").find('input').val($(this).val());
And create the chip when date picker is closed:
$('.datepicker').pickadate({
selectMonths: true,
selectYears: 15,
onClose: function() {
// add chip via filling the input and simulating enter
$("#datechips").find('input').trigger({ type : 'keydown', which : 13 });
},
});
It may not be ideal, but you should be able to tailor this going forward.
https://jsfiddle.net/j3ej8240/
I've also had a lot of trouble working this out. This is how I capture the add and delete chip events without using jQuery:
function chipDeleted(e, data) {
console.log("Chip was deleted with text: " + data.childNodes[0].textContent);
}
function chipAdded(e, data) {
console.log("Chip was added with text: " + data.childNodes[0].textContent);
}
//
document.addEventListener("DOMContentLoaded", function (e) {
console.log("DOM fully loaded and parsed");
var firstTag = "Initial Tag";
var elems = document.querySelectorAll('.chips');
var instances = M.Chips.init(elems, {
data:[{
tag: firstTag
}],
autocompleteOptions: {
limit: Infinity,
minLength: 1
},
placeholder: "No search...",
onChipDelete: function (e, data) { chipDeleted(e, data) },
onChipAdd: function (e, data) { chipAdded(e, data) }
});
});
And my HTML part is like this:
<body>
<div class="chips search-history"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
</body>

Get data from the server and display in the Edit Form

This question is continuation of the following question Add JSON data to the view that unfortunately ended up unresolved yet.
In my main view which has a form with 2 controls and placeholder for flexigrid I added the following at the bottom
<div id="add-edit-dialog" style="display: none" title="Add / Edit Client">
#Html.Partial("_ClientForm", Model)
</div>
The flexigrid pluglin instantiates in run-time and adds 3 buttons: Add, Edit, Delete.
For Edit button I need to get the current row information from the server and then display it in the Form. For Add button I do not need to go to the server (I think).
This is my current code for the Edit button:
function edit(com, grid) {
$('.trSelected', grid).each(function () {
var id = $(this).attr('id');
id = id.substring(id.lastIndexOf('row') + 3);
currentId = id;
$('#fntype').val('Edit');
var ClientName;
ClientName =$('.trSelected td:eq(2)').text();
var url = '/Client/Edit/' + id ;
$.getJSON(url, function (html) {
// setFormControls(data.Id, data.Role, data.Location, data.JobType,
// data.Description);
// alert(data);
$($dlg).html(html);
});
//location.replace(url);
RunModalDialog("Edit Client: " + ClientName);
});
So, it is going to Edit controller action and returns that same partial view _ClientForm with correct information passed as a model. If I look at the response result returned in FireBug I can see that the returned HTML is correct and all the textboxes have correct information in their values.
However, the dialog that opens looks exactly the same as the dialog for the Add button - in other words, all form controls come blank. I can not figure out what is wrong and why it is not working the way I want it.
This is what I have for the RunModalDialog:
var validator = $("#add-edit-form").validate();
var $dlg = $("#add-edit-dialog").dialog({
autoOpen: false,
show: "blind",
closeOnEscape: true,
resizable: true,
width: 1200,
height: 750,
minHeight: 600,
minWidth: 950,
buttons: {
"Save": function () {
if ($("#add-edit-form").valid()) {
// jobPost.setVals(txtId.val(), txtRole.val(),
// txtLocation.val(), txtJobType.val(),
// txtDescription.val());
$.ajax({
type: 'POST',
//data: JSON.stringify(clientInformation),
url: '/Client/Save',
dataType: 'json',
contentType: 'application/json',
success: function (result) {
// insert new list into grid
$('#flexClients').flexAddData(result);
}
});
$(this).dialog('close');
} else return false;
},
Cancel: function () {
$(this).dialog("close");
clearForm();
if (validator)
validator.resetForm();
}
},
close: function () {
clearForm();
},
open: function () {
//$("#add-edit-dialog").parent().appendTo($("#add-edit-form"));
}
});
function RunModalDialog(title, url) {
if (title) {
$dlg.dialog("option", {"title": title });
}
if (url) {
$dlg.load(url).dialog("option", { "title": title }).dialog("open");
//$dlg.load(url, function () {
// var validator = $("#sform").validate();
// if (validator)
// validator.resetForm();
// $dlg.dialog("option", { "title": title }).dialog("open");
//});
} else {
$dlg.dialog("open");
}
}
The code with the load (and commented code) was another attempt to solve this problem. That sort of worked (the form displayed with the info), but the main Client view was also reloaded so I was seeing double grid.
Do you see what should I change in my code to get this thing working?
Thanks a lot in advance.
With Jazzen Chen from MS help we solved this problem. All I needed to do to display the data correctly was to change getJSON to just get jquery function. Now my form comes with data populated correctly and the next challenge will be to save the data.
I posted a blog post with what I have so far - hope it may help
http://blogs.lessthandot.com/index.php/WebDev/UIDevelopment/AJAX/asp-net-mvc-project-with

jQuery each() not continuing code execution for first element if a second element was clicked?

Sorry if the title is not clear enough, I have <a> elements with the same class when user clicks on each one the jquery code should run for each one alone, the problem is when clicking the first element and before it finishes running the whole code if I click a second element it leaves the first one incomplete and runs the code on the second one, it's supposed to work simultaneously (btw it's supposed to send data to a php file and it's working fine even if I click many elements by the classes are not working)
here's the code:
jQuery(function($) {
$('.anchor-tag-class').each(function() {
$(this).click(function() {
$this = $(this);
var id = $this.attr('data-id');
if ( $this.hasClass('on') ) {
$this.removeClass('on');
$this.addClass('loading');
$.post("process.php", { element_id: id, status: 'off' }, function(data) { $this.addClass('off').removeClass('loading'); } );
} else {
$this.removeClass('off');
$this.addClass('loading');
$.post("process.php", { element_id: id, status: 'on' }, function(data) { $this.addClass('on').removeClass('loading'); } );
}
});
});
});
so what am I doing wrong ?
and thanks in advance.
You don't need the each() in this case, as the code will only be run for the specific element which raised the event. You can also chain your functions hanging off the $this variable.
Try this:
$('.anchor-tag-class').click(function() {
var $this = $(this);
var id = $this.attr('data-id');
if ( $this.hasClass('on') ) {
$this.removeClass('on').addClass('loading');
$.post("process.php", { element_id: id, status: 'off' }, function(data) { $this.addClass('off').removeClass('loading'); } );
}
else {
$this.removeClass('off').addClass('loading');
$.post("process.php", { element_id: id, status: 'on' }, function(data) { $this.addClass('on').removeClass('loading'); } );
}
});
You have a $this variable, set to $(this)... Where is $this defined? If it is outside the scope of the function, that's your problem!

change loses bind reference

Have a link that uses the ID to grab specific content from an external file (works, no problems here). I then change the ID of the link so that a new ID so that new info can be gotten the from the external file but the same info is always shown. So, I'm looking for some help in figuring out why the new info isn't being loaded but the old instead.
Here is the code for setting the new ID value. It resides in a completely separate section of the code. It then calls the function fncSetupInfoWindow() and it creates the bindings. .windowInfo is a class set on specific elements.
$('#pickedCenterProgram a').text(newProgram[0]).parent().slideDown().attr('id', newVal).attr('title', newProgram);
fncSetupInfoWindow();
function fncSetupInfoWindow() {
$('.windowInfo').unbind('mouseover mouseout').each(function () {
var obj = $(this), position = [], contentID = globalObjects.emptyString, title = obj.attr('title'), contentID = obj.attr('id').toLowerCase();
obj.bind({
mouseover: function (e) {
position = fncGetPositionArray(e.pageX, e.pageY);
fncLoadStatusInfo(position[0], position[1], contentID, title);
},
mouseout: function () {
$('#modInfoWindow').closeModal();
}
});
});
}
Here is the code for loading the info
function fncLoadStatusInfo(x, y, programName, title) {
initLoader.className = 'txt-c'; //create loader
initLoader.iconClass = 'alignVert-b';
$('#modInfoWindow').createModalWindow({ isModal: false, left: x, top: y, ignorePosition: false, title: title, width: 250, hideCloseIcon: true, autoOpen: true }).html(initLoader.createLoader());
$('#modInfoWindow').load('../pages/infoFile.htm ' + '#' + programName);
return false;
}
Everything works, well almost, except that the newly assigned ID is not being used but the original for when the page is created. I've tried numerous things as well as even destroying the modal (aka dialog) window all with the same results.
thanks ^.^
Thanks.
The problem is that you're using the id at the time it was bound (inside the .each()), rather than at the time of the event (inside the event handler). You can do it at the time of the event and simplify things overall like this:
function fncSetupInfoWindow() {
$('.windowInfo').bind({
mouseover: function (e) {
var pos = fncGetPositionArray(e.pageX, e.pageY);
fncLoadStatusInfo(pos[0], pos[1], this.id.toLowerCase(), this.title);
},
mouseout: function () {
$('#modInfoWindow').closeModal();
}
});
}
Or even simpler (probably what you want) using .hover():
function fncSetupInfoWindow() {
$('.windowInfo').hover(function (e) {
var pos = fncGetPositionArray(e.pageX, e.pageY);
fncLoadStatusInfo(pos[0], pos[1], this.id.toLowerCase(), this.title);
}, function () {
$('#modInfoWindow').closeModal();
});
}

Categories