I have a chat room style application and each entry is processed on the client once it is received and then some html is generated to display it. As certain messages will have tooltips and other bits of data embedded within them which use knockout bindings to display.
Now after looking over all the posts around this the answers to this problem seem to be:
Make sure all your elements exist up front but are empty
Call ko.applyBindings on the new elements when they are added
The first one is not feasible as you only create the elements as the chat comes in from the server, so the second option seems the only way to do it, however this would require calling for each chat message that comes in. A lot of people say that ko.applyBindings can incur significant overheads, however I think they mean if you were to call it upon all elements rather than just targeting specific ones.
Just so that everyone is on the same page, here is the basic snippet of the view around the area that matters:
<!-- ko foreach: {data: ChatRoom.Entries, afterRender: ChatEntryRendered } -->
<div class="entry-content" data-bind="html: ProcessedContent"></div>
<!-- /ko -->
Ignoring the bits around that, it will basically loop around each entry, add a div which will contain html which will contain bindings which need knockout goodness applied. So for example the ProcessedContent could look something like:
<span>Some content with a <span data-bind="tooltip: 'Some Content Here'">DYNAMIC</span> bit of <span class="special-text">Content</span></span>
So this above html would not currently be processed by the foreach as it is dynamically applied to the page, and before everyone starts freaking out about injecting html into the views, the server does not send down any markup, it just sends down a string with a load of tokens which the client converts into html. Also without muddying the waters too much, in this scenario the ChatRoom.Entries object is culled every now and again so it will fluctuate from 0-200 (usually 100-200) entries at any given time and the rest of the chat entries are cached in local storage, just so there are never more than about 150 bound Entries to the view at any given time.
Here is a jsfiddle showing the issue in a practical example.
http://jsfiddle.net/Mps4Q/8/
The main reason that the html binding doesn't bind the inserted html is because it can be unsafe. But if you know it's safe, you can use a custom binding that does bind the contents. Here's an example from another SO question: https://stackoverflow.com/a/17756777/1287183
Fiddle: http://jsfiddle.net/Mps4Q/9/
Related
Presently, I am using a script to show/hide comments on a number of WordPress-based sites. The script works as expected on essentially every site. However, I've run into an issue with a site using the Hero theme. On the index pages, the theme pulls the content from X number of posts. Unfortunately, this has the effect of calling the script multiple times and resulting in the first post getting X number of show/hide buttons and the other posts being unaffected.
I'm uncertain as to how to modify the script in order to target each of the comment sections individually. Naturally, the task would be easier if the theme author had not assigned all comment sections on index pages the same id (#commentBox). I've looked at limiting the scope of the script (i.e., to have each instance of the script affect only the post content within which it's contained) and changing the actual functionality of the script to account for the multiple comment sections. Unfortunately, I've not yet been able to get it working as intended.
Here is a link an index page displaying the issue: http://www.sitestyling.ca/abbyphotography/blog/. The first link (i.e., the one to the script) leads to a page which has the script implemented and functioning as expected.
Any help or suggestions would be greatly appreciated.
So to state the obvious here, having multiple elements with the same ID is very bad mojo. To whatever extent that you can control how these WP sites are loaded I would encourage you to work to modify the repeated injection of your script into the page since even after making a change, your script would be run repeatedly since you have multiple blocks defining document.ready functions. You could ameliorate that with a global to tell if your script had already fired but that's getting a bit hackish...
What I would suggest in principle is that you add logic to your script to do the following:
Find the offending duplicate ID items and rename them to something unique
Add a class that you can reference rather than an ID
Refactor your code to loop through the collection of items returned from the class selector
If really, really necessary you could also then have kept track of your renamed IDs, go retrieve them individually and reset them to the offending original duplicate ID name thus incriminating yourself for future page user
The first couple of points here could be done pretty simply with something like this:
var uniqueAppend = 1;
var tempName = 'commentBox';
while(jQuery("#commentBox").length > 0 ){
jQuery("#commentBox").attr('id',tempName + uniqueAppend++).addClass('commentContainer')
}
Now you can find all your comment DIVs at once with jQuery(".commentContainer") and then iterate through that collection to take whatever actions you need.
I have a page in which almost all of the controls are created dynamically.
When I send the page I have no problem retrieving the data from those controls.
The problem comes when I have to retrieve the data of the "returns"(see buttons inside the blue frames), because since they are not inside any control I have to use an array to keep track of them.
This is the pop-up that is used to enter the returns for each expression (IF,ELSE IF,ELSE)
My question is, what would you do if you had to keep track of those returns??
Would you create an js array of returns for every expression(IF,ELSE IF,ELSE) knowing that you would have to create arrays of arrays since each structure can have several instructions,which in turn can have several expression, which in turn can have several returns?? What would you do to keep the solution as simple as possible, considering that the only thing I don't have inside controls is the returns.
At present I'm using the js array approach but , I have to do a lot of things so that when I remove a structure of all the returns associated with the expressions inside that structure, get removed too.
EDIT:
==============
The code I use to create all the controls in my page is too large to be posted it here, but here's an image showing the structure of the js array I use to store all the returns for each expresion(IF,ELSE IF,ELSE) and that I later submit as a json object.
Considering that structure, do you think it would be possible to simplified that structure so that while I am still editing the page I only have to have the returns in a array??
To make a long story short, I want to create the whole structure shown in the image just before I summit the form, NOT while I'm still editing the page.
Just a couple of extra things to consider:
structures : Structure #1,Structure #2
instructions: All the frames with a dropdown list showing "Multiple IF"
expressions : All the IF's,ELSE IF's and ELSE's
==============
P.S. I'm not asking for any working code, I only want to hear your suggestions of what you would you do if you had to deal with a situation like the one described above.
Use the form element's onsubmit event.
<form action="" onsubmit="this['returns'].value = createReturnsArray();">
<input type="hidden" name="returns" />
</form>
When the form is submitted, the function createReturnsArray is called and its return value send along with the form as returns. Of course, you would change all these things to suit your needs.
I am with affiliate programs that give you little forms to put on your website, but often times they're entirely composed of javascript (so, no HTML tags , ID's or classes are inside of them).
These probably pull in forms using AJAX. JS or JQuery cannot display page elements by themselves, for that they need HTML. What you can do is use the Chrome Developer Tools to find the IDs or classes in the form they load in, and then after the AJAX call edit the form from there.
If there's a form then it has to ultimately draw elements into the DOM for the page to render. There's always a way to get at those nodes if you really need to, but if they don't include IDs or names then you'll have to walk the tree and look for specific relationships based on what you see in the finished page. It will definitely be a PITA, but it's doable.
I've a question about best practices in javascript.
I've a dropdown menu with some statuts. If the statut is : external, I want to display a form. I don't know the best way to do this. Do i need to hide a DIV from the DOM and display him when i need it or do i need to generate my form dynamically in jquery and make a call ajax to populate some data.
It really depends on your application. If you already have a lot of elements in the DOM, and the likelyhood of actually needing to show this form is low, you may want to add it later (using ajax) because in most cases you don't need it anyway. However, if your DOM load is light, and in most cases the form will be shown, you make want to have it ready and hidden so that is can be quickly shown.
There is also a middle ground where you can "lazy load" it (using javascript on page load), and keep it in a json object until it is ready to be used. This will keep your DOM responsive, and give the added benefit of a quicker load of the form.
it depends on the probability of user clicking on that element and number of elements already present in the DOM. I suggest to create form runtime whenever user performs action instead of hiding it. There are some browser plugins which shows all hidden elements in a page.
Unless your page is unusually large already or there are a lot of different forms like this that could be used from the same page, putting the HTML into the page and just starting out with it hidden gives you the advantage that all your markup is in one place (in the HTML file that represents your page) and can more easily be centrally maintained that way.
When you start putting markup into your javascript, you split up the maintenance of the markup between both the HTML of the page and the HTML that is embedded into your page.
If, on the other hand, you had a lot of these forms that were all slightly different that could all be used from the same page, then it gets messy to pre-specify all possible combinations of the form in the original HTML and you would probably be better off dynamically generating it via javascript or perhaps generating it from a template with slight modifications.
I'm creating a form on a web page, but I want that form to change as a user inputs values.
Example: If we have a drop down menu: ObjectType
And someone chooses Cars when that selected I'd want new options below to show up. Say, Make, Model, Year, & Notes.
Whereas, if that person chooses Vegetables then maybe all I want is a checkbox for Root Vegetables.
My question is what is the best way to do this. My form is pretty intricate and is going to have perhaps 20 different possible set ups, but I want those set ups to be sorted. I used appendChild() with AJAX requests, but I just ended up with out of order fields. And on top of that, the occasional slow connection keeps an individual waiting for a field to show up.
Rather than loading HTML pages with these form objects (technically part of a table), should I be keeping all of this stuff in an array? Is it possible to just load one HTML page or XML object and use selectElementById() on that result after it has been saved?
The objects I'm loading are rows, here's an example of one and what it would need to be able to do:
<td>
<strong>Abilities:</strong>
</td>
<td>
<textarea
id ='abilities'
name="abilities"
style="width:100%" rows="4"
onchange='userCreation.updateAbilities()'
onkeyup='userCreation.updateAbilities()'>
</textarea>
</td>
I have a table in my page, I was creating a new tr element with JavaScript, setting this as the innerHTML and then appending the child. Is there a better way to do this?
I would just put all of the form elements in a page, and hide the ones you're not using with CSS. That way you maintain order, and don't have to wait for fields to show up. It will slightly slow down page load time, but make your life a lot simpler.
Otherwise, I'd store the name (or whatever) of each field in an array or object, and when it comes time to AJAX load it, look up its position first and put it there.
Just have the entire for in the page and just change the visibility of different sections, based on user interaction instead of dynamically loading elements via AJAX.