I have a couple of templates with some copy in them. The copy is editable by the user and when the user edits and saves (by clicking a button) I insert the edited copy along with all HTML tags (for later, when I print the data out again) in a db.
When I log the data it works but as soon as I try and write it to the db I get a 'too much recursion' error and I don't understand why.
// Event
Template.editControls.events({
'click .save': function(e) {
var target = e.currentTarget.parentNode;
var targetContent = target.nextElementSibling;
if(targetContent.isContentEditable) {
var targetData = targetContent;
var selectedCopy = Session.get('activeElement');
ContentCollection.update(selectedCopy, {$set: {content: targetData}});
targetContent.contentEditable = false;
}
}
});
// Template
<section class="content" id="header">
<ul class="inline-list">
<li class="edit">edit</li>
<li class="save">save</li>
</ul>
<div class="content__editable" contenteditable="false">
<p>Header content I can change</p>
</div>
</section>
Related
The view in my html is not getting filtered on selecting any li element.
But when I console the filter functions the output generated is correct.Also how to clear the filter so it is reusable again.I'm getting a blank page on clicking open or close select elements.Can anyone help me with this.
I have used two filters in a controller inside the functions like this-
indexController Functions-
this.UserTickets = ()=> {
//code to get the tickets
}
this.openTickets = () => {
index.filteredTickets = $filter('filter')(index.tickets, { status: "open" } );
console.log(index.filteredTickets);
};
//filter closed tickets
this.closeTickets = () => {
index.filteredTickets = $filter('filter')(index.tickets, { status: "close" } );
console.log(index.filteredTickets);
};
this.clearFilter = () => {
//clear the filter
};
HTML-
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li><a ng-click="indexCtrl.clearfilter()">None</a></li>
<li><a ng-click="indexCtrl.openTickets()">Open</a></li>
<li><a ng-click="indexCtrl.closeTickets()">Close</a></li>
</ul>
<div ng-repeat="ticket in indexCtrl.tickets | filter:tickets |filter:indexCtrl.filteredTickets">
<div class="ticket-no">
<h4>Ticket No:<span>{{ticket}}</span></h4>
</div>
<div class="ticket-title">
<a ng-href="/ticketView/{{ticket.ticketid}}"><h3>{{ticket.title}}</h3></a>
</div>
<div class="ticket-info">
<p class="pull-left">{{ticket.username}} On {{ticket.created | date:"MMM d, y h:mm a"}}</p>
<p class="pull-right">Status:<span>{{ticket.status}}</span></p>
</div>
<hr class="hr">
</div>
You are mixing both angular filter options. I would recommend the javascript filters, index.filteredTickets=$filter('filter')(index.tickets,{status:"open"}); rather than the html template syntax, ng-repeat="ticket in indexCtrl.tickets | filter:tickets...". The key difference between these methods is how often they are run. The html template syntax filters are run on every digest cycle, the javascript filters are only run when the method is called, in your case, on each button click. For small apps or when the lists are small, this difference won't be noticeable, but if your app grows in size, the constant filtering on each digest cycle can cause page lag.
The filters in the controller are my preferred way of handling this, so I will show you how to clean up your code for these to work. You are almost there, just a few small changes are needed.
In your html, you can remove the inline filters in the ng-repeat, these aren't needed, and change the array to be your filter list, index.filteredTickets.
.html
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li><a ng-click="indexCtrl.clearfilter()">None</a></li>
<li><a ng-click="indexCtrl.openTickets()">Open</a></li>
<li><a ng-click="indexCtrl.closeTickets()">Close</a></li>
</ul>
<div ng-repeat="ticket in indexCtrl.filteredTickets">
<div class="ticket-no">
<h4>Ticket No:<span>{{ticket}}</span></h4>
</div>
<div class="ticket-title">
<a ng-href="/ticketView/{{ticket.ticketid}}"><h3>{{ticket.title}}</h3></a>
</div>
<div class="ticket-info">
<p class="pull-left">{{ticket.username}} On {{ticket.created | date:"MMM d, y h:mm a"}}</p>
<p class="pull-right">Status:<span>{{ticket.status}}</span></p>
</div>
<hr class="hr">
</div>
For the javascript, you need to make sure the filteredTickets are accessible in the html. I'm not sure if index == this, if not, you may need to attach the filtered tickets to the scope. The one other change needed is to set the filteredTickets to your original list if the none button is pressed. You will also want to call clearFilter after you load the list, otherwise index.filteredList will be undefined/null.
.js
this.UserTickets = () => {
//code to get the tickets
....
//after getting list, call clear filter
this.clearFilter();
}
this.openTickets = () => {
index.filteredTickets = $filter('filter')(index.tickets, { status: "open" } );
console.log(index.filteredTickets);
};
//filter closed tickets
this.closeTickets = () => {
index.filteredTickets = $filter('filter')(index.tickets, { status: "close" } );
console.log(index.filteredTickets);
};
this.clearFilter = () => {
//clear the filter
index.filteredTickets = index.tickets;
};
could some one tell me, how to update accordion datas with new values on button click as when user enter their input?
assume like there is input box. user hit submit after giving value. at the same time it should show the input what user gives in side accordion.
accordion ll be categorized as
/Latest update
/old updates
/etc
what am having is
$("className").click(function(){
setInterval(function(){
}, 900);
})
<div classname="className"></div>
it would be better if share fiddle/plunker snippets for Typescript, Jquery or even Angular2
many thanks for any help
because i had some free time i made you an example of what i think you want.
1.enter 'aa' the latest updates will slideDown and have text 'aa'
2.enter second value 'bb' the latest updates will have text 'bb' , old updates will have text 'aa' and also 'aa' is archived
3.enter third value 'cc' the latest updates will have text 'cc', old updates will have text 'bb' and archive will have 'aa' and 'bb'
and so on.
this is made using IF conditions which are very straight forward using text().length.
also included ( at the beginning of the JQ ) a simple accordion code
let me know if this is what you were looking for. check snippet below or jsFiddle
var accTrigger = $('h2')
$(".text").hide()
$("h2").on("click", function() {
var text = $(this).siblings(".text")
if ($(text).is(":visible")) {
$(text).slideUp()
} else {
$(text).slideDown()
}
$(this).parents(".accordion-item").siblings().find(".text").slideUp()
});
var button = $("button"),
input = $("input"),
latest = $("#latest .text"),
old = $("#old .text"),
archive = $("#archive .text")
$(button).on("click", function() {
inputValue = $(input).val()
if ($(latest).text().length > 0) {
$(old).text($(latest).text()).slideDown()
}
if ($(old).text().length > 0) {
var aText = $(archive).html()
$(archive).html(aText + '<br>' + $(old).text()).slideDown()
}
$(latest).text(inputValue).slideDown()
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="accordion">
<div class="accordion-item" id="latest">
<h2>Latest Updates</h2>
<div class="text"></div>
</div>
<div class="accordion-item" id="old">
<h2>Old Updates</h2>
<div class="text"></div>
</div>
<div class="accordion-item" id="archive">
<h2>Archive</h2>
<div class="text"></div>
</div>
</div>
<input type="text" value="">
<button type="submit">
submit value
</button>
I am new to automated testing, Protractor, and angularJS. I have a list that I would like to count, copy to an array maybe, and verify the list text is present. For example The list shows Attractions, Capacity, and Content to the user so they know what privileges they have.
Below is the .html
<div class="home-info">
<div class="home-top home-section">
<h3>User Information</h3>
<div class="home-box">
<div class="property-group wide">
<span>
Change Phillips<br />
</span>
</div>
</div>
<div class="home-box">
<div class="property-group wide">
<div>Editors:</div>
<span>
<ul class="property-stack">
<li><span>Attractions</span>
</li>
<li><span>Capacity</span>
</li>
<li><span>Content</span>
</li>
<li><span>Media</span>
</li>
<li><span>Options</span>
</li>
<li></li>
<li></li>
<li><span>Upload CADs</span>
</li>
</ul>
</span>
</div>
</div>
</div>
Below is the code I have written. I can get the first item on the list however using .all isn't working for me.
var text = "";
browser.driver.findElement.all(By.xpath("//li/span")).count().then(function(count) {
initialCount = count;
console.log(initialCount);
});
browser.driver.findElement(By.xpath("//li/span")).getText().then(function(text) {
console.log(text);
});
I'm trying to avoid using xpath as I was told to try and avoid. To be honest Im lost. Thanks for the help in advance.
Code used for matching:
expect(myLists).toEqual(['Attractions', 'Capacity', 'Conent',
'Media', 'Options', 'Upload CADs'
]);
I am not sure what version of protractor you're using but you should be able to just call element without the browser or driver prefix. Using element.all should get you the array of of elements you're looking for.
If you want to access specific indexes within that array you can use the .get(index) suffix to the element.all
So below:
1. you get the array of the elements
2. you get the count of the array
3. we call a for loop to iterate through all the indexes of the array
4. each index of the array we call the getText() and print it to the console
var j = 0; // using this since the i iterator in the for loop doesn't work within a then function
var textList = [];
var text = "";
var myLists = element.all(by.css("li span"));
myLists.count().then(function(count) {
console.log(count);
for(int i = 0; i < count; i++){
myLists.get(i).getText().then(function(text) {
textList[j++] = text;
console.log(text);
});
}
});
EDIT:
In researching I actually found another way to iterate through the array of elements by using the .each() suffix to the element.all.
var j = 0; // using this since the i iterator in the for loop doesn't work within a then function
var textList = [];
var text = "";
var myLists = element.all(by.css("li span"));
myLists.count().then(function(count) {
console.log(count);
myLists.each(function(element, index) {
element.getText().then(function (text) {
textList[j++] = text;
console.log(index, text);
});
});
});
you should be able to use the textList array to match things.
expect(textList).toEqual(['Attractions', 'Capacity', 'Conent',
'Media', 'Options', 'Upload CADs'
]);
I have a javascript function which will read the device ContactList and add them into a javascript array.In my HTML page i have taken a listview.Now as per my requirement i have to add these array data into the listview by jquery dynamically which i am not able to do .I am not able to see anything on the screen of the mobile on launching the app..
Here is my javascript code to read from Mobile's contact list..
function onDeviceReady() {
// specify contact search criteria
var options = new ContactFindOptions();
options.filter=""; // empty search string returns all contacts
options.multiple=true; // return multiple results
filter = ["displayName"]; // return contact.displayName field
// find contacts
navigator.contacts.find(filter, onSuccess, onError, options);
}
var names = [];
// onSuccess: Get a snapshot of the current contacts
//
function onSuccess(contacts) {
for (var i=0; i<contacts.length; i++) {
if (contacts[i].displayName) { // many contacts don't have displayName
names.push(contacts[i].displayName);
}
}
alert('contacts loaded');
}
and here is my HTML listview..
<div data-role="page" id="home" data-theme="c">
<div data-role="content">
<div id="header" class="header">
<h1>Contact Directory</h1>
</div>
<ul data-role="listview" id="contactlist" data-theme="a">
</ul>
</div>
</div>
So, My question is how can i add the array values into the listview by jquery dynamically..
Thanks..
Couple of ways, but here is one way.
Create a simple string variable to hold your LIs.
Loop over names and append to the string <li> + names[x] + </li> where X is your loop counter.
Use jQuery to get the UL dom and then do .html(s) where s is your string.
Basically you are injecting <li>...</li><li>...</li> into your UL.
The last step is to refresh the list view so jQuery displays it correctly. This is done with the refresh API, defined here: http://api.jquerymobile.com/listview/#method-refresh
I use the following code and I would like to be able to get the ID attribute from the <li> (the post ID) that is associated with an <a> when it is clicked, but I cannot figure out how do do this. Is anybody able to help me at all?
<li id="custom_latest_news-5" class="widget custom_widget_latest_news">
<div class="widget-title">
Latest news
</div>
<div class="widget-content">
<ul class="link-list ajax-links">
<li id="post-5521">Last call for self-assessment tax forms</li>
<li id="post-5523">Young drivers gambling on no insurance</li>
<li id="post-5520">Tenants forced to abandon pets</li>
</ul>
</div>
</li>
Here is the JS that I currently have -
/**
* Intercept a click for page refresh and run the page refresh JS
*/
$(function(){
$('.ajax-links').delegate('li a', 'click', function(e){
/** Prevent the click from doing anything */
e.preventDefault();
/** Get the post ID */
var post_id = '???';
});
});
Thanks.
I believe you need
var post_id = $(this).parent().attr('id');
Example: http://jsfiddle.net/FwqGT/
You could use:
var post_id = $(this).parent().attr("id");
If you need to get the following (sibling) <li>, you could also do:
var next_id = $(this).parent().next().attr("id");
The li:s with the post ids in your markup are actually not siblings but parents.
This ought to do it:
var post_id = $(this).parent().attr('id'));