Populate list dynamically - javascript

Using jQuery FancyList from http://jquerywidgets.com/widgets/fancy-list/
I am trying to insert a <li> through code, not by a user click action.
My issue lies in the this keyword, specifically the following lines:
$(".fancy-list-footer .add").click( function() {
$('.tab-container .user-information .first-name:last').val('').removeClass('placeholder');
$('.tab-container .user-information .last-name:last').val('').removeClass('placeholder');
fancyList($(this));
});
I would like to be able to pass a first name and last name without having to populate the textboxes - a for loop will do this.
I tried changing the fancyList(elem) function to fancyList(elem, firstName, lastName) but I couldn't seem to get the correct value for elem - I tried var elem = document.getElementByClassName('fancy-list-footer') because I thought that's what the $(this) referred to in the button click, but this didn't work either.
Codepen: http://codepen.io/anon/pen/vEYaqa?editors=101
Any help appreciated!

You can make a function like so that will add a name:
function addToFancyList(first_name, last_name) {
$('.fancy-list').find(".fancy-list-content-list:last").append("<li><div class='person'><span class = 'first'>" + first_name + "</span><span class = 'last'>" + last_name + "</span></div><div class='clear'></div></li>");
}
And simply call it like so:
$(function () {
addToFancyList('Tom', 'Someone');
});

the answer relies in the function itself. here is the implementation of fancyList from the link you send:
function fancyList(elem) {
var this_parent = elem.parents(".fancy-list");
rel = this_parent.attr("rel");
var regex = /(<([^>]+)>)/ig;
first_name = this_parent.find(".fancy-list-footer input#fancy-list-first-name").val().replace(/[<\s]/g, "").replace(/[>\s]/g, "");
last_name = this_parent.find(".fancy-list-footer input#fancy-list-last-name").val().replace(/[<\s]/g, "").replace(/[>\s]/g, "");
// more lines of code...
but it can easly change to this:
function fancyList(elem, first_name, last_name ) {
var this_parent = elem.parents(".fancy-list");
rel = this_parent.attr("rel");
var regex = /(<([^>]+)>)/ig;
first_name = first_name .replace(/[<\s]/g, "").replace(/[>\s]/g, "");
last_name = last_name.replace(/[<\s]/g, "").replace(/[>\s]/g, "");
// more lines of code...
this way the function will better suit your needs and won't force you to generate elements just to get their textual values

Related

Change liferay-ui:input-localized XML with javascript

I have the following tag in my view.jsp:
<liferay-ui:input-localized id="message" name="message" xml="" />
And I know that I can set a XML and have a default value on my input localized. My problem is that I want to change this attribute with javascript. I am listening for some changes and call the function "update()" to update my information:
function update(index) {
var localizedInput= document.getElementById('message');
localizedInput.value = 'myXMLString';
}
Changing the value is only updating the currently selected language input (with the whole XML String). The XML String is correct, but I am not sure on how to update the XML for the input with javascript.
Is this possible?
PS: I have posted this in the Liferay Dev forum to try and reach more people.
After a week of studying the case and some tests, I think that I found a workaround for this. Not sure if this is the correct approach, but it is working for me so I will post my current solution for future reference.
After inspecting the HTML, I noticed that the Liferay-UI:input-localized tag creates an input tag by default, and then one more input tag for each language, each time you select a new language. Knowing that I created some functions with Javascript to help me update the inputs created from my liferay-ui:input-localized. Here is the relevant code:
function updateAnnouncementInformation(index) {
var announcement = announcements[index];
// the announcement['message'] is a XML String
updateInputLocalized('message', announcement['message']);
}
function updateInputLocalized(input, message) {
var inputId = '<portlet:namespace/>' + input;
var xml = $.parseXML(message);
var inputCurrent = document.getElementById(inputId);
var selectedLanguage = getSelectedLanguage(inputId);
var inputPT = document.getElementById(inputId + '_pt_PT');
inputPT.value = $(xml).find("Title[language-id='pt_PT']").text();
var inputEN = document.getElementById(inputId + '_en_US');
if (inputEN !== null) inputEN.value = $(xml).find("Title[language-id='en_US']").text();
else waitForElement(inputId + '_en_US', inputCurrent, inputId, xml);
var inputLabel = getInputLabel(inputId);
if (selectedLanguage == 'pt-PT') inputLabel.innerHTML = '';
else inputLabel.innerHTML = inputPT.value;
if (selectedLanguage == 'pt-PT') inputCurrent.value = inputPT.value;
else if (inputEN !== null) inputCurrent.value = inputEN.value;
else waitForElement(inputId + '_en_US', inputCurrent, inputId, xml);
}
function getSelectedLanguage(inputId) {
var languageContainer = document.getElementById('<portlet:namespace/>' + inputId + 'Menu');
return languageContainer.getElementsByClassName('btn-section')[0].innerHTML;
}
function getInputLabel(inputId) {
var boundingBoxContainer = document.getElementById(inputId + 'BoundingBox').parentElement;
return boundingBoxContainer.getElementsByClassName('form-text')[0];
}
function waitForElement(elementId, inputCurrent, inputId, xml) {
window.setTimeout(function() {
var element = document.getElementById(elementId);
if (element) elementCreated(element, inputCurrent, inputId, xml);
else waitForElement(elementId, inputCurrent, inputId, xml);
}, 500);
}
function elementCreated(inputEN, inputCurrent, inputId, xml) {
inputEN.value = $(xml).find("Title[language-id='en_US']").text();
var selectedLanguage = getSelectedLanguage(inputId);
if (selectedLanguage == 'en-US') inputCurrent.value = inputEN.value;
}
With this I am able to update the liferay-ui:input-localized inputs according to a pre-built XML String. I hope that someone finds this useful and if you have anything to add, please let me know!
To change the text value of an element, you must change the value of the elements's text node.
Example -
xmlDoc.getElementsByTagName("title")[0].childNodes[0].nodeValue = "new content"
Suppose "books.xml" is loaded into xmlDoc
Get the first child node of the element
Change the node value to "new content"

Find ID in String using match

I'm building a widget that will generate a graph for an element when it is double clicked on the page. Without remaking all widgets this is the only way for me to tackle the problem.
I want find the ID of a widget from the html of an element.
All widgets I want to work are inside a div element panel_content_id_#
I want to find the number found on the line of code
var io_id=32715;
How can I search the string for this pattern and get the number (32715).
$('div[id^="panel_content_id_"]').dblclick(function(e){
console.log($(this).attr('id'));
var code = $(this).html();
// Find ID
var id = -1;
var search = code.match("var io_id=");
if(search > -1){
}
console.log($(this).html());
});
The line of code im looking for will look like so
var io_id=xxxxx;
Where xxxxx = some random number I dont know
I want to find xxxxx
Split it in two parts - All the code before the var io_id= and the other part is after that.
And then you know that the line ends with ;, so from that second part you cut of the stuff that is before the semicolon.
CODE
$('div[id^="panel_content_id_"]').dblclick(function(e){
console.log($(this).attr('id'));
var code = $(this).html();
// Find ID
var id = -1;
if (code.indexOf("var io_id")>-1) {
id = parseInt(code.split("var io_id=")[1].split(";")[0]);
}
if(search > -1){
console.log("The code betrayed me");
}
console.log("The id is: " +id);
});
Maybe you could try this regex pattern:
\d+(?! var io_id=)
Used like this:
$('div[id^="panel_content_id_"]').dblclick(function(e) {
console.log($(this).attr('id'));
var code = $(this).html();
// Find ID
var id = -1;
var search = code.match("var io_id=");
if (search) { // Edited
// New code
alert(code.match(/\d+(?! var io_id=)/gim));
}
console.log($(this).html());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="panel_content_id_32715">
Div content
<br><br>
var io_id=32715;
</div>

Remove node function on parent element

I'm new to JS. I'm trying to delete the parent node with all the children by clicking a button. But the console tells me that undefined is not a function. What am I missing?
Fiddle:
http://jsfiddle.net/vy0d8bqt/
HTML:
<button type="button" id="output">Get contacts</button>
<button type="button" id="clear_contacts">clear contact</button>
<div id="output_here"></div>
JS:
// contact book, getting data from JSON and outputting via a button
// define a JSON structure
var contacts = {
"friends" :
[
{
"name" : "name1",
"surname" : "surname1"
},
{
"name" : "name2",
"surname" : "surname2"
}
]
};
//get button ID and id of div where content will be shown
var get_contacts_btn = document.getElementById("output");
var output = document.getElementById("output_here");
var clear = document.getElementById("clear_contacts");
var i;
// get length of JSON
var contacts_length = contacts.friends.length;
get_contacts_btn.addEventListener('click', function(){
//console.log("clicked");
for(i = 0; i < contacts_length; i++){
var data = contacts.friends[i];
var name = data.name;
var surname = data.surname;
output.style.display = 'block';
output.innerHTML += "<p> name: " + name + "| surname: " + surname + "</p>";
}
});
//get Children of output div to remove them on clear button
//get output to clear
output_to_clear = document.getElementById("output_here");
clear.addEventListener('click', function(){
output_to_clear.removeNode(true);
});
You should use remove() instead of removeNode()
http://jsfiddle.net/vy0d8bqt/1/
However, this also removes the output_to_clear node itself. You can use output_to_clear.innerHTML = '' if you like to just delete all content of the node, but not removing the node itself (so you can click 'get contacts' button again after clearing it)
http://jsfiddle.net/vy0d8bqt/3/
You want this for broad support:
output_to_clear.parentNode.removeChild(output_to_clear);
Or this in modern browsers only:
output_to_clear.remove();
But either way, make sure you don't try to remove it after it has already been removed. Since you're caching the reference, that could be an issue, so this may be safer:
if (output_to_clear.parentNode != null) {
output_to_clear.remove();
}
If you were hoping to empty its content, then do this:
while (output_to_clear.firstChild) {
output_to_clear.removeChild(output_to_clear.firstChild);
}
I think using jQuery's $.remove() is probably the best choice here. If you can't or don't want to use jQuery, The Mozilla docs for Node provides a function to remove all child nodes.
Element.prototype.removeAll = function () {
while (this.firstChild) { this.removeChild(this.firstChild); }
return this;
};
Which you would use like:
output_to_clear.removeAll();
For a one-off given the example provided:
while (output_to_clear.firstChild) { output_to_clear.removeChild(output_to_clear.firstChild); }

Hover over data using title attribute in javascript

I have a javascript code that displays data in a table format and when hovered over the first column it displays additional details. The hover over code is using jquery tooltip and the title attribute of html. The code works fine in most cases but if one of the fields I am displaying in the hover has " symbol it screws up everything that record onwards and the hover and main data display together and the hover doesnt work on those rows.
below is a snapshot of my code
var medicationName = medJSON.MED_DETAILS[medIdx1].ORDER_NAME;
var orderdetails = medJSON.MED_DETAILS[medIdx1].ORD_DETAILS;
var comments = medJSON.MED_DETAILS[medIdx1].ORD_COMMENTS;
var reqStart = medJSON.MED_DETAILS[medIdx1].REQ_ST_DT;
var originalStart = medJSON.MED_DETAILS[medIdx1].ORIG_ORD_DT;
var lastDose = medJSON.MED_DETAILS[medIdx1].LAST_DOSE;
var nextDose = medJSON.MED_DETAILS[medIdx1].NEXT_DOSE;
var stopDt = medJSON.MED_DETAILS[medIdx1].STOP_DT_TM;
var stopReason = medJSON.MED_DETAILS[medIdx1].STOP_REASON;
var enteredBy = medJSON.MED_DETAILS[medIdx1].ORDER_ENTERED_BY;
var status = medJSON.MED_DETAILS[medIdx1].ORD_STATUS;
var simpleDetails = medJSON.MED_DETAILS[medIdx1].CLIN_DISP_LN;
if(nextDose.length == 0)
{
nextDose = "Not Defined";
}
var medHover = ["<table><tr><td><b>Medication:</b></td><td>",medicationName,"</td></tr>"
,"<tr><td><b>Details:</b></td><td>",simpleDetails,"</td></tr>"
//,"<tr><td><b>Order Comments:</b></td><td>",comments,"</td></tr>"
,"<tr><td><b>Request Start:</b></td><td>",reqStart,"</td></tr>"
,"<tr><td width = 200px><b>Original Order Date/Time:</b></td><td>",originalStart,"</td></tr>"
,"<tr><td><b>Last Documented Dose:</b></td><td>",lastDose,"</td></tr>"
,"<tr><td><b>Next Scheduled Dose:</b></td><td>",nextDose,"</td></tr>"
,"<tr><td><b>Stop Date/Time:</b></td><td>",stopDt,"</td></tr>"
,"<tr><td><b>Stop Reason:</b></td><td>",stopReason,"</td></tr>"
,"<tr><td><b>Order Entered By:</b></td><td>",enteredBy,"</td></tr>"
,"<tr><td><b>Status:</b></td><td>",status,"</td></tr>"
,"</table>"]
tempStr1.push("<tr class = 'evenrow' ><td class = 'cmedname custhvr' title=\"",medHover.join(""),"\">",medicationName,"</td><td> ",simpleDetails,"</td></tr>")
thanks,
Sid
Process medHover with:
medHover.join("").replace('\"', '"');
This replaces the quote character with a value usable with HTML.

.clone doesn't not appear to be incrementing

this script is suppose to clone a new row of a HTML table. It does not seem to be incrementing the name, id, attributes. What am I doing wrong? The only other thing that is not working is get the value from the previous input id of #endtime_* and putting it in the cloned input id of #starttime_* although I think that is because it does seem to be incrementing as it clones a row.
<script type="text/javascript">
function MaskTime(){
var index = $("#TimeCard tbody>tr").length-1;
$('#endtime_'+index).mask("99:99 aa");
$('#starttime_'+index).mask("99:99 aa");
}
function update_rows(){
$("#TimeCard tbody>tr:odd").css("background-color", "#FFF");
$("#TimeCard tbody>tr:even").css("background-color", "#999");
}
$(document).ready(function() {
$("#addrow").click(function() {
var row = $('#TimeCard tbody>tr:last').clone(true).insertAfter('#TimeCard tbody>tr:last');
var index = $("#TimeCard tbody>tr").length-1;
var endvalue = $('#endtime_'+index-1).val();
$("td:eq(0) select").attr("name", 'type_'+index).attr("id", 'type_'+index).addClass("validate[required]").val('')
$("td:eq(1)").html(" ")
$("td:eq(2) select").attr("name", 'propid_'+index).attr("id", 'propid_'+index).addClass("validate[required]").val('')
$("td:eq(3)").html(" ")
$("td:eq(4) input").attr("name", 'starttime_'+index).attr("id", 'starttime_'+index).addClass("validate[required,custom[timeclock]]").val(endvalue)
$("td:eq(5) input").attr("name", 'endtime_'+index).attr("id", 'endtime_'+index).addClass("validate[required,custom[timeclock]]").val('')
$("td:eq(6)").html(" ")
update_rows();
MaskTime();
return false;
});
});
</script>
For the first part of your question:
It does not seem to be incrementing the name, id, attributes.
Your script isn't giving the proper context for where the tds are for which you want to modify the attribues, etc.
Here's a modification that corrects that, adding a new variable "newrow" (to reduce DOM calls) and modifying the lines of code related to td:eq(#)...
$(document).ready(function() {
$("#addrow").click(function() {
var row = $('#TimeCard tbody>tr:last').clone(true).insertAfter('#TimeCard tbody>tr:last');
var index = $("#TimeCard tbody>tr").length-1;
var endvalue = $('#endtime_'+index-1).val();
var newrow = $("#TimeCard tbody>tr:last");
newrow.children("td:eq(0)").children("select").attr("name", 'type_'+index).attr("id", 'type_'+index).addClass("validate[required]").val('')
newrow.children("td:eq(1)").html(" ")
newrow.children("td:eq(2)").children("select").attr("name", 'propid_'+index).attr("id", 'propid_'+index).addClass("validate[required]").val('')
newrow.children("td:eq(3)").html(" ")
newrow.children("td:eq(4)").children("input").attr("name", 'starttime_'+index).attr("id", 'starttime_'+index).addClass("validate[required,custom[timeclock]]").val(endvalue)
newrow.children("td:eq(5)").children("input").attr("name", 'endtime_'+index).attr("id", 'endtime_'+index).addClass("validate[required,custom[timeclock]]").val('')
newrow.children("td:eq(6)").html(" ")
update_rows();
MaskTime();
return false;
});
});
Also, I'd made a jsfiddle with the above: http://jsfiddle.net/m78UN/2/
I'm not following what you're wanting when you describe your second problem:
The only other thing that is not working is get the value from the previous input id of #endtime_* and putting it in the cloned input id of #starttime_*
...so I've not attempted to address that.
I think you can do everything you're doing in a way simpler way. I don't have your original HTML, but check this out as a possible alternative. It mainly does 3 things:
Removed IDs used for finding things
Caches selectors
Adds classes to time inputs to make them easier to reference
Removed MaskTime() function
Here's the code:
$(document).ready(function() {
var $timecard = $("#TimeCard");
var $tbody = $timecard.find("tbody");
var $rows = $tbody.children("tr");
$("#addrow").click(function(e) {
e.preventDefault(); // clearer than return false
var $lastRow = $tbody.find("tr:last-of-type");
var lastEnd = $lastRow.find(".endTime").val();
var $newRow = $lastRow.clone(true).appendTo($tbody);
var $cols = $newRow.find("td");
var index = $rows.length - 1;
$cols.eq(0).find("select").attr("name", 'type_' + index).addClass("validate[required]").val('');
$cols.eq(1).empty();
$cols.eq(2).find("select").attr("name", 'propid_' + index).addClass("validate[required]").val('');
$cols.eq(3).empty();
$cols.eq(4).find("input").attr("name", 'starttime_' + index).addClass("time startTime validate[required,custom[timeclock]]").val(lastEnd);
$cols.eq(5).find("input").attr("name", 'endtime_' + index).addClass("time endTime validate[required,custom[timeclock]]").val('');
$cols.eq(6).empty();
update_rows(); // no idea what this is
$newRow.find(".time").mask("99:99 aa"); // MaskTime() just did this
});
});

Categories

Resources