I am beginner in jQuery and asp.net. I created a simple chat application using SignalR, the design of which you can find here fiddle
How can I create a new instance of that chat design whenever a user has been call by other user while he/she were in chat from before with other user. Here I think I can convert it to User Control. but I dont want to have same Id's which I am using for other chat design and those generated instances should work differently, I mean if userA calls userB and at the same time userC calls userB then they must be created in such a way that they must be unique in handling there own calls (just like FB Chat).
The another issue may arise after successfully creating a new instance is that they might not be get attached to the jQuery functions and server side code automatically. If so, anyway to solve this too?
Before asking here I searched alot (maybe I dont know the exact keyword to search for).
EDIT: Many jQuery developers suggested me to go with Knockout.js or Backbone.js or simple jQuery. But I think there is some simple way to achieve this using ASP.NET functions like User Control or HTTP Handlers (or something else). About which I dont know anything. So, please suggest me which concept to opt for ? and please give detailed explanation(if possible with simple example).
jquery related answers are also welcome.
Single Instance
Multiple Instances
Use JQuery to populate or popup new instance of chat but change your ids using jquery. I would suggest have all your styling and ids done according to a parent container so you can easily grap the parent, duplicate it and change the IDs or content.
I would keep a non filled chat window with ID's like "updateme1" updateme2 etc and then once i get it as a template i will replace all ids one by one with relevant content.
You are doing it right and i dont think its signalR that you need to look into. SignalR would be able to help you pass on specific parameters like "requirechatwindow=true or false" based on if this person is in chat with current person but you can always do this on client as well by going through current open chat sessions. If current chat session does not contain a chat between A and B then open new window with new ID and put a data-from= A and data-to=B as a palceholder so you know this chat is between A and B etc
Hope this helps
UPDATED Fiddle and technique
Here is the fix on Your fiddle edited to show creation and multiple ids I had to adjust some of your css to view the boxes in different location
Updated the code with some comments
The technique is simple:
You create a html template on your page might be in a hidden region
You then use that to create new element in a container and have a handle to pickup this element for example in my code the currentid is my handle but i know the container name so i will only pickup template populated within the actual container to avoid conflict with template itself.
Assign a new id and then you can use any events or any speacial objects on there.
You can then pickup new elements from the new id or any other handle you might have inside them. For example i have just added a click even on it with confirm to hide it.
$('#doubleme').click(function(){
var currentid = $("#chattemplate .chat-outline").attr('data-tid');
var newid = parseInt(currentid,10) + 1;
$("#chatcontainers").append($("#chattemplate").html());
$("#chatcontainers .chat-outline").attr('id',"id"+newid);
$("#chattemplate .chat-outline").attr('data-tid',newid);
});
You only need these five lines of code actually and if you go to fiddle i have commented all of them but they are easy to understand. I am using selectors used in fiddle but these can be further optimised with attributes like data-handle-for or whatever name you can give.
If you are considering this for SignalR then within your hub response of new request you can call the intiate chat window which can setup everything on the client. Any subsequent messages using that data handle can be updated within this new chat window.
For example i assume you create a new group called "chatwindow7" and "chatwindow8" which makes its round trip in your send method and so on get broadcast to only user with this group. Then each user might have multiple windows open but you only need to pickup chatwindow7 for messages with that data handle and update it and so on.
If you are using one-to-one chat users only then you can use connection id as well which means all messages broadcasted will have both sender and reciever (by deafault) connection ID and you only need to pickup the window with connection id handle and update its list of messages or whatever.
The simplest way to do this is to replace the id attributes with class attributes.
<div id="chat-outline">
...
</div>
becomes
<div class="chat-outline">
...
</div>
And update your CSS appropriately.
.chat-outline
{
background-color: gray;
....
}
Then use a text/template tag to make it available to jQuery.
<script type="text/template" id="chat-template">
<div class="chat-outline">
...
</div>
</script>
Note that because browsers ignore script types they don't recognise, this will be ignored by the html rendering engine, but as it has an id, it will be visible to jQuery, and can be accessed thus:
<div id="container">
</div>
<script type="text/javascript">
$(function() {
var chatTemplate = $('#chat-template').html();
$('#container').append(chatTemplate); // First instance
$('#container').append(chatTemplate); // Second instance
$('#container').append(chatTemplate); // Third instance
});
</script>
Of course, if your code needs an id attribute as a handle for a chat instance, you can create a function that creates the chat-instance html given an id. In this case I'll use underscore to provide random-id, template, and iteration functions, but it is easy to use another library, or write your own.
<div id="container">
</div>
<script type="text/template" id="chat-template">
<div class="chat-outline" id="<%= id %>">
...
</div>
</script>
<script type="text/javascript">
var createChatInstance(idstring) {
return _.template($('#chat-template').html(), { id: idstring });
}
$(function() {
var chatTemplate = $('#chat-template').html();
// Create an array of 3 unique ids by which chat instances will be accessed.
var chatIds = [_.uniqueId('chat-outline'),
_.uniqueId('chat-outline'),
_.uniqueId('chat-outline')];
_.each(chatIds, function(chatId) {
$('#container').append(createChatInstance(chatId));
});
// You now have an array of 3 unique ids matching 3 divs.
// You can access individual sub-divs via descendent class matching from the id
// thus: $('#' + chatIds[n] + ' .chat-message').keyup(...code handling event...);
});
</script>
At this point, if you want to take the architecture further, you really do need to consider investigating something like backbone.js.
Hope this helps.
Related
I want to insert my block of HTML into a Shopify shop after a certain section but the problem is that each shop can use one of thousands of different themes, each one having a different DOM structure.
I can create the Script Tag and I can try to insert my HTML like this:
(function() {
var child = document.createElement("div");
var text = document.createTextNode("This is a test message");
child.appendChild(text);
var parent = document.getElementByClassName("ProductSection");
parent.appendChild(child);
})();
And this will work if the theme has a section with a class name of ProductSection but it won't for the majority of them that don't. Let's say I have an image gallery I'd like to show but only on Product pages and after the product description, what's the best way to select the product description DOM node so that I can insert my image gallery after it?
I found a couple threads with similar problems:
https://community.shopify.com/c/Shopify-APIs-SDKs/Using-Script-tag-to-add-dynamic-content-to-product-template/m-p/457855
https://community.shopify.com/c/Shopify-APIs-SDKs/Need-to-add-a-button-to-the-Product-page-via-a-Script-Tag/m-p/413919
and they seem to come to a similar conclusion, yet there are apps on the Shopify app market that do exactly this, and I wonder how do they do it?
As suggested in the links shared by you, it is not possible to correctly identify the DOM element in all the cases. However, there are couple of different approaches that can be used.
1) One is to ask merchant to add some specific element to markup that you can later use for rendering your content via JavaScript.
2) Try to guess the DOM element via some specific tag or href value, but allow merchants to override the DOM element selector via some JavaScript variable.
3) Use approach 2 with a combination of pre-determined info. Saw this approach used by AfterPay. They have a pre-defined array of popular themes along with their selectors. Then they use the theme name property from Shopify.theme.name
and get the relevant selectors. This solution may not work in all cases, so do allow the merchant to override DOM selector via some JavaScript variable.
Afterpay.supportedThemes = {
alchemy: {
product: {
"2017-12-14": {
selector: ".quadd-wrapper"
}
}
}
}
AfterPay JS Source Code
If you know of any other plugins, you can inspect the JavaScript and have a look how they identify the selectors.
I'm currently building an event table that will feature a "share" button. Once the user clicks on the share button I want to find text value from that particular table and store them in a variable so that I can use them in my next step. Basicly when I click the share button I want to find the parent element that wraps the particular table and then find text values from each particular cell and store that in a variable. In my JSFiddle I have setup to display the results in the resultbox. http://jsfiddle.net/Ak84L/5/
$("#shareButt").click(function(){
var date = $(this).parent('.even_table').find('date').text();
$(".resultbox").text("date"+date);
});
First change shareButt and date to values of class attribute instead of id, because IDs have to be unique.
And use this code:
$(".shareButt").click(function () {
var date = $(this).closest('.event_table').find('.date').text();
$(".resultbox").text("date" + date);
});
DEMO
First DON'T use same id. Use class instead. Go this way:
js
$(".shareButt").click(function(){
var date = $(this).parents(".event_table").find(".date").text();
$(".resultbox").text("date"+date);
});
fiddle
it would be much simpler to append a custom data tag to the element than to muck around with artsy fartsy jquery calls.
If its good enough for major web frameworks like angular.js, jade, bootstrap, etc. why do many people continue to attempt to reinvent the wheel to create the most complicated solution.
JS FIDDLE EXAMPLE
HTML
<div class="shareButt" date-data="12.5.2014">SHARE</div></td>
jQuery
$(".shareButt").click(function(){
$('.resultbox').text('date' + $(this).attr('date-data'));
});
I don't consider myself a professional by any means. I decided to spend this summer picking up a few web languages that would allow me to prototype my ideas (I am a designer).
To get with the question, I am having a tough time figuring out how to manipulate elements that I am echoing back from an external .php script. Essentially I am doing this.
process_feed.php:
- Gets data, does SQL search based on data, outputs rows
while ($row = mysql_fetch_assoc($feedResult))
{
$ctime = date("U",strtotime($row['timestamp']));
echo '<div id="secretmsg">'.$row['secretmsg'].'</br>';
echo '<div id="postedby">Posted By: '.$row['postedby'].'</div>';
echo '<div id="timestamp">'.ago($ctime).'</div><button type ="button" name="'.$row['m_id'].'">Reply</button></div>';
}
main page:
function RefreshFeed()
{
var SchoolName = document.getElementById('schoolname').innerHTML;
$.post('../../process_feed.php', {name: SchoolName}, processResponse);
function processResponse(data) {
$('.secretfeed').html(data);
}
}
Perhaps not the best solution, but I have RefreshFeed on an interval so I can constantly get updated information.
The issue is this: I am trying to work on a comment system where users can respond to each post. On my process page, I am adding a Reply button with the name set to the ID in the database. I am trying to setup basic functionality where the Reply button will open up a text input for commenting, send the message to the DB based on the ID, etc etc. However, on my main page I am not able to manipulate the element because it's being echoed? What can I change in order to echo information from the database onto my main page, and then from my main page manipulate the echoed div's.
I hope this makes sense - thanks for the help :)
If I understand you correctly then you would like to modify the DOM once the data has been added - so you can then just use a selector to get the desired element and do what ever you want - e.g.:
function processResponse(data) {
// Selector to get all elements by class name within the whole document
$('.secretfeed').html(data);
// Selector to get all buttons by tag name inside $('.secretfeed')
$('.secretfeed').find('button').text('foo');
// Selector to get all buttons by attribute inside $('.secretfeed')
$('.secretfeed').find('[type="button"]').text('bar');
// Selector to get the element with the given id within the whole document
$('#secretmsg').css('color', '#ff0000');
}
Notes:
Ids for HTML elements should always be unique within the whole document! In your example you possibly echo multiple elements with the same id (as it is inside a while loop) - use class="" instead.
It is recommended to save selectors so that jQuery does not need to parse the DOM over and over again - e.g.:
var $myselector = $('.myclass');
$myselector.text('foo');
But keep in mind that the selector is not updated when you modify the DOM by e.g. adding another element with class="myclass" - you would then need to assign the variable again so the selector contains the newly inserted element as well.
Additionally be sure that the DOM is ready when you want to work on it - regarding your callback processResponse this will always be the case as jQuery takes care of it and does not execute the callback until it is ready - but when you come from a page reload wrap your code like this:
var $myselector = $();
$(document).ready(function(){
$myselector = $('.myclass');
});
Additional info:
Finally (out of the scope of your question) take a look at event delegation so that you do not need to select all elements directly - e.g. if you want to add a click handler to all of your buttons you do not need to register an event handler for each but can create a global one:
$(document).on('click', '.secretfeed button', function(){
alert($(this).attr('name'));
});
I'm working with on developing one of the social networking site and its having some notification features in left panel.
Whenever any user have played a game it will automatically change the number of notification count.
For that i have using below code line.
jQuery('#count_id').load('mypage.php');
But it will retrieve me whole site content with header,footer and content area in the response text, which is wrong as per my requirements.
but if i used below code of line
jQuery('#count_id').load('mypage.php #count_id');
then it will retrieve me a real count but add another div in between the original,
Original html:
<div id="count_id" class="notify">2</div>
and Code after retrieving response:
<div id="count_id" class="notify">
<div id="count_id" class="notify">1</div>
</div>
which is also not as expected. count are right but i don't want to add new div inside a original one.
What should i need to change in my code?
Thanks.
jQuery('#count_id').load('mypage.php #count_id > *');
That would bring only the DOM childs (the content)
Because this is how it works. Also it enables you to attach events to the element you load and delegate them inside this element (so new elements can also benefit from attached JavaScript events) - see .delegate().
If you want to replace the element, you can try the following:
jQuery.get('mypage.php', function(data){
jQuery('#count_id').replace(jQuery(data).find('#count_id'));
}, 'html');
I did not test it, but it should work.
Ivan Castellanos is however right. According to the documentation, you can provide any selector after the first space in the .load()'s parameter.
To retrieve count_id, you can directly get the html value in the div like this:
<script type='text/javascript'>
jQuery(document).ready(function()
{
countVal = $("#count_id").html(); //returns the html content inside the div, which is the count value
countVal = parseInt(countVal); //This will convert the string to type integer
});
</script>
Note:
If you want increase the count and update the div value, you can add the following lines:
countVal++;
$("#count_id").html(countVal);
I am building app with php and jquery and it has many ajax loads and functionalities. What i would like to know is what is the most widely used and acceptable way of accessing dom elements with jquery and adding events to it using jquery and javascript and if there is any rule of thumb to follow for the following instances.(and how i do them now)
A query generates a list of records and each record has to be edited and deleted.
The generated records look like this
Record1
Record1
Record2
Record2
Record3
Record3
and my jquery code handle them would be
$(".edit").click(function() {
var currentElementId = $(this).attr("id").replace("edit-id-","");
$("#ajaxdiv").load("ajaxpage.php","editid="+currentElementId);
});
is this type of stuff ok? i mean is there any other way to do stuff like this especially when this gets more complicated like have to add 3 more identifiers to id and then exploding them and finding out each of the identifiers separately. Any guidelines here to follow.?
If you simply need to have something that can be cleaner, maybe you can consider bind the record into one
meaningful div, and use .live() to bind the event handlers
i.e.,
<div data-rec-id = '300'>
...
<span class='link del' data-act='del'>Delete</span>
<span class='link edit' data-act='edit'>Edit</span>
</div>
<div data-rec-id = '301'>
...
<span class='link del' data-act='del'>Delete</span>
<span class='link edit' data-act='edit'>Edit</span>
</div>
$('.edit').live('click', function(){
var id = $(this).closest('[data-rec-id]').attr('data-rec-id');
$("#ajaxdiv").load("ajaxpage.php","editid="+id);
});
or even generic:
$('.link').live('click', function(){
var id = $(this).closest('[data-rec-id]').attr('data-rec-id');
var action = $(this).attr('data-act');
$("#ajaxdiv").load("ajaxpage.php","id="+id+"&act="+action);
});
Please don't use something like:
<a href="javascript:;" ...
or I would suggest you use some robust framework. e.g., http://documentcloud.github.com/backbone/
I think the way you've done it is acceptable. You're mostly concerned about manually doing string processing to fetch the element ID? That is a little messy but not too bad.
If you don't want to do it that way, you might consider attaching a separate event handler to each a element when you create them, and have that event handler know the ID as a closure variable. But that will consume more memory, so it will depend on how many of those links you have.
I've found using using the web server to server up static web pages with the only dynamic content being json passed back and forth, is the best overall approach. We post JSON, and get JSON back from the server. This is used to design the page. This makes the web server become a data communication rather than heavy lifting the page constructing. This also add the ability for an API structure you can give out to ppl and they can write apps for it. For example, the web site and the mobile application use the same API interface.