I currently have a itemsCollection and a historyCollection. Both are separate isolated .dat files.
The saving and displaying works fine for both of these isolated storages, however the problem is when I try to delete something out of the itemCollection I also want to remove all the items out of the historyItemCollection where the historyItemCollection contains that specific itemIndex.
Update:
The itemCollection could contain something like this:
a
b
c
The historyItemCollection could look like this:
a
b
c
b
So if I remove b (itemIndex 1) then I want both to be removed in the historyItemCollection.
I can remove the items out of the itemCollection fine, but the historyItemCollection throws errors.
int i = 0;
for (i = 0; i <= App.ViewModel.historyItemCollection.Count-1; i++)
{
if (App.ViewModel.historyItemCollection[i].VehicleId == (Application.Current as App).vehicleIndex)
{
App.ViewModel.historyItemCollection[i].Remove(i);
}
}
App.ViewModel.vehicleItemsCollection[(Application.Current as App).vehicleIndex].Remove((Application.Current as App).vehicleIndex);
The error message I'm getting:
Parameter name: index
It fails on this line:
App.ViewModel.historyItemCollection[i].Remove(i);
In this line do you really mean both of these to be itemIndex?
App.ViewModel.historyItemCollection[(Application.Current as App).itemIndex].Remove((Application.Current as App).itemIndex);
Also, does calling RefreshItems() have any impact on itemIndex?
I'd recommend breaking your code up into more lines - then single stepping through.
As an aside, why are you setting the DataContext in this method? Then why are you also setting it twice - and to different types of objects each time. This seems unusual - perhaps you could instead set the DataContext globally to a new ViewModel class which has the history and items as children?
The problem is that you're removing items from a list as you iterate forwards through it.
As you delete items from the list you invalidate the count of total items in the list and your relative position.
If you must edit the list this way you should step backwards through it so as not to effect the indexing.
See also How to remove elements from a generic list while iterating over it?
Related
Attempting to confirm that of all the schema in the head of a page exactly 3 of them should have a specific string within them. These schemas have no tags or sub classes to differentiate themselves from each other, only the text within them. I can confirm that the text exists within any of the schema:
cy.get('head > script[type="application/ld+json"]').should('contain', '"#type":"Product"')
But what I need is to confirm that that string exists 3 times, something like this:
cy.get('head > script[type="application/ld+json"]').contains('"#type":"Product"').should('have.length', 3)
And I can't seem to find a way to get this to work since .filter, .find, .contains, etc don't filter down the way I need them to. Any suggestions? At this point it seems like I either need to import a custom library or get someone to add ids to these specific schema. Thanks!
The first thing to note is that .contains() always yields a single result, even when many element match.
It's not very explicit in the docs, but this is what it says
Yields
.contains() yields the new DOM element it found.
If you run
cy.get('head > script[type="application/ld+json"]')
.contains('"#type":"Product"')
.then(console.log) // logs an object with length: 1
and open up the object logged in devtools you'll see length: 1, but if you remove the .contains('"#type":"Product"') the log will show a higher length.
You can avoid this by using the jQuery :contains() selector
cy.get('script[type="application/ld+json"]:contains("#type\": \"Product")')
.then(console.log) // logs an object with length: 3
.should('have.length', 3);
Note the inner parts of the search string have escape chars (\) for quote marks that are part of the search string.
If you want to avoid escape chars, use a bit of javascript inside a .then() to filter
cy.get('script[type="application/ld+json"]')
.then($els => $els.filter((index, el) => el.innerText.includes('"#type": "Product"')) )
.then(console.log) // logs an object with length: 3
.should('have.length', 3);
I'm a beginning learner of InDesign scripting and would like to help myself with debugging, but my attempts seem to run into walls. Hope someone has some insights that will help me going forward.
I'm working on a little project that loops through some selected tables, puts the 3 tables into an array/variable (accomplished that) and then loops through the content of those tables to find a GREP match and store those in an array/variable (for further uses I won't get into now)
My main objective at this point: See exactly what text characters the .findGrep(); function is catching and display those in the Javascript Console of the ExtendScript Toolkit app.
So here's a bit of the journey up to this point, including codes tried and suggestions from others. (All of my attempted uses of these has failed...why I'm here now... and why this is long; my apologies)
Initial try.
var myTables = []; (in Data Browser this shows values of [object Table], [object Table], [object Table]
var myFinds = [];
var myTest = [];
var myCharacters = [];
app.findGrepPreferences = null;
app.findGrepPreferences.findWhat = "\"";
for (x = 0; x < myTables.length; x++) {
var myFinds = myTables[x].findGrep();
$.writeln(myFinds);
};
Notes on this code: Because not every table has the characters in the findWhat, sometimes in this loop myFinds has nothing, but when it does have something, it shows this in console [object Character],[object Character],[object Character]
So someone (firstHelp) gave me this: And it did not work... error thrown on .contents.toString(); *"undefined is not an object" which I thought, "ok, yes I see at times in the loop myFinds has nothing in it... more on this later"
var stringArray = [];
for( var n=0; n<myFinds.length; n++ ) {
stringArray[n] = myFinds[n].contents.toString();
};
$.writeln(myFinds.join("\r"));
Code revamp Gave up on the $.writeln(myFinds); within the loop and tried this in order to gather Grep finds in a variable/array that could be dealt with outside of loop.
for (x = 0; x < myTables.length; x++) {
$.writeln(myTables[x].cells.firstItem().texts[0].contents[0]);
myFinds.push(myTables[x].findGrep());
};
$.writeln(myFinds);
ExtendScript Toolkit console now showing this for myFinds:
*myFinds = [Array], [object Character], [object Character], [object...
+ (object symbol) 0 =
+ (object symbol) 1 = [object Character], [object Character], [object Character]
+ (object symbol) 2 =
+ (object symbol) _proto_ =*
*again tried the .contents.toString(); on the myFinds and still the same error, "undefined..." including targeting the array when it clearly had something in it.
**So then I get this tipoff...(but no helpful code to apply to what I already have)
"you are dealing with arrays of arrays mixed with texts.
So you have to check with each item of the result array if it is text
or another array of texts.
If it is an array loop that array."
And later this bit of code that is supposed to "flatten" my array... a = [].concat.apply([],a);
Replacing a with myFinds like this, myFinds = [].concat.apply([],myFinds); did absolutely nothing. The array and its contents showed no change in the console... and I have no idea how to loop through each item of this array within an array, find out if it's text or another array and then show its real contents to console.
Really...how many loops and if/thens etc do I need to run on one array to show its actual contents in the console? But I know I struggle with breaking down every little step I want, to its minute scripting granularity and so my ignorance regularly impedes me. I welcome any suggestions/tips to move me closer to my **main objective" as stated above. Thanks
Regarding the first help. The real reason why you get an error while accessing content property is that you don’t check the type of the object and presume it will be a Text object. As the findGrep may not find a Text occurrence, you actually get an empty array. And Array.prototype.contents doesn’t exist hence the error.
Then $.writeln is legacy of Adobe ExtendScript toolkit, the IDE for ExtendScript. This product is no longer de eloped and maintained by Adobe. You should consider using other logging techniques such as the Visual Studio ExtendScript plugin which will allow you to use breakpoints and everything you need.
I want to make 3 dependents drop down list, each drop down dependent to the previous drop down, so when I select an item from first drop down , all data fetch from database and add to second drop down as item.
I know how to do this in a normal php page using ajax, but as opencart uses MVC I don't know how can I get the selected value
Basically, you need two things:
(1) Handling list changes
Add an event handler to each list that gets its selected value when it changes (the part that you already know), detailed tutorial here in case someone needed it
Just a suggestion (for code optimization), instead of associating a separate JS function to each list and repeating the code, you can write the function once, pass it the ID of the changing list along with the ID of the depending list and use it anywhere.
Your HTML should look like
<select id="list1" onchange="populateList('list1', 'list2')">
...
</select>
<select id="list2" onchange="populateList('list2', 'list3')">
...
</select>
<select id="list3">
...
</select>
and your JS
function populateList(listID, depListID)
{
// get the value of the changed list thorugh fetching the elment with ID "listID"
var listValue = ...
// get the values to be set in the depending list through AJAX
var depListValues = ...
// populate the depending list (element with ID "depListID")
}
(2) Populating the depending list
Send the value through AJAX to the appropriate PHP function and get the values back to update the depending list (the part you are asking for), AJAX detailed tutorial here
open cart uses the front controller design patter for routing, the URL always looks like: bla bla bla.bla/index.php?route=x/y/z&other parameters, x = folder name that contains a set of class files, y = file name that contains a specific class, z = the function to be called in that class (if omitted, index() will be called)
So the answer for your question is:
(Step 1) Use the following URL in your AJAX request:
index.php?route=common/home/populateList
(Step 2) Open the file <OC_ROOT>/catalog/controller/common/home.php , you will find class ControllerCommonHome, add a new function with the name populateList and add your logic there
(Step 3) To use the database object, I answered that previously here
Note: if you are at the admin side, there is a security token that MUST be present in all links along with the route, use that URL:
index.php?route=common/home/populateList&token=<?php echo $this->session->data['token'] ?> and manipulate the file at the admin folder not the catalog
P.S: Whenever the user changes the selected value in list # i, you should update options in list # i + 1 and reset all the following lists list # i + 2, list # i + 3 ..., so in your case you should always reset the third list when the first list value is changed
P.P.S: A very good guide for OC 1.5.x => here (It can also be used as a reference for OC 2.x with some modifications)
I have got a Kendo Grid and I want to access the data from the row whose detail I expanded. For testing purposes, I have this:
function detailExpand(e)
{
var aux = e.sender.MyModelId;
var aux2 = this.MyModelId;
...
But none of those variables have the MyModelId in it.
I have inspected it and I can't find the model properties unless inside the e.sender._data[index-here] but I don't know the index of the row whose detail I've expanded.
e.sender.dataItem(e.masterRow).MyModelId
http://docs.telerik.com/kendo-ui/api/javascript/ui/grid#events-detailExpand
http://docs.telerik.com/kendo-ui/api/javascript/ui/grid#methods-dataItem
For the record, you should try to avoid using methods starting with an underscore (_). I believe kendo uses the underscore to show it's an internal method (a "private"). Unexpected behavior could occur.
So the tt templates will regenerate every file whenever you save. Now, great, it generates files. However, I am making partial classes to extend other classes, but I only need the files that dont already exist for me generated. The ones that exist, I'd like to preserve. So far, I am finding not one solid solution googling the globe...
In my code below, the exception for finding existing files doesnt matter, because the template will start by deleting all files first. Then it regenerates.
It there a method like "onsave" that I can override?
// BEGIN CODE TO GENERATE EXTENSIONS
<#
foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
{
string fileName = entity.Name + ".Extension.cs";
string filePath = this.Host.TemplateFile.Substring(0,this.Host.TemplateFile.LastIndexOf(#"\"));
filePath = filePath + #"\Extensions\" + fileName;
if((File.Exists(filePath) && PreserveExistingExtensions == false) || !File.Exists(filePath))
{
fileManager.StartNewFile(fileName);
BeginNamespace(namespaceName, code);
bool entityHasNullableFKs = entity.NavigationProperties.Any(np => np.GetDependentProperties().Any(p=>ef.IsNullable(p)));
#>
<#=Accessibility.ForType(entity)#>
<#=code.SpaceAfter(code.AbstractOption(entity))#>partial class
<#=code.Escape(entity)#><#=code.StringBefore(" : ", code.Escape(entity.BaseType))#>
{
}
<#
EndNamespace(namespaceName);
}
}
fileManager.Process();
#>
I do something similar (partial classes) where I have one that is always generated, but the custom one will only be generated if it doesn't exist. This second one is created as starting class for customizations. I'll output two files like so:
MyClass.generated.cs
MyClass.cs
MyClass.cs will never be recreated, unless it doesn't exist. MyClass.generated.cs will always be recreated.
I use the T4toolbox to do this, Oleg Sych has actually made this quite easy.
You can check out some sample T4 Templates I built here. Specifically have a look at this one, it's a good example for generated partial classes where one needs to be created every time, and one is only created if it doesn't exist.
The main thing to look at is this line in the code:
var requestBaseMessageCustom = new MessageTemplate(rootNamespace, serviceName + "Request");
requestBaseMessageCustom.Output.File = "Messages/" + serviceName + "Request.cs";
requestBaseMessageCustom.Output.PreserveExistingFile = true;
requestBaseMessageCustom.Render();
Notice the property called PreserveExistingFile, that's the key.