I am facing the same problem as this one as I am trying to figure out how to use crossroads for a few hours now and nothing seems to work. its webiste is just another poor documented site... I think I am probably daft! I wonder if anyone has made it?
html head,
<title>Crossroads</title>
<script src="js/libs/signals.js"></script>
<script src="js/libs/crossroads.min.js"></script>
<script src="js/app.js"></script>
</head>
app.js, just as simple as this,
crossroads.addRoute('/news/{id}', function(id){
alert(id);
});
so I try it out on my localhost browser,
http://localhost/crossroadjs/#/news/123
nothing happens. I thought it would be 123??
Crossroads doesn't handle history/state change events from the browser. From their site:
A routes system shouldn't do anything else besides routing.
Instead, the site recommends Hasher for this purpose and gives a rather complete looking example:
//setup crossroads
crossroads.addRoute('foo');
crossroads.addRoute('lorem/ipsum');
crossroads.routed.add(console.log, console); //log all routes
//setup hasher
function parseHash(newHash, oldHash){
crossroads.parse(newHash);
}
hasher.initialized.add(parseHash); //parse initial hash
hasher.changed.add(parseHash); //parse hash changes
hasher.init(); //start listening for history change
//update URL fragment generating new history record
hasher.setHash('lorem/ipsum');
Alternatively you could use a different history plugin, or write something yourself. But crossroads leaves that part up to you.
Crossroads.js gives crossroads.addRoute(pattern, [handler], [priority]); API to add route patterns. However, when the first time you load the page Crossroads does not automatically initiate the parser to check against the url of the page. You need to add crossroads.parse(document.location.pathname); on you document load to trigger the route. Check out Crossroads.js Tutorial.
Related
I am setting up LaunchDarkly to control my first feature flag and its working fine from server & client side.
Now I am trying LaunchDarkly Bootstrap approach (From the below given Link) and tried like below my code, but it's not accepting the double braces and I do not know How to get flag value by using the bootstrap approach, so where I did go wrong in my code?. Could anyone please help me with an example?
Link,
https://docs.launchdarkly.com/docs/js-sdk-reference#section-bootstrapping
Initialized client with Bootstrap option as below,
client = LDClient.initialize(sdkKey, userContext.user, options = {
bootstrap: {
{{ ldclient.all_flags(userContext.user) }}
}
});
And my function to get the flag value,
isFeatureEnabled: function (featureFlag, properties) {
console.log("Before Variation");
//we shall update the custom properties into user context.
if (properties) {
for (var k in properties) {
userContext.user.custom[k] = properties[k];
}
}
//later make the identity call to update the user details.
client.identify(userContext.user, null, function () { /*rules updated*/
console.log("New user's flags available");
//validate the feature flag
var showFeature = client.variation(featureFlag);
if (!showFeature) {
window.in8.platform.showUnauthorized('');
}
console.log("after Variation");
});
}
Full disclosure, My name is John, and I am part of the support team here at LaunchDarkly. I'll be happy to help you out with this problem
Firstly, it appears you are using an older version of the bootstrapping example. The new example has a typo fix, and uses the new all_flags_state method.
I see two major issues here. There is the primary issue of how to bootstrap flag variations from the back-end to the front-end, and how to appropriately utilize LaunchDarkly when using bootstrapping. I will tackle the issue of how to bootstrap flag variations from the back-end first.
The example in LaunchDarkly's documentation utilizes templating to include the bootstrapped values to the front end. Templating is a strategy for including programmatically generated content in your static source or text files. Templating is commonly used when compiling or deploying code, or at runtime when serving content to clients. This is done to render information only available at that time in the final version.
Different templating languages behave in different ways, but generally speaking you include tokens in your source or text files which direct the template renderer to replace that token with data you supply it.
In the documentation it mentions that this example is for templating using Ruby, but the example is using Mustache rendering, and Mustache is available in many different languages. Templating is a strategy for including programmatically generated content in your static source or text files. This is commonly used when compiling or deploying code, or at runtime when serving content to clients. This is done to render information only available at that time in the final version.
The example may not work depending on which back-end language and framework you are using. According to the tags associated with your question, I feel safe to assume that you are using .NET to power your back-end, which doesn't have a prescribed templating language. There are many open source solutions out there, though.
In the following example I'm going to use https://github.com/rexm/Handlebars.Net to render the a users bootstrapped flag values into the result variable. I am going to borrow code available from the example in the handle bars repo, and from LaunchDarkly's hello-bootstrap and hello-dotnet repos, which are available here: https://github.com/launchdarkly/hello-bootstrap & https://github.com/launchdarkly/hello-dotnet
string source =
#"
<html>
<head>
<script src=""https://app.launchdarkly.com/snippet/ldclient.min.js""></script>
<script>
window.ldBootstrap={{ldBootstrap}};
window.ldClientsideId=""{{ldClientsideId}}"";
window.ldUser={{ldUser}};
</script>
</head>
<body>
<h1>LaunchDarkly server-side bootstrap example</h1>
<ul>
<li><code>normal client</code>: <span class=""normal"">initializing…</span></li>
<li><code>bootstrapped client</code>: <span class=""bootstrap"">initializing…</span></li>
</ul>
<script>
var user = window.ldUser;
console.log(`Clients initialized`);
var client = LDClient.initialize(window.ldClientsideId, user);
var bootstrapClient = LDClient.initialize(window.ldClientsideId, user, {
bootstrap: window.ldBootstrap
});
client.on('ready', handleUpdateNormalClient);
client.on('change', handleUpdateNormalClient);
bootstrapClient.on('ready', handleUpdateBootstrapClient);
bootstrapClient.on('change', handleUpdateBootstrapClient);
function handleUpdateNormalClient(){
console.log(`Normal SDK updated`);
render('.normal', client);
}
function handleUpdateBootstrapClient(){
console.log(`Bootstrapped SDK updated`);
render('.bootstrap', bootstrapClient);
}
function render(selector, targetClient) {
document.querySelector(selector).innerHTML = JSON.stringify(targetClient.allFlags(user), null, 2);
}
</script>
</body>
</html>";
var template = Handlebars.Compile(source);
Configuration ldConfig = LaunchDarkly.Client.Configuration.Default("YOUR_SDK_KEY");
LdClient client = new LdClient(ldConfig);
User user = User.WithKey("bob#example.com")
.AndFirstName("Bob")
.AndLastName("Loblaw")
.AndCustomAttribute("groups", "beta_testers");
var data = new {
ldBootstrap: JsonConvert.SerializeObject(client.AllFlagsState(user)),
ldUser = JsonConvert.SerializeObject(user),
ldClientsideId = "YOUR_CLIENT_SIDE_ID"
};
var result = template(data);
You could take this example and adapt it to render your static source code when serving the page to your users.
The second issue is how you are utilizing the SDK. I see that you are calling identify before evaluating your user every time. Each time you call identify the SDK needs to reinitialize. This means that even after bootstrapping your initial variations you will force the SDK to reinitialize by calling identify, removing all benefits of bootstrapping. As a solution, detect if your user object has changed. if it has, then call identify. Otherwise, do not call identify so that the SDK uses the cached user attributes.
If you want to dive deeper into this and provide us with some more of the source for your wrapper you can reach out to us at support#launchdarkly.com
I'm receiving this error from Google API Oauth:
idpiframe_initialization_failed", details: "Not a valid origin for the client: http://127.0.0.…itelist this origin for your project's client ID
I'm trying to send a request from this local path:
http://127.0.0.1:8887/
And I already added this URL to the Authorized JavaScript origins
section:
This is my code:
<!-- The top of file index.html -->
<html itemscope itemtype="http://schema.org/Article">
<head>
<!-- BEGIN Pre-requisites -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js">
</script>
<script src="https://apis.google.com/js/client:platform.js?onload=start" async defer>
</script>
<!-- END Pre-requisites -->
<!-- Continuing the <head> section -->
<script>
function start() {
gapi.load('auth2', function() {
auth2 = gapi.auth2.init({
client_id: 'MY CLIENT ID.apps.googleusercontent.com',
// Scopes to request in addition to 'profile' and 'email'
//scope: 'https://www.google.com/m8/feeds/'
});
});
}
</script>
</head>
<body>
<button id="signinButton">Sign in with Google</button>
<script>
$('#signinButton').click(function() {
// signInCallback defined in step 6.
auth2.grantOfflineAccess().then(signInCallback);
});
</script>
<!-- Last part of BODY element in file index.html -->
<script>
function signInCallback(authResult) {
if (authResult['code']) {
// Hide the sign-in button now that the user is authorized, for example:
$('#signinButton').attr('style', 'display: none');
// Send the code to the server
$.ajax({
type: 'POST',
url: 'http://example.com/storeauthcode',
// Always include an `X-Requested-With` header in every AJAX request,
// to protect against CSRF attacks.
headers: {
'X-Requested-With': 'XMLHttpRequest'
},
contentType: 'application/octet-stream; charset=utf-8',
success: function(result) {
// Handle or verify the server response.
},
processData: false,
data: authResult['code']
});
} else {
// There was an error.
}
}
</script>
<!-- ... -->
</body>
</html>
How can I fix this?
Reseting Chrome cached solved it for me. Long press on Reload button, then Empty Cache and Hard Reload.
Note: Make sure your Chrome Dev tools panel is open otherwise long press wont work.
I had a very similar issue to yours. I tried to add multiple whitelisted ports from localhost and nothing was working. Ended up deleting the credentials and setting them up again. Must have been a bug on googles end for my setup.
If it's all the same to you, try adding http://localhost:8887 to your authorized JavaScript origins instead. Had that error myself at some point and this fixed it. Know that you will have to use this URL for your request as well event though it translates to http://127.0.0.1:8887/.
I read on several places on the web people use to redo the creation of the credentials to get it to work.
So I did, I created a new credential for the same project and used my new user-id and it worked perfectly... Looks like the edition of the whitelist is a bit flacky...
Nb: I also used localhost instead of 127.0.0.1, IPs are not valid.
I fiddled around for about 10 minutes and then it finally worked when I tried
http://localhost/ in the browser (instead of 127.0.0.1)
Added the url at every place you can do white-lists at:
https://console.developers.google.com/apis/credentials/
I had this same issue; but this is what worked for me:
Open console.developers
Open the project name
Click on the credentials
Under the "name", click on the "web client 1"
Under the "URLs", add "http://localhost:3000"
just my 2 cents.. was able to get it working after deleting and recreating the credentials. Just as suggested above.
In case anyone missed this, next to the save button it does say:
Note: It may take 5 minutes to a few hours for settings to take effect
Waiting fixed this issue for me.
"Not a valid origin for the client" seems to be over-used by Google's API, i.e. it's misleadingly used for authentication errors too.
For people seeing the error, check that the credentials are correct.
(This might explain why it works for some people after re-creating credentials - in some cases, the original credentials might not have been correct).
I solved via adding both http://localhost and http://localhost:8083.
Okay so this is super embarrasing, but for me I was following the docs for the Google Sign-in Web package for a Flutter app, and where it says:
On your web/index.html file, add the following meta tag, somewhere in the head of the document: <meta name="google-signin-client_id" content="YOUR_GOOGLE_SIGN_IN_OAUTH_CLIENT_ID.apps.googleusercontent.com">
I had copied what was listed as my Client ID and pasted it at the beginning and had therefor duplicated the apps.googleusercontent.com portion of the content label in the meta tag. So it might help to make sure you haven't duplicated that!
I just went through all of these solutions before realizing I was putting in
https://localhost:3000
and my dev server was serving up
http://localhost:3000
Stupid, I know, but someone else will probably make the same mistake and perhaps this comment will help them :)
What worked for us was adding a non-localhost domain to the authorized origins. My colleague had his localhost-domains working after adding a non-existing local domain, e.g. http://test-my-app.local.
It might be in case, while you are using same email id for creating client id and for sign-in through webpage
I'm trying to create a burndown chart on a webapp and using the loginkey example code, but switched loginkey to apikey (code below). My API Key is placed where it says CorrectAPIKeyHere, and actual id's for workspace_id and project_id. I have double checked to make sure it's the correct key. Here's what shows up: http://pasteboard.co/P3WXWgPk.png
However, the code works if I'm already logged into Rally. Is there anything I'm missing from my code?
<script type="text/javascript" src="https://rally1.rallydev.com/apps/1.26/sdk.js?apiKey=CorrectAPIKeyHere"></script>
<script type="text/javascript" src="https://rally1.rallydev.com/apps/1.26/sdk.js"></script>
<script type="text/javascript">
function initPage() {
console.log(gon.project_oid);
var rallyDataSource = new rally.sdk.data.RallyDataSource("workspace_id", project_id,"true","false");
console.log($(main_content).width());
var config = {
report: rally.sdk.ui.StandardReport.IterationBurndown,
height: 400,
iterations: iteration_id
};
var report = new rally.sdk.ui.StandardReport(config);
report.display("burndown_chart");
}
rally.addOnLoad(initPage);
</script>
Unfortunately there are a couple different things contributing to your current bad times. API Keys are not supported in App SDK 1.x. They are also not supported by the Analytics1 service which backs that StandardReport component.
So the only way forward is to go back to using LoginKey, which comes with the usual caveats about security, etc. Did you have a working app with LoginKey?
Good news! Api Keys are fully supported now in App SDK 2.1 and the StandardReport component so it should be totally possible to do this now.
Some useful links:
Embedding apps externally:
https://help.rallydev.com/apps/2.1/doc/#!/guide/embedding_apps
The StandardReport component:
https://help.rallydev.com/apps/2.1/doc/#!/api/Rally.ui.report.StandardReport
I'm using selenium python webdriver in order to browse some pages. I want to inject a javascript code in to a pages before any other Javascript codes get loaded and executed. On the other hand, I need my JS code to be executed as the first JS code of that page. Is there a way to do that by Selenium?
I googled it for a couple of hours, but I couldn't find any proper answer!
Selenium has now supported Chrome Devtools Protocol (CDP) API, so , it is really easy to execute a script on every page load. Here is an example code for that:
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {'source': 'alert("Hooray! I did it!")'})
And it will execute that script for EVERY page load. More information about this can be found at:
Selenium documentation: https://www.selenium.dev/documentation/en/support_packages/chrome_devtools/
Chrome Devtools Protocol documentation: https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-addScriptToEvaluateOnNewDocument
Since version 1.0.9, selenium-wire has gained the functionality to modify responses to requests. Below is an example of this functionality to inject a script into a page before it reaches a webbrowser.
import os
from seleniumwire import webdriver
from gzip import compress, decompress
from urllib.parse import urlparse
from lxml import html
from lxml.etree import ParserError
from lxml.html import builder
script_elem_to_inject = builder.SCRIPT('alert("injected")')
def inject(req, req_body, res, res_body):
# various checks to make sure we're only injecting the script on appropriate responses
# we check that the content type is HTML, that the status code is 200, and that the encoding is gzip
if res.headers.get_content_subtype() != 'html' or res.status != 200 or res.getheader('Content-Encoding') != 'gzip':
return None
try:
parsed_html = html.fromstring(decompress(res_body))
except ParserError:
return None
try:
parsed_html.head.insert(0, script_elem_to_inject)
except IndexError: # no head element
return None
return compress(html.tostring(parsed_html))
drv = webdriver.Firefox(seleniumwire_options={'custom_response_handler': inject})
drv.header_overrides = {'Accept-Encoding': 'gzip'} # ensure we only get gzip encoded responses
Another way in general to control a browser remotely and be able to inject a script before the pages content loads would be to use a library based on a separate protocol entirely, eg: Chrome DevTools Protocol. The most fully featured I know of is playwright
If you want to inject something into the html of a page before it gets parsed and executed by the browser I would suggest that you use a proxy such as Mitmproxy.
If you cannot modify the page content, you may use a proxy, or use a content script in an extension installed in your browser. Doing it within selenium you would write some code that injects the script as one of the children of an existing element, but you won't be able to have it run before the page is loaded (when your driver's get() call returns.)
String name = (String) ((JavascriptExecutor) driver).executeScript(
"(function () { ... })();" ...
The documentation leaves unspecified the moment at which the code would start executing. You would want it to before the DOM starts loading so that guarantee might only be satisfiable with the proxy or extension content script route.
If you can instrument your page with a minimal harness, you may detect the presence of a special url query parameter and load additional content, but you need to do so using an inline script. Pseudocode:
<html>
<head>
<script type="text/javascript">
(function () {
if (location && location.href && location.href.indexOf("SELENIUM_TEST") >= 0) {
var injectScript = document.createElement("script");
injectScript.setAttribute("type", "text/javascript");
//another option is to perform a synchronous XHR and inject via innerText.
injectScript.setAttribute("src", URL_OF_EXTRA_SCRIPT);
document.documentElement.appendChild(injectScript);
//optional. cleaner to remove. it has already been loaded at this point.
document.documentElement.removeChild(injectScript);
}
})();
</script>
...
so I know it's been a few years, but I've found a way to do this without modifying the webpage's content and without using a proxy! I'm using the nodejs version, but presumably the API is consistent for other languages as well. What you want to do is as follows
const {Builder, By, Key, until, Capabilities} = require('selenium-webdriver');
const capabilities = new Capabilities();
capabilities.setPageLoadStrategy('eager'); // Options are 'eager', 'none', 'normal'
let driver = await new Builder().forBrowser('firefox').setFirefoxOptions(capabilities).build();
await driver.get('http://example.com');
driver.executeScript(\`
console.log('hello'
\`)
That 'eager' option works for me. You may need to use the 'none' option.
Documentation: https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/capabilities_exports_PageLoadStrategy.html
EDIT: Note that the 'eager' option has not been implemented in Chrome yet...
Hi I create a spa with knockout, amplify and sammy.
If I now click an a link like:
#/page?s=About
it links to url.de/subdirectory/#/page?s=About which is right but the console fires following error:
GET url.de/About 404 (Not Found)
because it should be:
url.de/subdirectory/About
My sammy code is:
var app=$.sammy(function () {
// define prexecutes
// update parameters in appModel from request for all routes
this.before('', function() {
//setParameters(this);
});
// authenticate on any page except for login and logout routes
this.before({except: {path:/\/(login|logout|hp)/}}, function() {
});
// actual routes
// home
this.get('#/', function() {
appModel.page("home");
return false;
});
// content
this.get('#/page', function(eventContext) {
content(eventContext);
});
});
app.run('#/');
How do I get sammy not ignoring my subdirectory in which my site is?
You can try with another custom route definition like this
this.get('#/page/:s', function(eventContext) { // where s is parametre
content(eventContext);
});
also use url like this
#/page/About // it will read 'About' as value of parameter 's'
instead of
#/page?s=About
Hope this helps
I ran into a similar situation myself recently. I could not find any configuration options or workarounds that would allow Sammy.js to route to a subdirectory. My solution was to create a virtual host on the server hosting my app with the subdirectory as the subdomain in order to place the app at the document root. In your case, the virtual server would map from url.de/subdir/About to subdir.url.de/About. I realize that this may not be possible for you (since I don't know how much control you have over your hosting environment), but it got me moving again pretty quickly. Hope this helps.
P.S. As a small aside, I just browsed through the Sammy.js source at https://github.com/quirkey/sammy, and it appears that the subdirectory is stripped out (in error) to fix an IE quirk. https://github.com/quirkey/sammy/blob/master/lib/sammy.js#L301 may be the problem.