Loading extJS Combo Remotely not Working - asp.net

This is my first bash at using extJS, and after a few hours of struggling, some things are working OK, except I have combo lists that I can't filter down to less than 2000 items in edge cases, so I'm trying to page the lists through remotely, but I must be doing something wrong.
My data store and combo look as follows:
var remoteStore = new Ext.data.JsonStore({
//autoLoad : true,
url : 'addition-lists.aspx',
fields : [{name: 'extension_id'}, {name: 'extension'}],
root : 'extensionList',
id : 'remoteStore'
});
.
.
xtype : 'combo',
fieldLabel : 'Remote',
name : 'remote',
displayField : 'extension',
valueField : 'extension_id',
mode : 'remote',
//pageSize : 20,
triggerAction : 'query',
typeAhead : true,
store : remoteStore,
anchor : '95%'
The combo works loading locally, but as soon as I switch to remote it remains blank.
My ASP.NET page returning the JSON is like this:
protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();
Response.Write(GetRemote());
}

On remote stores the combo defaults its minChars property to 4, so the query only gets sent after typing 4 chars. Setting minChars almost gives the desired behaviour.
I say almost because even if the item sought by autocomplete is in the current page, a new server query still gets sent, defaulting the selection to the first item in the new page.

The way you configured your store above, the result from your ASP script should read something like this:
{"extensionList": [
{"extension_id": 1, "extension": "js"},
{"extension_id": 2, "extension": "aspx"}
]}
If it doesn't look like that, your remote store will not find anything.

You can refer to this question ExtJS combobox problem in IE

Several things. First, when doing this:
remoteStore.loadData(<%= GetRemote() %>);
you are not actually making a remote call from your javascript. You are echoing the result of calling the GetRemote server function directly into the page at render time. Probably not what you intend? If GetRemote is writing out your combo data (and it's working correctly), then you should be able to use a combo setup for local data. If the intention really is to make a remote call, then you need to remove the server tag and load data via the proxy url as shown in several examples that come with Ext.
Another thing is that your Page_Load code doesn't actually show anything about how you are loading, formatting or returning your data. I would suggest viewing source and verifying that your tag is actually being replaced with the data you expect. If/when you switch it to a true remote call to load data then you can use Firebug to inspect your XHR calls and verify the data coming down that way.

You must set a proxy, i.e. set
proxy: new ScriptTagProxy
property for loading 'store' remotely. Look at examples for exact syntax.
EDIT: Please disregard my previous note since you're using JsonStore shortcut.
Try to apply all of these properties to your combo:
typeAhead: true,
typeAheadDelay: 500,
triggerAction: 'all',
selectOnFocus:true,
And please do not do server-side prefetch of records (using loadData). It hurts internal filter very much, so that you stick with filtered records from different prefetches.
On the other hand, if you do prefetch all records on the server-side, why do you need then remote access for your combo anymore?!

Related

Semantic-ui Form Validation basic setup

I'm new to semantic-ui and to javascript as well, so please bear with me. I have a basic form that I'm trying to get working with the built-in form validation semantic-ui provides. This form is part of a web app using node, express, and pug. The structure of the specific form (view) I'm working on looks like this:
Sorry for using a picture but I'm trying to keep this high-level.
As you can see, I have a form (with I believe the requisite classes), a submit button and a script block at the end, which is where I've got the validation code at the moment.
Here's my validation code such as it is:
$('#new-password-form').form({
on: 'blur',
fields: {
password: {
identifier : 'password',
rules: [
{
type : 'empty',
prompt: 'You must enter a password'
},
{
type : 'regExp[/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!##\$%\^&\*])(?=.{8,})/]',
prompt: 'Your password must be at least 8 characters long, and contain upper and lower case characters, digit(s), and symbol(s)'
}
]
}
}
}, {
onSuccess : function(e){
e.preventDefault();
}
});
The trouble is, validation isn't working. When I click the submit button the form attempts a regular get submit and it's as if the javascript isn't even there somehow. Yet it is there. Node is showing everything is properly fetched and loaded by the browser. Inspecting the rendered HTML shows everything is there, and I see no errors in the console. The page appears to have loaded all the requisite files successfully as follows:
GET /enroll/new 200 31.281 ms - 2652
GET /stylesheets/style.css 200 0.859 ms - 735
GET /jquery/jquery.js 200 1.491 ms - 280364
GET /ui/semantic.min.css 200 1.508 ms - 628536
GET /ui/semantic.min.js 200 2.070 ms - 275709
GET /images/amm.png 200 2.068 ms - 25415
GET /ui/semantic.min.css 200 0.418 ms - 628536
GET /favicon.ico 404 9.768 ms - 1499
So what gives? Can someone tell me what I'm doing wrong? Happy to provide more detail if what I have here isn't enough.
Update:
I extracted the HTML to a flat file, and relinked the assets (png, js, css) so there is no server involved at all. The page loads in the browser just fine. I get the exact same behavior (nothing happens when submit is clicked except the page reloads with get parameters—default non-js behavior AFAIK). It's making me think something is wrong with jQuery or javascript itself.
Well I found the problem... a missing ',' at the end of the "type:" row (regExp[/^(?=.*[a-z])...).
Now validation is working for both the static file, and the server version. For what it's worth coming from other languages where this is not an issue, javascript's ubiquitous use of inline functions and data structures nested multiple levels deep is something I've had a very hard time getting used to. Makes it all too easy to miss some critical little piece.
I guess let this be another example of a basic setup of semantic-ui that works... so long as you don't leave off any commas. (I fixed the code above for those that might want to copy/paste)

Meteor utilities:avatar data

I'd like to use the utilities:avatar package, but I'm having some major reservations.
The docs tell me that I should publish my user data, like this:
Meteor.publish("otherUserData", function() {
var data = Meteor.users.find({
}, {
fields : {
"services.twitter.profile_image_url_https" : true,
"services.facebook.id" : true,
"services.google.picture" : true,
"services.github.username" : true,
"services.instagram.profile_picture" : true
}
});
return data;
});
If I understand Meteor's publish/subscribe mechanism correctly, this would push these fields for the entire user database to every client! Clearly, this is not a sustainable solution. Equally clearly, however, either I am doing something wrong, or I am understanding something wrong.
Also: This unscalable solution works fine in a browser, but no avatar icons are visible when the app is deployed to a mobile device, for some reason.
Any ideas?
Separate the issue of which fields to publish from which users you want to publish data on.
Presumably you want to show avatars for other users that the current user is interacting with. You need to decide what query to use in
Meteor.users.find(query,{fields: {...}});
so that you narrow down the list from all users to just pertinent ones.
In my app I end up using reywood:publish-composite to publish the users that are related to the current user via an intermediate collection.
The unscalability of utilities:avatar seems, as far as I can tell, to be a real issue, and there isn't much to be done about it except to remove utilities:avatar and rewrite the avatar URL-fetching code by hand.
As for the avatars not appearing on mobile devices, the answer was simply that we needed to grant permission to access remote URLs in mobile-config.js, like this:
App.accessRule("http://*");
App.accessRule("https://*");

Selenium and wordpress: New post test

I've been looking a bit at Selenium, and I'm beginning to like it, since I know some Java programming and find both Java and C# pretty straight-forward for simple things like this.
However, I'm struggling with a test that creates a new post in Wordpress, from the Dashboard page:
This is the Selenium code (in C#):
(The Driver instance is, obviously, a driver class I've created - for starting the browser and connecting to the wordpress site.)
1: Driver.Instance.FindElement(By.Id("title)).SendKeys(title);
2: Thread.Sleep(1000);
3:
4: Instance.SwitchTo().Frame("content_ifr");
5: Thread.Sleep(1000);
6:
7: Driver.Instance.SwitchTo().ActiveElement().SendKeys("something");
Now, what happens is that the title is easily found (by ID, so I wouldn't expect problems there), and I can easily insert the title text (line 1).
But the inline frame for the post body is causing problems. When running the test, after the topic is filled in, the cursor changes to the body area (line 4) - as planned. However, nothing more happens. The SendKeys("string") method (ine 7) doesn't seem to work there.
Any ideas?
EDIT: Of course - an important piece of information is that the iframe in Wordpress simply loads a TinyMCE editor. So, in the page source, there's only a body tag with the javascript loading of the editor.
EDIT2: Of course, something suddenly changed. Without ANY change to the wordpress page, the "content_ifr" is now suddenly missing (?!!!!!?) The Selenium test fails with "unable to locate frame...", and it's also suddenly missing from the page source.
EDIT3: I also noticed something:
Driver.Instance.SwitchTo().Frame(iframe);
Driver.Instance.FindElement(By.Id("tinymce")).SendKeys("message body");
It's the SECOND line that makes the cursor switch to the mce field, not the line with the .SwitchTo(). However, I need the first line - the second line does nothing on its own. This is approaching something really stupid. I've been looking for a solution to this for a week - this doesn't exactly bode well for Selenium. The Selenium user group doesn't even want to answer when I ask them.
Also - if I skip the SendKeys() method in the second line, nothing happens. So, it seems that the two lines does ALLMOST what it should, right up to and including placing the cursor in the correct spot. But it never sends any text.
EDIT4 (last): After actually figuring out how to use IJavaScriptExecutor, it works using the solution(s) below.
Java method to handle TinyMCE editor would look like:
public void entersTopicOfBody(String textToBeTyped, WebDriver driver) {
driver.switchTo().frame("content_ifr");
WebElement body = driver.findElement(By.xpath("//body"));
body.click();
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].innerHTML = '"+ textToBeTyped+"'", body);
driver.switchTo().defaultContent();
}
Below is some C# code that publishes a post. I think the main issues you have are due to timing issues.
I've done a bit of Selenium recently and I favour implicit waits: it waits for a maximum time period for the item to be available, but returns as soon as possible. So you can specify a max wait of 100 seconds, but if it finds it in 1 second, it will only wait 1 second. Much more efficient vs sleeping for an arbitrary length of time. See this post about Implicit and Explicit waits
But even with implicit waits, it may not solve all issues. When coding the sample below, I ran into the issue where the "Publish" button was disabled and re-enabled after some time. And that's when you have to look at the code to see what it is doing as well. It's times such as these where sleeps can help you fix the problem for a quick fix if you do not wish to debug too much: just be sure to set a large enough sleep time and be wary that it could be inconsistent in the future.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Support.UI;
using OpenQA.Selenium.Support.Events;
namespace SeleniumTest
{
class Program
{
static void Main(string[] args)
{
IWebDriver driver = new OpenQA.Selenium.Firefox.FirefoxDriver();
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(30));
// enter your configurations here
driver.Navigate().GoToUrl("http://localhost/wordpress/wp-admin/post-new.php");
driver.FindElement(By.Id("user_login")).SendKeys("admin");
driver.FindElement(By.Id("user_pass")).SendKeys("yourpassword");
driver.FindElement(By.Id("wp-submit")).Click();
driver.FindElement(By.Id("title")).SendKeys("the title");
var iframe = driver.FindElement(By.Id("content_ifr"));
driver.SwitchTo().Frame(iframe);
// your solution which works in my instance
//driver.SwitchTo().ActiveElement().SendKeys("hello tiny mce from selenium");
// send keys with exact element
//driver.FindElement(By.Id("tinymce")).SendKeys("hello tiny mce from selenium");
// javascript - 1
IJavaScriptExecutor js = driver as IJavaScriptExecutor;
var tinymce = driver.FindElement(By.Id("tinymce"));
IJavaScriptExecutor executor = (IJavaScriptExecutor)driver;
executor.ExecuteScript("arguments[0].innerHTML = 'hello tiny mce via javascript'", tinymce);
// javascript - 0
driver.SwitchTo().DefaultContent();
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(11));
wait.Until((d) => { return !d.FindElement(By.Id("publish")).GetAttribute("class").Contains("disabled"); }); // wait for publish button to be enabled
driver.FindElement(By.Id("publish")).Click();
driver.FindElement(By.Id("message")); // wait for message on next page to verify it is posted
driver.Close();
}
}
}
A PHP version of olyv solution:
$content = 'my text';
$this->frame( 'content_ifr' );
$body = $this->byXPath( '//body' );
$body->click();
$script = 'arguments[0].innerHTML = "" + arguments[1] + ""; ';
$this->execute( [
'script' => $script,
'args' => [ $body->toWebDriverObject(), $content ],
]
);
$this->frame( null );
I know that I am a bit late to the party, but I just found a solution that is (I believe) much simpler than the answers given so far. So I decided to post it here in case it could help someone else.
There is no need to switch frames here. What you wanna do is 'click' on the button in the top right corner of the text editor that says "Text", which has id = "content-html". Now, you can 'send keys" to the textarea, which has id = "content".
Here is some Python code that does just this:
driver.find_element_by_id("content-html").click()
driver.find_element_by_id("content").send_keys("Some text...")
Hope it helps

RESTful advice: default value for given resource

I have the following rest structure for 'keyboard' objects:
GET /keyboards/ -> Lists user keyboards
POST /keyboards/ -> Creates new keyboard
GET /keyboards/{id} -> Get specific keyboard by id
PUT /keyboards/{id} -> Update specific keyboard by id
DELETE /keyboards/{id} -> Delete specific keyboard by id
The front end uses whatever keyboard is set to the users default keyboard, or, if the user has no custom keyboard set, simply returns a generic default.
At present, that is done by requesting another URL:
GET /keyboards/default
However, this appears a little misleading to me, as the resource 'default' could change whenever the user changes their default, and actually is a pointer to a different specific resource.
I'm not sure of a more elegant solution to this, as the front-end would appear to need to make two requests otherwise:
GET /keyboards/ -> Revealing the default
GET /keyboards/{id} -> To get the mappings associated with the keyboard
Which seems a more laborious, two step process. Is the first option a reasonable one, or am I missing a more elegant implementation?
It's OK to have convenience identifiers like 'default', 'latest' etc...
GET /keyboards/default
-> {
id: 3,
Another option is to hang the default keyboard off of a containing/referencing resource if there is one. For example
GET /computer
-> {
name: foo,
defaultKeyboard: 3,
...
If you want to avoid two requests you could have isDefault on the keyboard object.
GET /keyboards
[
{ id: 1, isDefault: false, ... }
{ id: 3, isDefault: true, ... }
That allows you to filter via querystring params.
Finally, this doesn't have to be an OR - you can have all of these for a convenient API for different access patterns.
Having to do a higher number of requests than with other architecture styles is a well-known and assumed drawback of RESTful APIs.
It is counterbalanced by the fact responses may be cached more easily as each resource has a unique URL.
Does you keyboard resource expose an "IsDefault" property? It should. And so:
GET /keyboards/
Would return a list of keyboards. You could examine the keyboard resources in the list and choose the one that is the default.
And you could also solve this by making this a query parameter:
GET /keyboards?IsDefault=true
There's nothing wrong with having a convenience /keyboards/default identifier, as long as its cacheability is being defined correctly, which in this case would probably be to tell clients to not cache it at all.

Programicatlly visit (all) ASP.Net page(s) in a website?

In the Security model for out ASP.Net website (.Net 3.5) we store the page name:
page.GetType().Name
as the primary key in a database table to be able to lookup if a user has access to a certain page. The first time a page is visited this record is created automatically in the database.
We have exported these database statements to insert scripts, but each time a new page gets created we have to update the scripts, not a huge issue, but I would like to find an automated way to do this.
I created an attribute that I tagged a few pages with and then wrote a small process to get all the objects that have this attribute, through the reflection create an instance and insert the record using the same code to for page records mentioned above:
IEnumerable<Type> viewsecurityPages = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsDefined(typeof(ViewSecurityAttribute),false));
foreach (Type t in viewsecurityPages)
{
object obj = Activator.CreateInstance(t, false);
//clip..(This code just checks if the record already exists in the DB)
if (feature == null)
{
Attribute attb = Attribute.GetCustomAttribute(t, typeof(ViewSecurityAttribute));
if (attb != null)
{
CreateSecurableFeatureForPage((Page)obj, uow, attb.ToString());
}
}
}
The issue is that page.GetType().Name when the page goes through the actual page cycle process is something like this:
search_accounts_aspx
but when I used the activator method above it returns:
Accounts
So the records don't match the in the security table. Is there anyway to programtically "visit" a webpage so that it goes through the actual page lifecycle and I would get back the correct value from the Name parameter?
Any help/reference will be greatly appreciated.
Interesting problem...
Of course there's a (too obvious?) way to programmatically visit the page... use System.Net.HttpWebRequest. Of course, that requires the URI and not just a handle to the object. This is a "how do we get there from here?" problem.
My suggestions would be to simply create another attribute (or use that same one) which stores the identifier you need. Then it will be the same either way you access it, right?
Alternatively... why not just use a 3rd party web spider/crawler to crawl your site and hit all the pages? There are several free options. Or am I missing something?

Resources