I am trying to update data-coords (11th line), but when I do it the code runs but the data-coords don't update. Why? It looks valid to me, am I missing something?
$(document).on('click', '.next-prev-js', function (e) {
var item = e.target;
if($(item).is("img") && tagging){
var offset = $(item).offset();
var imgid = $(item).attr("data-image-id");
var obi = $("#blackout-image").offset();
x = (e.clientX - offset.left);
y = (e.clientY - offset.top);
addTag(e.clientX - obi.left - 55, e.clientY - 55);
saveCoords(x, y, imgid);
$(item).attr("data-coords", x+","+y);
tagging = false;
$(".tag-self").text("Tag yourself");
$("#blackout-image img").css({cursor: "pointer"});
$("#blackout-image .face").delay(3000).fadeOut("fast");
return false;
}
var action = $(item).attr("data-action");
nextPrevImage(action);
return false;
});
Here is the HTML portion (This is inside a php echo statement):
<a class='thumb-photo' href=''>
<img class='thumb-img' data-coords='$x,$y' data-id='$id' data-image-id='$imid' data-file='$f' src='/user-data/images/image.php?id=$id&file=$f&height=240&width=240' width='240' height='240' />
</a>
Demo
(Don't refresh the page during this process)
If you click on one of the images, it will open in a viewer .
On the left hover over "Where is He" and a square will show where the data-coords are (from thumbnail image)
Next click on "Tag yourself", then click on a location in the image.
Close the viewer by pressing "esc" or clicking on the transparent area
Click on the image again, and mouse over "Where is He" the coords are still the old coords, but they should have been updated after you clicked on the new location
http://wows.phpsnips.com/profile.php?id=1&tab=photos
You should use the data method.
$(item).data({coords: x+","+y});
or
$(item).data("coords", x+","+y);
works in jsfiddle.
You can see your data attributes with:
console.log($(item).data());
The way the data- attributes work is that the value gets copied into the jQuery data object on page load. After that they aren't really connected anymore. So if you change the attribute, the object won't update automatically. Same for the other way around.
I made a quick test to demonstrate the behavior:
jQuery:
var $d = $('div');
alert('Load: Attribute "a" gets copied to data object.\rData Attribute: ' + $d.attr('data-test') + '\rData Object: ' + $d.data('test'));
$d.attr('data-test','b');
alert('Changed attribute to "b". Attribute changed, object still "a".\rData Attribute: ' + $d.attr('data-test') + '\rData Object: ' + $d.data('test'));
$d.data('test','c');
alert('Changed data object to "c". Object changed, attribute still "b".\rData Attribute: ' + $d.attr('data-test') + '\rData Object: ' + $d.data('test'));
Demo:
http://jsfiddle.net/F5qkq/
So in your case, you only change the data attribute with attr but that way the internal data-object remains the same because they aren't connected anymore.
The data-attribute is only really used to initialize the data object with a startvalue. But after that, as said before, you should only work with jQuery's data function to change the internal data object.
Related
first of all, I am not sure how to ask this properly. I hope you can understand based on the piece of code I provide below.
The code below basically appends every new content from bottom to top. I would like to make every new content to fade out after a few seconds. So that means, once every new content appear, it will fade out after few seconds.
function addContent(payload) {
// Container
let content = $('#paper');
content.append("<div class='item'>" + payload + "</div></br>");
// Scroll top bottom
content.animate({ scrollTop: content.get(0).scrollHeight }, 333);
}
I found this code .fadeIn('fast').delay(5000).fadeOut('fast') somewhere on the internet but I don't know how to use it with the code I have up there.
Code:
function addContent(payload) {
// Container
let content = $('#paper');
$("<div class='item'>" + payload + "</div></br>").appendTo(content).fadeOut(500);
// Scroll top bottom
content.animate({ scrollTop: content.get(0).scrollHeight }, 333);
}
Explanation:
While using JQuery you need to first Select an element and than apply the respective function to it.
So first we select the element which is $("<div class='item'>" + payload + "</div></br>") and then append it into the appropriate place which will become
$("<div class='item'>" + payload + "</div></br>").appendTo(content)
Creating New Elements
Then we will apply the fadeOut function to our New Element and the final result will be $("<div class='item'>" + payload + "</div></br>").appendTo(content).fadeOut();
More details about fadeOut
JQuery applies the method to what is Selected.
I have a code that works perfectly when the number of thumbnails to rotate is 16 and the location is the same for all (only changes the name of the file due to the thumbnail number). Example: http: //www.urltoimage1.jpg....http: //www.urltoimage16.jpg
This is the html:
<img width="189" height="142" src="http: //www.urltoimage8.jpg" class="someclass" id="latest-499" onmouseover="thumbStart('latest-499', 16, 'http: //www.urltoimage');" onmouseout="thumbStop('latest-499','http: //www.urltoimage8.jpg');">
Here is the javascript:
// JavaScript Document
//rotating thumb functions
var rotateThumbs = new Array();
function changeThumb( index, i, num_thumbs, path)
{
if (rotateThumbs[index])
{
if(i<=num_thumbs){
document.getElementById(index).src = path + i + ".jpg";
i++;
setTimeout("changeThumb('"+ index +"'," + i + ", " + num_thumbs + ", '" + path + "')", 600);
}else{
changeThumb( index, 1, num_thumbs, path);
}
}
}
function thumbStart(index, num_thumbs, path)
{
rotateThumbs[index] = true;
changeThumb( index, 1, num_thumbs, path);
}
function thumbStop(index, srco)
{
rotateThumbs[index] = false;
document.getElementById(index).src = srco;
}
Now, the problem is for some articles the thumbnails are not in the same location. Example: http: //www.urltoimage1.jpg....http: //www.urltoimageksks16.jpg
I think that, in the existence of this discrepancy, it is better to copy all the urls of the thumbnails to the class of the image, leaving the html in this way:
<img width="189" height="142" src="http: //www.urltoimage8.jpg" class="http: //www.urltoimage1.jpg,http: //www.urltoimage2.jpg,...,http: //www.urltoimageksks16.jpg" id="latest-499" onmouseover="thumbStart" onmouseout="thumbStop('latest-499','http: //www.urltoimage8.jpg');">
Now that I have all the urls in the class of the img tag, how can achieve that the thumbnail rotate?
Thanks
don't store the urls in the class attributes, use Data Attributes instead. (or Data Attributes from jQuery)
something like
<img .. data-thumbnail-url="http: //www.urltoimageksks16.jpg" .. />
if you're using jQuery (you've added it to your tags), you could use directly
var thumbnailSrc = jQuery('img').data('thumbnail');
if you're not using it (since I don't see any jQuery at all in your code) you have to use this instead
var thumbnailSrc = document.getElementById(index).dataset.thumbnail
using that, you could replace your src attribute. you'll probably want to store in data attributes the original src.
About rotating itself (It is not clear if it is part of your question or if you want to know if it is ok to store the urls in class attributes), there are answers for that using jquery, like jQuery animate image rotation You only need to adapt the functionality to be executed on hovering. You could use pure css as well Spin or rotate an image on hover
On a side note, use this
var rotateThumbs = [];
rather than
var rotateThumbs = new Array();
See In JavaScript, why is [ ] preferred over new Array();?
I am having an issue where when I have a rich text field that has design mode on that is within a sortable LI. The problem is that designMode changes to 'Off' if the LI is dragged to a new position. And even though I am able to target the correct iframe, it seems to ignore when I tell it to turn designMode back on, does anyone know why this is happening? Thank you for reading.
edit: jfiddle example: https://jsfiddle.net/LcLfaa8j/2/
function getRichTextField( itemId ) {
console.log('get rich text field');
return document.getElementById('rtf-iframe-' + itemId);
}
$(document).ready(function() {
getRichTextField("sort-textItem-1").contentWindow.document.designMode = "On";
getRichTextField("sort-textItem-2").contentWindow.document.designMode = "On";
$("#text-areas").sortable({
axis: 'y',
opacity: 0.8,
tollerence: 'pointer',
update: function(event, ui) {
var order = $(this).sortable( "serialize", { key: "order" } );
console.log("New Order = " + order);
console.log('the iframe that was moved designMode is now Off...');
var richText = getRichTextField($(this).data().uiSortable.currentItem.attr('id'));
console.log('TEST: the current is ' + $(this).data().uiSortable.currentItem.attr('id') + ' and designMode = ' + richText.contentWindow.document.designMode + ' doubleCheckOfRTFid = ' + $(richText).attr('id') + ' class = ' + $(richText).attr('class'));
richText.contentWindow.document.designMode = "On";
console.log('just attempted to turn designMode back on... but it gets ignored');
}
});
});
This is only a partial answer.The designMode isn't getting turned off; it's off by default, and the document where you set .designMode="on" gets deleted (and then recreated from scratch) when you drag it. You can see that if you put content into one of the documents and then drag it, the content disappears. Looks like the iframe is getting a new .contentWindow, which means it has a different child document too.
You can see this in the inspector by running
var before = getRichTextField("sort-textItem-2");
var beforecontentWindow=before.contentWindow;
(now drag the second iframe)
Now run:
var after = getRichTextField("sort-textItem-2");
var aftercontentWindow=after.contentWindow;
Now compare the references with ===:
before === after ;//returns true because iframe is the same
beforecontentWindow === aftercontentWindow ;//returns false because .contentWindow changed
Also see this post Jquery Sortable and Draggable between parent and child frame where he had trouble implementing draggable and sortable, but got it working eventually.
I don't know why being dragged would give your iframe a new contentWindow, but maybe someone else will be able to build on this.
It seems like adding a small delay with a setTimeout before turning designMode back on fixes this. Is this the only solution? Just curious.
I am trying to integrate a sticky headers technique like the one shown here... Persistent Headers.
I have tried to integrate it into my code and for the most part have been successful, however it isn't behaving correctly and I REALLY can't figure it out.
I'll try to explain in a nutshell what the page it is being used on does. I have a database with a table of students and another table of assessments. This page loops through a JSON object (recieved from the database via a PHP script) and then for each student in that first object fetches another JSON with their assessments. This all works fine. It does however create a fairly long page. Visually it looks like this...
Code rendered in Chrome
The code I have written based on that tutorial I posted above is supposed to clone headers specified by a class and then hide or show them based on some logic involving scrollTop the position of the element and the length of the element. This having the effect of the header sticking to the top of the page while the container it belongs to is still visible.
The problem is something is going wrong and although all the headers are shown in sequence they are way too early, they seem to hang about for different lengths of time, and these lengths do seem to correlate to how long the container it belongs to is.
So my code...
Firstly the function used to update the headers...
containerArray = new Array;
positionArray = new Array;
floatingHeaderArray = new Array;
function updateTableHeaders() {
$(".studentContainer").each(function(i) {
containerArray[i] = $(this);
var position = containerArray[i].position();
positionArray[i] = position.top;
var scrollTop = $("#main").scrollTop();
floatingHeaderArray[i] = $(".floatingHeader", this);
if ((scrollTop > positionArray[i]) && (scrollTop < positionArray[i] + containerArray[i].outerHeight(true))) {
floatingHeaderArray[i].css({
"visibility": "visible"
});
} else {
floatingHeaderArray[i].css({
"visibility": "hidden"
});
};
});
}
Now the code that generates the containers, headers and tabs.
$("#mainContent").fadeIn(0);
loadMessage = "Loading data for " + event.target.id;
$.getJSON('php/oneFullClass.php?techClass=' + event.target.id, function(data) {
$('#mainTitle').fadeOut(0);
$('#action').html('You are ' + actionIntent + 'ing ' + event.target.id);
$('#action').fadeIn(300);
$('#mainTitle').fadeIn(300);
$('#mainContent').append('<div id="scrollTopDisplay"></div>')
dynamicPositioning();
$.each(data, function(key, val) {
var thisPosition = positionArray[0]
$('#mainContent').append(
'<div class="studentContainer studentView" id="' + val.idStudent + '">' +
'<div class="studentName">' + val.name + ' ' + val.surname + ' - (' + val.form.substr(0, 1) + '/' + val.form.substr(1, 2) + ')</div>' +
'<div class="floatingHeader">' + val.name + ' ' + val.surname + ' - (' + val.form.substr(0, 1) + '/' + val.form.substr(1, 2) + ')</div>' +
'<div class="studentTarget"> Target: <strong>' + val.target + '</strong></div>' +
'</div>');
$(".studentContainer").hide().each(function(i) {
//$(this).slideDown(0);
$(this).delay(i * 50).slideDown(300).fadeIn(500);
})
//Get previous assessments for this student and build tabs
buildTabs('php/allPreviousAssess.php?sid=' + val.idStudent, val.idStudent);
});
});
$('#mainContent').append('<div id="expandAll" onClick="expandAll()">Expand</div>');
$('#mainContent').append('<div id="collapseAll" onClick="collapseAll()">Collapse</div>');
dynamicPositioning();
$('#expandAll').delay(300).fadeIn(300);
$('#collapseAll').delay(300).fadeIn(300);
$("#main").scroll(updateTableHeaders);
I think that's all the info you'll need but I'll post any other code that may be referenced in this code if you think it'll help figure it out.
I have a suspicion that the problem is something to do with the animated slide in effect I am using on the 'assessment cards' messing with the position values, or possible position()'s inability to get positions of hidden elements. However, as I call updateTableHeaders() with every scroll event, this shouldn't be an issue as all animation is over by the time you are given access to the layout (there is a modal shade effect that only dissapears once all AJAX requests are complete.
I hope someone can help, this one is making me unhappy! :(
Balloon, a library I wrote for easily making your headers stick, is pretty hassle-free. You simply make a Balloon object instance, specifying if you want your sticky headers to be stacked or replaced, and then inflate the headers by passing in the strings of their ids. Give it a try and let me know if it helped you:
https://github.com/vhiremath4/Balloon
If you find any issues with it, file a bug report on the repository, but I feel like it should do its job in your case.
I have a script that builds a dynamic div with contents. The button that initializes the build uses an onclick command and a ajax call to retrieve the appropriate info, then builds the div. This all works great, it builds the div, and jquery shows the div and the button changes to the close button. The problem now is that the button still has the onclick command attached to it, and I was to strip this command off, and reapply it if the user wants to view the information again.
The button code on initial load:
<img class="showPixFeature hidden" id="butShowImage_<?php echo $row_rsFeatureAds['AdID']; ?>" src="../images/class_see_more.png" align="absmiddle" onclick="getRemoteInfo('PicDetailFeature_<?php echo $row_rsFeatureAds['AdID']; ?>')" style="cursor: pointer" />
Script that builds the div:
function showImage(IDS, selectedID){
var adType = new Array();
adType = IDS.split("_");
//alert(adType);
var thumbs = new Array();
thumbs = adType[1].split("~");
var adID = thumbs[0];
//alert(adType[0] + '_' + thumbs[0]);
var picImage = document.getElementById(adType[0] + '_' + thumbs[0]);
removeChildren(picImage);
var picThumbs = document.createElement('div');
arLen = thumbs.length;
//alert(arLen);
if(arLen > 2){
for ( var i=1, len=arLen; i<len; ++i ){
//alert(thumbs[i]);
var thumbNail = document.createElement('img');
thumbNail.src = "../images/listings/" + adID + "_" + thumbs[i] + "_sm.jpg";
thumbNail.className = "thumbNails";
thumbNail.id = adID + '_' + thumbs[i];
picThumbs.appendChild(thumbNail);
picImage.appendChild(picThumbs);
addHandler(adID, thumbs[i], 1);
}
}
var previewImageContainer = document.createElement('div');
var previewImage = document.createElement('img');
previewImage.id = 'full_' + adID;
previewImage.src = "../images/listings/" + adID + "_" + "1_.jpg";
previewImage.className = 'thumbNails';
previewImageContainer.style.width = "700px";
previewImageContainer.style.textAlign = 'center';
previewImageContainer.appendChild(previewImage);
picImage.appendChild(previewImageContainer);
var closeButton = document.createElement('img')
closeButton.src = '../images/close_pix.png';
closeButton.id = 'close_' + adType[0] + '_' + adID;
picImage.appendChild(closeButton);
addHandler(adID, 'close_' + adType[0], 2);
$("#" + adType[0] + '_' + adID).show('blind', {}, '1300');
$("#butShowImage_" + thumbs[0]).attr("src", "../images/close_pix.png");
$("#butShowImage_" + thumbs[0]).removeClass('hidden').addClass('shown');
}
Is there a way of stipping that onclick command off?
Thanks for you help!
I prefer to .delegate() and .undelegate() methods for binding event stuffs like that. Delegate is little bit different from the .bind() and .live() methods
Here is the great explaination about the diffrences
http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-the-difference-between-live-and-delegate/
kep it in mind :)
There are several issues I would fix with your code. First and foremost is to separate your functionality from your markup. This means removing the onclick events that you are firing through your elements. Now, this gets more complicated because you are passing PHP vars through your markup as well.
So your issue can be broken down into to sections.
Removing event handlers from your markup. This is, among other things i'm sure, a poor way to organize functionality.
A more robust means of communicating between JavaScript/PHP. In order to really take advantage of the web-based environment it will save you a lot of trouble passing variables in a more organized fashion. I would recommend looking into pairing Ajax with JSON. jQuery has some good implementations of both of these ($.Ajax() | $.parseJSON()).
The primary goal here is to clean up your markup to make it more readable, and better contain the different functions of your application - Functionality, Style, and information.
First, clean up your element a bit by removing the onclick event listener
<img src="example.jpg" id="someId_<?php echo id;?>;" class="showPixFeature" />'
Second, attach your event listener in whichever fashion you would like. Use $.delegate if you are dynamically generating the images. Use $.bind if you are not.
$('.showPixFeature').bind('click', function(){
// this function will execute everytime an element is clicked
// you have access to the element ID here via 'this' because
// the functions context is the element that fires it
alert($(this).attr('id'));
});
You can then remove the bound event with $.unbind() API. OR $.undelegate if you are using delegate. From here we can add an ajax call to
$('#my-element').unbind('click');
You could use .one(). It's the same as using .bind(), and it unbinds it after it's used once.