I have an array of users. Each user can be skipped on .click button. However I want it to skip the user that logs in. The session is started with PHP, but I'm showing the user through ajax and javascript. However
if(sSession = sKey){
aPeople.slice(this.jPerson);
}
is not correctly skipping the user. Could you help?
Here's the code:
$("#btnSkip").click(function() {
$.getJSON('include/users.txt', function(aPeople){
var getPerson = function(id) {
var jPerson = aPeople[id]
var sID = jPerson.id
var sName = jPerson.name
var sImage = jPerson.picture
var sSession = $('#mySession').text()
var sKey = jPerson.key
//this if statement doesn't work
if(sSession == sKey){
console.log(sSession)
console.log(sKey)
console.log(personIndex)
console.log(jPerson)
aPeople.splice(jPerson);
}
$('#sName').text(sName)
$('#sImg').attr('src', sImage)
//TO START COUNT AGAIN
if(aPeople.length -1 == personIndex){
personIndex = 0
}else{
personIndex = personIndex + 1
}
}
getPerson(personIndex);
$( '#sName' ).fadeIn( 'slow' )
$( '#sImg' ).fadeIn( 'slow' )
})
})
So, it looks to me like to you want to:
Retrieve an array of user objects.
Navigate the retrieved list and display each user on a button click.
Never display the logged in user.
Here's a suggested solution:
I'm filtering out the logged in user with the jQuery grep function.
I simplified your navigation logic.
I wasn't sure you meant to retrieve the users JSON on every click, so I altered that also.
function setupUserNavigator(users, loggedInUserKey) {
var idx = 0;
// filter out the logged in user
var filtered = $.grep(users, function(user) {
return !(user.key === loggedInUserKey);
});
function current() {
return filtered[idx];
}
function next() {
idx += 1;
}
function more() {
return idx < filtered.length - 1;
}
return { current, next, more };
}
function displayUser(user) {
$('#sName').text(user.name);
$('#sImg').attr('src', user.picture);
}
function usersResponseHandler(users) {
var loggedInUserKey = $('#mySession').text();
var userNavigator = setupUserNavigator(users, loggedInUserKey);
// display the first user immediately
displayUser(userNavigator.current());
// display each subsequent user on a 'next' button click
$('#next').click(function() {
userNavigator.next();
displayUser(userNavigator.current());
if(!userNavigator.more()) {
$(this).prop('disabled', true);
}
});
}
// $.getJSON('include/users.txt', usersResponseHandler);
// use test data for the snippet and mock response handler call
var data = [
{ id: '1', key: '1234', name: 'Joe', picture: 'img/joe.png' },
{ id: '2', key: '5678', name: 'John', picture: 'img/john.png' },
{ id: '3', key: '9012', name: 'Sarah', picture: 'img/sarah.png' },
{ id: '4', key: '0987', name: 'Tim', picture: 'img/tim.png' },
{ id: '5', key: '6543', name: 'Lily', picture: 'img/lily.png' }
];
usersResponseHandler(data);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Logged In User Key:
<div id="mySession">9012</div><br />
Name:
<div id="sName"></div>
Picture:
<div><img id="sImg" src="" /></div><br />
<button id="next">Next</button>
Related
I'm using Vue js to display and edit details of a person. The person being edited has a list of favourite colours that I want to display as a list of checkboxes. When I change the colours selected, and click the 'Update' button, the person object should be updated accordingly, so I can pass back to the api to update.
I've got as far as displaying the Person object's colours correctly against their respective checkboxes. But I'm struggling with passing the changes to the colour selection, back to the Person object. Below is my checkbox list and details of how I've tried to implement this. Is there a better way of doing this?
I've tried using 'b-form-checkbox-group'. Below is my code.
Please note - The list of available colours is dynamic, but I've temporarily hardcoded a list of colours ('colourData') till I get this working.
Also, in the 'UpdatePerson' method, I've commented out my attempts to get the selected colours mapped back to the Person object.
<template>
<form #submit.prevent="updatePerson">
<b-form-group label="Favourite colours:">
<b-form-checkbox-group id="favColours"
v-model="colourSelection"
:options="colourOptions"
value-field="item"
text-field="name">
</b-form-checkbox-group>
</b-form-group>
<div class="container-fluid">
<b-btn type="submit" variant="success">Save Record</b-btn>
</div>
</form>
</template>
<script>
import service from '#/api-services/colours.service'
export default {
name: 'EditPersonData',
data() {
return {
personData: {
personId: '',
firstName: '',
lastName: '',
colours:[]
},
colourData: [
{ colourId: '1', isEnabled: '1', name: 'Red' },
{ colourId: '2', isEnabled: '1', name: 'Green' },
{ colourId: '3', isEnabled: '1', name: 'Blue' },
],
selectedColours: [],
colourSelection: []
};
},
computed: {
colourOptions: function () {
return this.colourData.map(v => {
let options = {};
options.item = v.name;
options.name = v.name;
return options;
})
}
},
created() {
service.getById(this.$route.params.id).then((response) => {
this.personData = response.data;
this.colourSelection = response.data.colours.map(function (v) { return v.name; });
this.selectedColours = response.data.colours;
}).catch((error) => {
console.log(error.response.data);
});
},
methods: {
async updatePerson() {
//const cs = this.colourSelection;
//const cd = this.colourData.filter(function (elem) {
// if (cs.indexOf(elem.name) != -1) { return elem;}
//});
//this.personData.colours = [];
//this.personData.colours = cd;
service.update(this.$route.params.id, this.personData).then(() => {
this.personData = {};
}).catch((error) => {
console.log(error.response.data);
});
},
}
}
</script>
Any help wold be much appreciated.
Thanks
I got this working by making the below changes to the commented part in the 'updatePerson()' method:
methods: {
async updatePerson() {
const cs = this.colourSelection;
const cd = this.colourData.filter(function (elem) {
if (cs.some(item => item === elem.name)) { return elem; }
});
this.personData.colours = [];
this.personData.colours = cd;
service.update(this.$route.params.id, this.personData).then(() => {
this.personData = {};
}).catch((error) => {
console.log(error.response.data);
});
}
}
I have made a scheduled script which is sending PDF though email.send()
I have get the filters as params from Suitelet. I want to get the name of the user (from runtime.getCurrentUser) and pass it to my PDF. I m just confused how to pass them and will that API be used in Suitelet or Sched script.
Can anyone help me with the code?
Here is my Scheduled script code:
/**
* #NApiVersion 2.x
* #NScriptType scheduledscript
*/
define(['N/ui/serverWidget', 'N/search', 'N/render', 'N/runtime', 'N/file', 'N/email'],
function (ui, search, render, runtime, file, email) {
function execute() {
try {
generateReport();
}
catch (e) {
log.error('generateReport ERROR', e);
}
}
function generateReport() {
var slfilters = runtime.getCurrentScript().getParameter({ name: 'custscript_searchfilter_report' });
log.debug('slfilters', slfilters);
if (!!slfilters) {
slfilters = JSON.parse(slfilters);
}
log.debug('slfilters2', slfilters);
var user = runtime.getCurrentUser();//Need this user to be passed to my xml template
var gender = slfilters.gender;//getting this from Suitelet
log.debug('gender', gender);
var item = slfilters.item;//getting this from Suitelet
log.debug('item', item);
var item_ = getItems(item, gender);
log.debug('getItems(item, gender)', item_);
//return item;
var xmlTemplateFile = file.load(3918);
//var template = script.getParameter({ name: 'custscript_template' });
var renderer = render.create();
renderer.templateContent = xmlTemplateFile.getContents();
var customSources = {
alias: 'searchdata',
format: render.DataSource.JSON,
data: JSON.stringify({
value: item_,
})
};
renderer.addCustomDataSource(customSources);
var xml = renderer.renderAsString();
var pdf = render.xmlToPdf({
"xmlString": xml
});
email.send({
author: 317,
recipients: 'aniswtf#gmail.com',
subject: 'Item Report',
body: 'Report Generated: ',
attachments: [pdf]
});
}
//
// ─── GET RESULTS ───────────────────────────────────────────────────
//
const getResults = function (set) {
var results = [];
var i = 0;
while (true) {
var result = set.getRange({
"start": i,
"end": i + 1000
});
if (!result) break;
results = results.concat(result);
if (result.length < 1000) break;
i += 1000;
}
return results;
};
//
// ─── GET ITEMS ───────────────────────────────────────────────────
//
function getItems(item, gender,user) {
try {
log.error('getItems Function started');
var itemSearch = search.load({
id: 'customsearch_mx_itemsearch'
});
var defaultFilters = itemSearch.filters;
itemSearch.filters.push(
search.createFilter({
name: "custitem5",
operator: 'anyof',
values: gender
}),
search.createFilter({
name: "internalid",
operator: 'anyof',
values: item
})
);
//defaultFilters = arrFilters;
//defaultFilters = defaultFilters.concat(arrFilters);
//log.error('Updated Filters', defaultFilters)
log.error('itemSearch', itemSearch);
//return defaultFilters;
var results = itemSearch.run().getRange({
start: 0,
end: 150
});
var result2 = results.map(function (x) {
// var results = getResults(itemSearch.run()).map(function (x) {
return {
'category': x.getText({
name: "custitem10",
join: "parent"
}),
'season': x.getValue({
name: "custitem11",
join: "parent"
}),
'riselabel': x.getText({
name: "custitem_itemriselabel",
join: "parent"
}),
'fit': x.getText({
name: "custitem9",
join: "parent"
}),
'name': x.getText({ //sku
name: "itemid",
join: "parent"
}),
'style': x.getText({
name: "custitem8",
join: "parent"
}),
'inseam': x.getText({
name: "custitem7",
join: "parent"
}),
'wash': x.getText({
name: "custitem_washname",
join: "parent"
}),
};
});
log.debug('Results', results.length);
log.debug('results', results);
log.debug('result2', result2);
// return results;//nabeeel's
return result2;//mine
} catch (e) {
log.error('error in getItems', e)
}
}
return {
execute: execute
};
});
There is no User in a Scheduled Script, so runtime.getCurrentUser() there will not return a value. You will need to retrieve the User via that method in the Suitelet (assuming it is not an anonymous external Suitelet).
From there you can add a Script Parameter to the Scheduled Script to hold the User, and then your Scheduled Script can read the Parameter and add the value as another Data Source on your template.
This is my first question on here. Doesn't appear to be asked elsewhere, but then again I'm not sure exactly how to phrase my question.
How can I transform an array that looks like this:
var message = {
pay_key: '12345',
'transaction[0].sender_id': 'abc',
'transaction[0].is_primary_receiver': 'false',
'transaction[0].id': 'def',
'transaction[1].sender_id': 'xyz',
'transaction[1].is_primary_receiver': 'false',
'transaction[1].id': 'tuv',
};
into something like this:
{
pay_key : '12345',
transaction : [
{
sender_id : 'abc',
is_primary_receiver : 'false',
id : 'def'
},
{
sender_id : 'xyz',
is_primary_receiver : 'false',
id : 'tuv'
}
]
}
I have no control over the format of the first object as it comes from an external service. I am trying to insert the message object into a MongoDB collection, but when I try to do an insert as-is, I get an error. So I'm trying to put it into the correct form.
Should I be using Underscore for this? I've played around with _.each but can't get it to work.
my take..
var message = {
pay_key: '12345',
'transaction[0].sender_id': 'abc',
'transaction[0].is_primary_receiver': 'false',
'transaction[0].id': 'def',
'transaction[1].sender_id': 'xyz',
'transaction[1].is_primary_receiver': 'false',
'transaction[1].id': 'tuv',
};
message.transaction=[];
for (var p in message) {
var m = p.match(/^transaction\[(\d+)\]\.(.*)/);
if (m&&m[1]&&m[2]) {
message.transaction[m[1]]=message.transaction[m[1]]||{};
message.transaction[m[1]][m[2]]=message[p];
delete message[p];
}
}
Here's a generic function I just whipped up
function makeObject(message) {
var retObj = {},
makePath = function (p, pos) {
if (/\[\d+\]$/.test(p)) {
var q = p.split(/[\[\]]/),
r = q[0],
s = q[1];
if (!pos[r]) {
pos[r] = [];
}
return pos[r][s] = pos[r][s] || {};
}
return pos[p] = pos[p] || {};
};
for(var k in message) {
if (message.hasOwnProperty(k)) {
if (k.indexOf('.') < 0) {
retObj[k] = message[k];
}
else {
var path = k.split('.'),
pos = retObj,
last = path.pop();
path.forEach(function(p) {
pos = makePath(p, pos);
});
pos[last] = message[k];
}
}
}
return retObj;
}
It works as required, but I'm sure there's some better code to do it
Had a similar response, so adding it anyway:
Object.keys(message).forEach(function(key) {
var keySplit = key.split( /\[|\]\./g )
if ( keySplit.length != 1 ) {
if ( !message.hasOwnProperty(keySplit[0]) )
message[keySplit[0]] = [];
message[keySplit[0]][keySplit[1]] = message[keySplit[0]][keySplit[1]]||{};
message[keySplit[0]][keySplit[1]][keySplit[2]] = message[key];
delete message[key];
}
});
I have an Angular application that collects values of items for an invoice, I want to make sure only unique items are being added to this collection but am having no luck.
I am pushing 3 pieces of information to this collection: id, price, and type. I want to make sure there is nothing in the collection currently matching those 3 points.
// My container
$scope.invoice = {
items: [{
}]
}
$scope.addPhoto = function() {
console.log('Withdrawing Photo: '+ $scope.item.id);
if ($scope.invoice.items.indexOf(item.id) != $scope.item.id)
{
$scope.invoice.items.push({
id: $scope.item.id,
price: $scope.item.price,
type: 'photo'
});
}
}
// Trying to avoid collections like this
invoice: {
items:
[ { } , {
id: 25
price: 0
type: photo
} , {
id: 25
price: 0
type: photo
} ]
}
.filter is pretty much what you need.
$scope.addPhoto = function() {
console.log('Withdrawing Photo: '+ $scope.item.id);
var matches = $scope.invoice.items.filter(function(datum) {
return datum.id === $scope.item.id &&
datum.price === $scope.item.price &&
datum.type === $scope.item.type;
});
if (!matches.length)
{
$scope.invoice.items.push({
id: $scope.item.id,
price: $scope.item.price,
type: 'photo'
});
}
}
Semi-contrived JSFiddle
This is the solution I came up with to solve my problem, hopefully it helps someone else.
$scope.addPhoto = function () {
console.log('Withdrawing Photo: ' + $scope.item.id);
var newItemId = $scope.item.id;
var newItemPrice = $scope.item.price;
var newItemType = 'photo';
var matches = true;
// Make sure user hasnt already added this item
angular.forEach($scope.invoice.items, function(item) {
if (newItemId === item.id && newItemPrice === item.price && newItemType === item.type) {
matches = false;
$scope.message = 'You have already selected to withdraw this item!';
}
});
// add item to collection
if (matches != false) {
$scope.invoice.items.push({
id: $scope.item.id,
price: $scope.item.price,
type: 'photo'
});
$scope.total += $scope.item.price;
$scope.message = 'Total Amount Selected';
}
};
YOu can simple pop opposite of push
array.splice(array.pop(item));
so I've implemented the treeview of Fuel UX within my website. Whenever it's loaded, I need to reselect the items I want manually. Is there a possibility to preselect certain items after each reload?
Thanks in advance!
I was in the same situation since yesterday and could now solve the problem with the solution below. Just explaining that I used the methods present on the button "select nested Test Item 1" on this page. Here's the solution:
var preSelectFolder = function ($treeEl, folder, $parentEl) {
var $elParent = $parentEl || $treeEl;
if (folder.type == "folder") {
var $folderEl = $elParent.find("div.tree-folder-name").filter(function (_, treeFolder) {
return $(treeFolder).text() == folder.name;
}).parent();
$treeEl.one("loaded", function () {
$.each(folder.children, function (i, item) {
preSelectFolder($treeEl, item, $folderEl.parent());
});
});
$treeEl.tree("selectFolder", $folderEl);
}
else {
preSelectItem($treeEl, folder, $elParent);
}
};
var preSelectItem = function ($treeEl, item, $parentEl) {
var $elParent = $parentEl || $treeEl;
if (item.type == "item") {
var $itemEl = $elParent.find("div.tree-item-name").filter(function (_, treeItem) {
return $(treeItem).text() == item.name && !$(treeItem).parent().is(".tree-selected");
}).parent();
var itemId = $($itemEl).data() != null ? $($itemEl).data().id : "";
if (itemId == item.id)
$treeEl.tree("selectItem", $itemEl);
}
else if (item.type == "folder") {
preSelectFolder($treeEl, item, $elParent);
}
};
And in the event of 'loaded' I use this code:
element.on('loaded', function (e) {
angular.forEach(scope.items, function (item) {
preSelectItem($("#BuildTree"), item);
});
});
I use AngularJs so just replace "angular.forEach" for each function of Jquery and "scope.items" are items that should be pre-selected. In my case the items are in the following format:
[
{ name: 'Dir 1', type: 'folder', id: 'D1' },
{ name: 'Dir 2', type: 'folder', id: 'D2' },
{ name: 'Item 1', type: 'item', id: 'i1' },
{ name: 'Item 2', type: 'item', id: 'i2' }
]
Hope that helps.
If by manually, you mean you're actually clicking on the items again there should be a way to do this more programmatically.
I haven't tested it, but if you call $('#MyTree').tree('selectItem', $el) where $el is a .tree-item element, that should select the item.
It would be nice for your datasource to be able to tell the tree which items are selected. I see you've posted the feature request to https://fuelux.uservoice.com/forums/181290-general/suggestions/4097231-add-preselect-option-for-treeview which is great - anyone else reading this who agrees it would be useful should vote there.
I make if for ASP.NET MVC. I use a dynamic tree.
At first I received a route for selected item
[{
"id": 1, // parent category
"name": "Все категории",
}, {
"id": 56, // 1-st sub category
"name": "Для дома",
}, {
"id": 63, // item
"name": "Домашние растения",
}]
Then it need to switch off Async request for Ajax in dataSource function: 'async':false
This is all code:
#{
var jsonSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
string catRoute = jsonSerializer.Serialize(ViewBag.catRoute);
}
var catRoute = $.parseJSON('#Html.Raw(catRoute)'); // this is object of item route
function dynamicDataSource(openedParentData, callback) {
var childNodesArray = [];
$.ajax({
'type': 'post',
'url': '#Url.Action("getFuelUxTree", "Category", new { area = "Root" })',
'data': openedParentData,
'async':false // switch off ajax request
})
.done(function (data) {
childNodesArray = data;
lastTree = data;
callback({
data: childNodesArray
});
});
}
$('#categoryTree').tree({
dataSource: dynamicDataSource,
multiSelect: false,
folderSelect: false
});
// iterate all route items and open category
for (var i = 0; i < catRoute.length; i++) {
$('li#'+catRoute[i].id+' button', '#categoryTree').click();
}