I have a jqGrid which loads very nice (thanks Oleg), however I load flat data from a database table which also contains id's which I want to merge on the interface with the metadata there available
So I have a bunch of variables like:
var strMeta = [{id:35,label:"Russia",labelLocal:"Россия",pid:"33"}, {id:36,label:"Moldavia",labelLocal:"Молдавия",pid:"33"}]
In the jqGrid are id's like 35 and 36.
Now what I want to do is when the jqGrid page loads (so only for the page and not the entire data) it will match with that specific column so I get something like "[35] Россия" instead of "35", anybody ever tried to do this or have any idea how to do this?
for a form object I do this already however I cannot get this to work on the jqGrid
$.each(_Columns, function (x, it) {
if (i == it.name) {
var dataid = it.dataid;
if (dataid !== "") {
$.each(strMeta, function (y, arr) {
if (arr.id == item) {
alert(arr.label);
var _item = "[" + item + "] " + arr.labelLocal;
if (arr.labelLocal === "") {
_item = "[" + item + "] " + arr.label;
$("#" + i).val(_item);
}
return;
}
});
}
}
I know here the textbox names, however this is in a jqGrid a little different as I understood the rowid is being added to the name of the column
Thanks,
Related
Hi I have an Array which I would like to remove an element from.
After the deletion of the element from the array, it is saved to localStorage.
However, after loaded from storage it shows that the first element is missing ].
This is the code which I am using to perform the deletion:
var dataSet = (localStorage.getItem('expenditureListFromStorage'));
console.log(dataSet);
//var dataSet = "[" + dataSet + "]";
var dataSet = "[" + dataSet + "]";
console.log("Before parsing" + dataSet);
console.log(dataSet);
var dataSet = JSON.parse(dataSet);
//dataSet.push(dataSet.splice(dataSet.indexOf(selectedExpenditure), 1)[0]);
dataSet.unshift(dataSet.splice(dataSet.indexOf(selectedExpenditure), 1)[0]);
//dataSet.unshift(selectedExpenditure);
console.log("Before Deletion" + dataSet);
dataSet.shift();
//dataSet.pop(dataSet.indexOf(selectedExpenditure), 1);
//dataSet.splice(dataSet.indexOf(selectedExpenditure), 1);
console.log("After Deletion" + dataSet);
localStorage.setItem('expenditureListFromStorage', dataSet);
This is the code which I am using when saving the first element to the array:
if (localStorage.getItem('expenditureListFromStorage') === null)
{
var newExpenditure = [];
newExpenditure.push([tempExpenditureName, tempExpenditureCategory, tempExpenditureDescription, tempExpenditureOccurrence, tempExpenditurePrice, tempExpenditureDate]);
newExpenditure = "[" + newExpenditure + "]";
localStorage.setItem('expenditureListFromStorage', newExpenditure);
console.log(localStorage.getItem('expenditureListFromStorage'));
}
This is the code I am using to add subsequent elements (this piece of code is placed just after the code which saves the first element of an array):
else
{
var newExpenditure = [];
newExpenditure.push([tempExpenditureName, tempExpenditureCategory, tempExpenditureDescription, tempExpenditureOccurrence, tempExpenditurePrice, tempExpenditureDate]);
newExpenditure = "[" + newExpenditure + "]";
console.log("New Expenditure from Form = " + newExpenditure);
var expenditureArrayList = (localStorage.getItem('expenditureListFromStorage'));
console.log("expenditureArrayList from Storage before parsing" + expenditureArrayList);
expenditureArrayList = expenditureArrayList + "," + newExpenditure;
console.log("expenditureArrayList from Storage after parsing" + expenditureArrayList);
localStorage.setItem('expenditureListFromStorage', (expenditureArrayList));
console.log(expenditureArrayList);
}
If I do not save these elements this way, I cannot retrieve the array again after loading from localStorage.
I am trying to work with an array in this format
[["Array1Value1", "Array1Value2", "Array1Value3"],["Array2Value1","Array2Value2","Array2Value3"]]
This array would then be retrieved from localStorage and displayed as an HTML table using the dataTables plugin. However the problem is that when I am deleting an element and saving the array without this array, something is breaking the array and its first element.
Could someone help me out please?
The code for my add-in takes a search term, then displays a list of matching links on a table. Each link is supposed to insert itself into a word document when it's clicked, but I can't figure out how to pass variables in to a jQuery .click() function.
Currently, no matter what option I click, the URL of the link that gets inserted into the word document is always the URL of the last item on the list. So for example, if I had 3 results in the table: Facebook, Instagram and Yahoo, then whatever option I click, the URL that gets inserted is always http://www.yahoo.com
function displayLinks() {
// Empty pre-existing results
$('#linksTable').empty();
var filteredLinks = [];
// Grab value from search box
var searchTerm = document.getElementById('linksSearchField').value;
// Separate all links containing search term and put them in a filtered list
for (var i = 0; i < numberOfLinks; i++) {
if (sortedLinks[i].linkName.toLowerCase().includes(searchTerm.toLowerCase())){
filteredLinks.push(sortedLinks[i]);
}
}
// Get length of filtered links array
var numberOfSearchResults = filteredLinks.length;
// Populate table with loop
if (searchTerm != '') {
for (var x = 0; x < numberOfSearchResults; x++) {
var table = document.getElementById('linksTable');
var row = table.insertRow(x);
var nameCell = row.insertCell(0);
var linkName = filteredLinks[x].linkName;
var linkNameFormattedForID = linkName.replace(/([ &/!*^%$##+_-])+/g);
var linkURL = filteredLinks[x].linkURL;
// Add link to table
nameCell.innerHTML = "<a href='javascript:void(0);' id='" + linkNameFormattedForID + "'>" + linkName + "</a>";
// Code to add link to word document
$('#' + linkNameFormattedForID).click(linkName, function (linkName) {
Word.run(function (context) {
const doc = context.document;
const originalRange = doc.getSelection();
originalRange.insertHtml("<a href='" + linkURL + "'>" + linkName.currentTarget.innerText + "</a>", "Start");
originalRange.insertText("Refer to ", "Start");
originalRange.load("text");
return context.sync()
})
.catch(function (error) {
console.log("Error: " + error);
if (error instanceof OfficeExtension.Error) {
console.log("Debug info: " + JSON.stringify(error.debugInfo));
}
});
});
}
}
}
I think I could maybe fix the problem by defining the linkURL variable within the click function itself, but the issue is that I can't access filteredLinks[x] inside of it. I can access the filteredLinks array on its own, but it can't read x, even though the click function is contained within the loop?
As a last-resort super hacky fix, I think I could just change the ID of each item to include it's URL, then extract it from linkName.currentTarget.innerText, but I'd rather not do that unless I really have to.
Thanks in advance!
The problem is that var in JavaScript is function scoped, and because the click event gets invoked after the for loop ends, the value of x will always be the final value of x. There's more information in pleanty of blog posts like this one: https://medium.com/front-end-developers/es6-variable-scopes-in-loops-with-closure-9cde7a198744
The solution:
Use let or const instead of var
A slightly worse solution:
wrap the contents of the for loop inside an IIFE
for (var x = 0; x < numberOfSearchResults; x++) {
(function(x){
...
})(x);
}
Here's a challenging one. I'm relatively new to scripting but have an idea I want to get working.
I have a script that is dynamically generating drop-down lists based on an array: each item in that array creates a dropdownlist.
function getDropDownLists(inputArray, grp) { //input an array and the UI Group we're adding these DDLs to
try {
eval(grp + "Array = [];"); //Creates an array to store the DDLs we're about to create
var listName; //Create variable to store name of DDL we're creating as we iterate through inputArray
for (var i = 0; i < inputArray.length; i++) {
listName = grp + "SrcLevel_" + i.toString(); //Get the name for the DDL we're about to create
eval('var ' + listName + ' = ' + grp + '.add("dropdownlist",[0,0,150,25])'); //add a DDL for the current array item
eval(listName + '.add("item","' + listName + '")'); //This line creates an item in each dropdown to tell me its name
eval(grp + "Array[" + i + "] = " + listName + ";"); //Adds newly created DDL to the storage array
}
} catch (e) {
alert("Error on line " + e.line + ":\n" + e.message);
}
}
When I call this function (it may not work perfectly here as I've cleaned it up a bit for display purposes) it correctly creates all my dropdownlists. However, I want to create onChange events for each of these to reference the previous one in the created storage array and change its contents. I know how to make the onChange events work if these were known dropdownlists, but every project I'll be working on is different and I'd like to get this to work without having to retool every time the project requirements change.
For example, when I call getDropDownLists(['mom','dad','baby'],family), I would get three dropdownlists: familySrcLevel_0,familySrcLevel_1,familySrcLevel_2. How would I then create onClick events for each of these dropdownlists, knowing that I won't always know how many there are? Is such a thing possible? It has to be done in Extendscript.
The solution was to create another eval statement that contained the onChange function in it at the end of the function above.
I have implemented searchbox using jQuery. Here is the code which sends search term and
after that I receive Json which I use to make list of matched searched items.
The problem is that on each keyup I delete all matched items :
$("#realPlaceForSearchItems").html("");
because if I don't that I get duplications when searching for product if I enter "pro" and then type "d". (I am appending list items to the list) Is it possible to achieve that I somehow just delete elements that do not match "prod" (which previously matched "pro" ofcourse) and that elements that match prod stay untouched after typing "d".
$("#searchInput").keyup(function () {
$this = $(this);
$('#realPlaceForSearchItems').show();
$("#realPlaceForSearchItems").html("");
var seachedTerm=$this.val();
if ($this.val().length> 2)
{
$("#realPlaceForSearchItems").html("");
$('#realPlaceForSearchItems').show();
$.ajax({
type: "POST",
url: ROOT + "Filter/Search/",
data: {term: $this.val()},
success: function (data)
{
var Link = $("#searchTemplate>li>a");
var placeForProductId=$("#searchTemplate>li>a>input");
var placeForPicture = $("#searchTemplate>li>a>div>img");
var placeForProductName = $("#searchTemplate>li>a>div>div");
var placeForPrice= $("#searchTemplate>li>a>div>span");
$.each(data.productsWereSeached, function () {
console.log("sddsd", data.totalrows);
var imagesFolder="/Content/images/";
var pathToProduct="/ProductDetails/Index/"
var slash = "/";
Link.attr("href", pathToProduct + this.Id);
placeForProductId.val(this.Id);
if (this && this.Picture) //for the case there is no any picture there would be error cant read propery or undefined
placeForPicture.attr("src", imagesFolder + this.Id + slash + this.Picture.FileName);
else
placeForPicture.attr("src", "");
placeForProductName.html(this.Name);
placeForPrice.html((parseFloat(this.Price) / 100.0).toString() + " kn");
$listItem = $("#searchTemplate").html();
$("#realPlaceForSearchItems").append($listItem);
});
$("#nOfMatchedProducts").val(data.totalrows);
if (data.totalrows > 2)
{
var searchurl="/Search/ShowMoreSearched?term="
$showMoreItem = $("#showMoreItem").html();
$("#showMoreItem>li>a").attr("href",searchurl+seachedTerm);
$("#realPlaceForSearchItems").append($showMoreItem);
}
},
failure: function ()
{
}
});
}
});
$.each(data.productsWereSeached, function () {
if($('a[href="'+pathToProduct + this.Id+'"]').length == 0) {
console.log("sddsd", data.totalrows);
var imagesFolder="/Content/images/";
var pathToProduct="/ProductDetails/Index/"
var slash = "/";
Link.attr("href", pathToProduct + this.Id);
placeForProductId.val(this.Id);
if (this && this.Picture) //for the case there is no any picture there would be error cant read propery or undefined
placeForPicture.attr("src", imagesFolder + this.Id + slash + this.Picture.FileName);
else
placeForPicture.attr("src", "");
placeForProductName.html(this.Name);
placeForPrice.html((parseFloat(this.Price) / 100.0).toString() + " kn");
$listItem = $("#searchTemplate").html();
$("#realPlaceForSearchItems").append($listItem);
}
});
Psst... I'm assuming you also want to limit calls to the server and that your search result list is not wildly huge!
So! Benefit to your current approach is you don't have to manage/compare any existing data set. This makes things easier when a search for "pro" changes to a search for "cro" or any other change that makes the previous AJAX call irrelevant. But, like you said, it leaves you with this clear then re-add items inefficiency when you search for "prod" after "pro".
Idea:
Store the most recent AJAX call criteria in a global.
If new search value includes the latest AJAX search value, filter/hide items in the existing data set which do not match the new criteria. Do not perform a new search.
If new value does not include the latest AJAX search value: clear current data set, update AJAX search value, execute new AJAX call
Pass the index from $.each (http://api.jquery.com/jQuery.each/) into your function, then use it to select the search result you will replaceWith (http://api.jquery.com/replaceWith/) the element you just built. In using this method, your four LI elements within the search results UL must exist before a search.keyup is executed.
Do this by changing two lines...
$.each(data.productsWereSeached, function (index) {
... all of the existing code in the loop stays the same except ...
$("#realPlaceForSearchItems LI:eq(" + index + ")").replaceWith($listItem);
});
In my application, I have an HTML select box from which I remove and add items based on various user actions (the items become available/unavailable). However, I would also like all items to be displayed in preferred order, so every time I return an item to the select list, I need to re-sort in preferred order and select the preferred option. I've been unsuccessful thus far.
This is what I've got currently:
function update_select (select_id) {
// Rebuild given select box with appropriate options
var s = $(select_id);
s.empty();
for (index in order_by_kind(selectable)) {
var option = selectable[index];
var s_option = $('<option value="' + option.value + '">' + option.desc + '</option>')
s.append(s_option);
if (index == 0) {
s_option.attr('selected', true);
console.log(s_option);
}
}
}
If I log the results of order_by_kind(), the option values are sorted as desired. I empty the contents of the list and rebuild it in the desired order, but the item always is last in the list. Logging s_option shows that the option is set as selected, but the item is never selected in the UI. What might I doing wrong?
Edit:
My order_by_kind() function is below, for those who would like to verify that it functions correctly:
function order_by_kind(obj_list) {
var tmp = [];
for (index in type_order) {
var kind = type_order[index];
for (obj_index in obj_list) {
var obj = obj_list[obj_index]
if (kind == obj.value) {
tmp.push(obj);
// break out of the inner loop
break;
}
}
}
return tmp
}
The problem was that although I was iterating over the ordered list, I was still referencing the unsorted list in order to build my options.
function update_select (select_id) {
// Rebuild given select box with appropriate options
var s = $(select_id);
s.empty();
// sort and write back the selectable items
selectable = order_by_kind(selectable);
for (index in selectable) {
var option = selectable[index];
var s_option = $('<option value="' + option.value + '">' + option.desc + '</option>')
s.append(s_option);
if (index == 0) {
s_option.attr('selected', true);
console.log(s_option);
}
}
}
Try this approach, storing and restoring the selected value:
function update_select (select_id) {
// Rebuild given select box with appropriate options
var s = $(select_id);
var val = s.val();
s.empty();
for (index in order_by_kind(selectable)) {
var option = selectable[index];
var s_option = $('<option value="' + option.value + '">' + option.desc + '</option>')
s.append(s_option);
}
s.val(val);
}
This may be a dead question, however its the first one in the search results - So i will post my solution here: The fiddle contains the compare functions for both value and html.
function reOrderOptions(select)
{
function compareOptions(optionA, optionB) {
return optionA.value - optionB.value;
}
var options = $(select + " option");
$(select).empty().append(options.sort(compareOptions));
}
Fiddle!