JavaScript /Jquery : A for loop function with some special usage - javascript

This application have 2 components, a HTML page which contain some element and a JavaScript to generate buttons.
I will try to give out a simplify example in the question for now, but if there's something unclear then i would upload the full code later.
I am using HandleBar.js to generate different contents in the html but don't worry if you don't have any idea about this plugin i will make another non-handlebar.js version.
Consider the Html part looks like below:
HandleBar.js version
//example:
//{{feedId}} = 0t454g465754754h456
//{{url}} = www.jegdo.co.uk
{{each}}
<div class="feedIdChecker">{{feedId}}</div>
<div class="{{feedId}}-EditRegionUrl" >{{url}}</div>
<button class="output-{{feedId}}">Output</button>
{{/each}}
Then i have a JQuery function which would output the url
var feedId = $(".feedIdChecker").html();
$('".output-'+feedId+'"').click(function(){
var postUrl = $('".'+feedId+'-EditRegionUrl"').html();
console.log(postUrl );
});
});
}
I found there's no way to identify which button is which. Since i need to declare the var feedID outside the button, it would always get the first feedID it founds and append to all buttons, how may i solve it? Please tell me if this question is confuse, i will try to explain it in a better way.
There's lots of people trying to help me but it seem i need to give out some more details in order for better understanding:
Javascript:
var initRegionEdit = function(){
var feedId = $(".feedIdChecker").html();
$(".CTHK").click(function(){
var postUrl = ($(this).prev('div').html());
})
}
HTML
<div class="EditRegionUrl" >{{url}}</div>
<div class="feedIdChecker">{{feedId}}</div>
{{#if region}}
<span class="dropdown"><i class="fa fa-map-marker" aria-hidden="true" style="color:gray;"></i>
<span class="result-date result-date-region" type="button" data-toggle="dropdown">{{region}}
<span class="caret"></span></span>
<ul class="dropdown-menu" style="min-width:100px;text-align:center;">
<li class="CTHK" data-url="{{url}}" style=" margin-top: 0px !important;margin-bottom: 0px !important;">Hong Kong</li><div class="divider"></div>
<li class="CTTW" style=" margin-top: 0px !important;margin-bottom: 0px !important;">Taiwan</li><div class="divider"></div>
</ul>
</span>
{{/if}}
I wish above information can help

So when you select $(".feedIdChecker") you actually get an array of all matching elements, but as soon as you call .html it only gets you the first. So to solve your issue we need to loop over all the $(".feedIdChecker")s like so:
$(".feedIdChecker").each(function(i, e) {
var feedID = $(e).html();
$('.output-'+feedID).click(function(){
var postUrl = $("." + feedID + "-EditRegionUrl").html();
console.log(postUrl);
});
});
This will attach the click handler to each of the buttons.

You could use the handlebars.js each/index feature to do this:
<button id="whatever-{{#index}}"
class="output-{{feedId}}">
Output
</button>
I'm assuming you need an answer on how to apply a unique id to each button, not how to bind click handlers to them (which other people have answered anyway)

May this version be quicker and with less code.
$('[class*=output-]').click(function() {
var feedId = this.className.split("-")[1];
var postUrl = $('.EditRegionUrl-' + feedId).html();
alert(postUrl);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="feedIdChecker">1</div>
<div class="EditRegionUrl-1" >URL1</div>
<button class="output-1">Output1</button>
<div class="feedIdChecker">2</div>
<div class="EditRegionUrl-2" >URL2</div>
<button class="output-2">Output2</button>

Can you just put url in the button and a generic class:
<button class="output-{{feedId}} btn-class" data-url="{{url}}">Output</button>
and then
$('.btn-class').click(function(){
console.log($(this).data('url') );
});
Or even just without changing your markup at all
$("button").click(function(){
console.log($(this).prev('div').text());
});

Related

JSP Javascript get id from hidden input in foreach JSTL

I have a problem here: I want to get the ID of commentUserId in the hidden input into the javascript file to put into an ajax. But all I got was the value of the first row.
This is the design code
<c:forEach items="${commentList}" var="items">
<div class="media" style="padding: 10px 0">
<div class="media-body">
<input type="hidden" id="commentUserId" name="commentUserId" value="${items.accountId.accountId}"/>
<a id="${items.commentId}" name="btnReportComment" class="btn btn-report">\Report</a>
</div>
</div>
and this is code in javascript
$('a[name=btnReportComment]').click(function() {
var commentUserId = $('#commentUserId').val();
alert(commentUserId);})
Try to update your click event like:
$('a[name=btnReportComment]').click(function() {
var commentUserId = $(this).closest('.media-body').find('[name="commentUserId"]').val();
alert(commentUserId);
})
Here, we are using this to get the reference of click btnReportComment.
Then we find the commentUserId input w.r.t to it using closest & find.

Dynamic binding of li items click event

I have durandal and knockout web application.
I have a html as follows:
<ul id="header">
</ul>
In .js function I am adding li dynamically as:
$("#header).append('<li id="btn"> <span class="name">Test</span></li>')
ko.applyBindingsToNode(ul);
I am aware of the fact that I am binding the li after applyBindings has been called. To add it dynamically I am using
ko.applyBindingsToNode(ul); , but still no luck.
Can anyone please tell me whats the syntax/alternative solution for this?
// begins a JavaScript comment. This means that everything after <a href="javascript: is commented out, and the resulting code will look something like this:
$("#header).append('<li id="btn"><a href="javascript:
ko.applyBindingsToNode(ul);
Furthermore, the ko.applyBindingsToNode call will be part of the ' string opened just after the opening brackets on the append call.
To resolve this, you need to escape those comments by placing backslashes before them:
href="javascript:\/\/"
Refer to the demo here.
Please find the code below:
HTML:
<ul id="header">
</ul>
JS:
$(function() {
$("#header").append('<li id="btn">' + ' <span class="name">Test</span></li>');
//ko.applyBindingsToNode(ul);
});
using foreach:
var DemoPage = (function() {
function DemoPage() {
var _this = this;
_this.buttons = ko.observableArray([]);
_this.debug = ko.observable('');
_this.testmethod = function(data, event) {
_this.debug('Clicked LI: ' + data.buttonId);
}
_this.addHeadingRow = function() {
_this.buttons.push({
buttonId: Math.floor(Math.random() * 100)
});
}
}
return DemoPage;
})();
var demoApp = new DemoPage();
ko.applyBindings(demoApp);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul id="header" data-bind="foreach: buttons">
<li id="btn">
<a data-bind="click: $root.testmethod">
<span class="name">Test</span>
</a>
</li>
</ul>
<button data-bind="click: addHeadingRow">add heading row</button>
<p data-bind="text: debug"></p>
I would like to answer my own question.
The solution is very simple .
In the .js file define an observable array
self.arraysample = ko.observableArray([]);
In a method populate the array with data
self.arraysample.push(data)
In the html page , we can do this:
<ul id="head" data-bind:"foeach:arraysample">
<li>
<a id="btn">
<span data-bind="text:$data.arrayelement"></span>
</a>
</li>
</ul>
Thats it whenevr the data in the "self.arraysample" changes, automatic updating will take place because of knockout js properties.
I hope it helps someone because ,I have seen so many examples in the web advising to use ko.applyBindings() once again which doesnt work at all.

Issues with find() when inserting html dynamically using jquery

I have a modal with a grid of buttons representing different html components. When one of the buttons is pressed, some html is supposed to be injected into the page once the modal closes. However, I'm having trouble targeting the specific column where the html is to be injected. Here's my code:
<div class="row" id="newRow">
<div class="col-md-12 column">
<button class="btn addElement" href="#" data-toggle="modal" data-target="#add-element"><i class="fa fa-plus fa-3x add-item"></i></button>
</div>
</div>
And in my js file I have some code to assign an id to the column div (since there could potentially be many columns with this addElement button) that looks like this:
...
$(this).parent().next().children().find('.column').assignId();
...
Up to this point, everything works well. I'm having no trouble getting the column a unique id (defined in my assignId() function).
As I mentioned, the addElement button gets clicked, opening a modal which is when this code is executed:
$(document).on('click', 'button.addElement', function (e) {
e.preventDefault();
$('#add-element').modal('show').draggable();
var col = $('button.addElement').parent();
// debugging in the browser verifies that the colId
// successfully stores the id attribute for the column
var colId = col.attr('id');
addElements(colId);
});
...
function addElements(colId) {
$('#insert-paragraph').on('click', function () {
var html_content = '<div class="box" data-type="paragraph">...</div>';
$("#newRow").find("#"+colId).html(html_content)
$('#add-element').modal('hide');
});
}
It's on this line: $("#newRow").find(colId).html(html_content); that I'm having the issue. My guess is that the formatting for find(...) is wrong and that I can't just insert a variable like that, but I've tried a few different things and nothing seems to be working.
Any help is very much appreciated.
Thanks!
UPDATE:
#juvian suggested writing a few of the variables' values to the console:
console.log(colId);
console.log($("#newRow")).length;
console.log($("#newRow").find("#"+colId).length);
console.log($("#newRow").find("#"+colId).html());
I logged these values twice. First, just before passing colId into the addElements function and in the addElements function immediately after $(#newRow").find("#"+colId).html(html_content); The results of those two tests are as follows:
Values prior to running addElements:
console.log(colId); = 8153-1076-641d-3840
console.log($("#newRow")).length; = Object[div#newRow.row.clearfix]
console.log($("#newRow").find("#"+colId).length); = 1
console.log($("#newRow").find("#"+colId).html()); = <button class="btn addElement"...>...</button>
Values after the insert-paragraph button is pressed:
console.log(colId); = 8153-1076-641d-3840
console.log($("#newRow")).length; = Object[div#newRow.row.clearfix]
console.log($("#newRow").find("#"+colId).length); = 1
console.log($("#newRow").find("#"+colId).html()); = <div class="box box-element" data-type="paragraph">...</div>
Interestingly enough, it appears like everything is working like I'd expect it to, however, when it's all said and done, the addElement button remains and the page still renders this:
<div id="newRow" class="row clearfix">
<div id="32aa-ab91-f50d-c3b3" class="col-md-12 column ui-sortable">
<button class="btn addElement" data-target="#add-element" data-toggle="modal" href="#">
<i class="fa fa-plus fa-3x add-item"></i>
</button>
</div>
</div>
.find as most jquery functions, takes a css selector as parametre. Unfortunately, colId is just a string, so it matches no elements (unless colId is html, span or something like that)
You are just missing adding the id selector at the beginning to do an id match:
.find("#"+colId)
I guess The parent of button is a div here which has no id.
var col = $('button.addElement').parent();
thus var colId is getting no value.give that div an id and it should be fine.

Checking div.contents() for presence of another div

I have a piece of javascript which allows for the selection of multiple choices. An example of the html is this:
Pick an option:
<br><br>
<div id="dialogue_container"> </div>
<div id="Append"> And then this happens.</div>
<div class="inlinechoice-0" id="0">
<a class="question" id="1">Choice 1</a><br>
<a class="question" id="2">Choice 2</a><br>
<a class="question" id="3">Choice 3</a>
</div>
<div class="answer-1">
You picked 1.
<div class="inlinechoice-1" id="1">
<a class="question" id="4">Choice 4</a><br>
<a class="question" id="5">Choice 5</a><br>
</div>
</div>
<div class="answer-2">
You picked 2.
</div>
<div class="answer-3">
You picked 3.
</div>
<div class="answer-4">
You picked 4.
<div class="inlinechoice-2" id="2">
<a class="question" id="6">Choice 6</a><br>
<a class="question" id="2">Choice 7 (2)</a><br>
</div>
</div>
<div class="answer-5">
You picked 5.
</div>
<div class="answer-6">
You picked 6.
</div>
<br><br>
<FORM>
<INPUT TYPE="button" onClick="history.go(0)" VALUE="Refresh">
</FORM>
Then I have some javascript here:
$('div[class*=inlinechoice').on('click','.question', function(e) {
var $this = $(this),
$id = $this.prop('id');
$("#dialogue_container").append($('.answer-' + $id).contents());
});
$('div[class*=inlinechoice').on('click', function(a) {
var $this = $(this),
$cid = $this.prop('id');
$('.inlinechoice-' + $cid).hide();
});
And then a little bit of CSS here:
div[class*='inlinechoice-'] { cursor: pointer; }
div[class*='answer-'] {display:none}
div[class*='append']{display:none}
The way it works is that all of the inlinechoice/answerclass/append class begin as hidden. As the user clicks the options, the javascript puts the appropriate answers into the dialogue_container div in the order that they are selected. However, I would like to add a final touch, and that is to show the contents of the append div once there are no more choices available to the user. I need to check the contents of the dialogue_container to see if there are any active inlinechoices(i.e. non hidden ones), and if there are none, then I can set the append div to be shown. I'm thinking the solution will be something like suggested here, but I'm not sure how to apply this to the contents of the dialogue container, as they are dynamic.
Thanks.
Codepen here
Edit: New Codepen here. I've added the following code to the first question onclick event and it's appending correctly to choices which have no nested choices (i.e. choices 2 and 3) in them, but not choice 1 (which has additional questions). I think rather than searching the entire contents of #dialogue_container, I need to just look at the contents of the last select #answer, however, this is proving a bit tricky.
$foo = $("#dialogue_container").append($('.answer-' + $id).contents());
$str = $foo.html();
$term = "question";
$index = $str.indexOf($term);
if($index != -1){
//Do Nothing
}
else{
$('#append').show();
}
Edit: Is there a particular reason why this works:
$foo = $("#dialogue_container").append($('.answer-' + $id).contents());
But this doesn't?
$('.answer-' + $id).contents();
I'm guessing it's something to do with using .contents() combined with a class rather than a div, but I'm not sure how to instruct the script to return just the contents of the last clicked answer class.
If I add the following in, I can get an alert to return the correct contents, but I don't want to hardcode the answer-id class like this:
alert($('[class*="answer-2"]').eq(0).html());
I've tried:
alert($('[class*="answer-"]' + $id).eq(0).html());
To try and pick up the correct answer class, but it doesn't return anything. I feel like I'm nearly there on this, but not quite!
Edit: Thanks to a little clarification here, I finally managed to figure this out! I'll add the answer below.
Missing ] in your attribute selector
$('div[class*=inlinechoice]').on('click', '.question', function(e) {
// -----^-----
var $this = $(this),
$id = $this.prop('id');
$("#dialogue_container").append($('.answer-' + $id).contents());
});
$('div[class*=inlinechoice]').on('click', function(a) {
// -----^-----
var $this = $(this),
$cid = $this.prop('id');
$('.inlinechoice-' + $cid).hide();
});
CODEPEN
So it turns out that the order in which I called things mattered (you'd think I'd be able to figure something like this out by now).
Adding the following into the javascript right after $id variable has been defined seems to have done the trick:
//This is the append code which adds the contents of the append div when there are no more choices.
$str = $('.answer-' + $id).html();
$index = $str.indexOf("question");
if ($index != -1) {
//Do Nothing
} else {
$('#append').show();
}
Codepen

Dynamic div content + retain last viewed div on browser backward

I am using dynamic div content and toggling between them on clicks, works well but is there a way to retain the last viewed div when the user clicks forward and backward on his browser? Thanks.
<script>
$(".settings").click(function() {
var id = this.id;
if ($("." + $(this).attr('rel')).css('display') == 'none') {
$('.n_tab').hide();
$('.p_tab').hide();
($("." + $(this).attr('rel')).show());
}
});
</script>
<div class="settings" rel="n_tab">
<div class="title info_2_Title">
Notifications</div>
</div>
<div class="settings" rel="p_tab">
<div class="title info_2_Title">
Privacy</div>
</div>
<div id="MasterContainer">
<div class="n_tab" style="display: none;"> the N DIV </div>
<div class="p_tab" style="display: none;"> the P DIV </div>
</div>
Try using a library like history.js to set that up. Internally it will use the pushState API, or fall back to url fragments if the browser doesn't support that.
You could try adding an id to each tab and appending that in an object or array each time a div is selected.
Define an array history = []; outside the click event and in your click event something like
history.push($(this).id);
If you wanted to keep more detailed data you could use a json object and append to it.
Thanks for the help guys, but after fiddling ard with History.js, I still couldn't get it to work, in the end I used a cookie to store the state and then check it when the page with dynamic div loads.
$(function() {
var x = $.cookie('tab_cookie');
($(x).show());
if (x == '.m_tab') {
var btn = document.getElementById('<%= btnLoadm.ClientID %>');
if (btn) btn.click();
}
});

Categories