I have two p5 sketches, and I want to use them in the same space of a website. So that after clicking a button, the sketches switch. So I made three different files. The first two, are the sketches, and they are wrapped in a function (instance mode). The third sketch is a code written in global mode, because It has the information that loads a button right when the website is first accesed, and it has the information containing what the button is supposed to do: call the other sketches.
The code looks like this:
var playing = false;
var button;
function setup() {
var col = color(185,185,185,150);
button = createButton('Play');
button.position(20,20);
button.parent('black');
button.style("background-color", col);
button.style("padding", "10px 20px");
button.style("font-size", "14px");
button.mousePressed(toggleCanvas); // attach button listener
}
function mousePressed() {
}
function toggleCanvas() {
if (playing) {
if(myp5r){
myp5r.remove();
runSketch();
button.html('Stop');
}else{
runSketch();
button.html('Stop');
}
}else {
if(myp5){myp5.remove();
stopSketch();
button.html('Play');
}else{
stopSketch();
button.html('Play');}
}
playing = !playing;
}
I have been warned, to not mix global and instance mode, although my "common sense" says that it is ok to use a global mode for the button. Because I want it to be loading first, along with the page.
I noticed that weird things happen, though. Like, I get a blank space added beneath the footer, it looks horrible. And, even more worse, button is not appearing in the correct spot in the site. I already ckecked that css has position:relative for example. And the design works in localhost, but not in the site.
Related
I need to add back navigation on swipe. I can do that fairly easily by just adding a swipe listener to the page view and calling goBack. But I really would like the animation that goes with it (in Instagram or FB) where as soon as you start dragging your thumb, the page translates to the right and the previous page starts to translate into view. And then once you get to a certain point it actually performs the navigation.
I tried animating the page, as well as the frame to the right figuring since the view isn't being destroyed it might work. But it doesn't display the page Im navigating back to.
Looking for help on how to accomplish this!
I guess you might have come across the other SO thread answering this question natively.
All you have to do is modify the default gesture recogniser on iOS frame.
export function onNavigatedFrom(args: EventData) {
console.log("Adding gesture...");
const frame = (<Page>args.object).frame;
if (frame.ios && !(<any>frame)._gestureRecognizer) {
const controller = frame.ios.controller;
const popGestureRecognizer = controller.interactivePopGestureRecognizer;
const targets = popGestureRecognizer.valueForKey("targets");
if (targets) {
let gestureRecognizer = UIPanGestureRecognizer.alloc().init();
gestureRecognizer.setValueForKey(targets, "targets");
frame.nativeView.addGestureRecognizer(gestureRecognizer);
(<any>frame)._gestureRecognizer = gestureRecognizer;
}
}
}
export function onNavigatedTo(args: EventData) {
console.log("Back to root page, removing gesture...");
const frame = (<Page>args.object).frame;
if (frame.ios && (<any>frame)._gestureRecognizer) {
frame.nativeView.removeGestureRecognizer((<any>frame)._gestureRecognizer);
(<any>frame)._gestureRecognizer = null;
}
}
Playground Sample
I load a Canvas prefab at runtime when an event occurs. The canvas simply has a Panel inside it, which in turn has 2 buttons. I'm trying to add OnClick events to both these buttons in the script, but it only works for the first button somehow!
I have the following two lines of code one after the other:
GameObject.Find("RestartButton").GetComponent<Button>().onClick.AddListener(() => RestartClicked());
GameObject.Find("ViewButton").GetComponent<Button>().onClick.AddListener(() => ViewClicked());
The callback only works for the RestartButton, and not for the ViewButton.
It may well be a very small thing, but I searched Google and Bing extensively and remain clueless, so any help would be appreciated.
Thanks!
Edit:
The script instantiates the prefab and tries to reference the two buttons in the prefab through GameObject.Find(), given that once Instantiate is called the Canvas should be active in the heirarchy.
I also opened up the part of the code that attaches buttons to the listener for debugging. I dont think it attaches the listener at all.
void Start () {
SetupScene();
var prefab = Resources.Load("RestartOrViewPrefab");
if (prefab == null)
{
Debug.LogAssertion("Prefab missing!");
return;
}
restartCanvas = (GameObject)Instantiate(prefab);
Button btn = GameObject.Find("ViewButton").GetComponent<Button>();
btn.onClick.RemoveAllListeners();
btn.onClick.AddListener(() => ViewToggle());
Button btn2 = GameObject.Find("RestartButton").GetComponent<Button>();
btn2.onClick.AddListener(() => RestartClicked());
}
private void RestartClicked()
{
Debug.Log("RESTARTING");
SetupScene();
}
private void ViewToggle()
{
Debug.Log("TOGGLE");
if (freshStart)
{
//Something here
freshStart = false;
}
else
{
//Something else here
freshStart = true;
}
}
So I took two days to solve my problem. Apparently, doing a GameObject.Find() for a GameObject within a prefab that you just instantiated doesn't work. We always need to use the GameObject that the Instantiate() method returns to find any component within the prefab.
The code I used to make my scene work may not be the best solution if your prefab is very big/complex (say you have 15 buttons and need to do something with one), but it sure does work. :)
I replaced the following lines of code:
Button btn = GameObject.Find("ViewButton").GetComponent<Button>();
btn.onClick.RemoveAllListeners();
btn.onClick.AddListener(() => ViewToggle());
Button btn2 = GameObject.Find("RestartButton").GetComponent<Button>();
btn2.onClick.AddListener(() => RestartClicked());
With the following lines of code:
Button[] buttons = restartCanvas.GetComponentsInChildren<Button>();
foreach(Button but in buttons)
{
if(but.gameObject.name == "RestartButton")
but.onClick.AddListener(() => RestartClicked());
else if(but.gameObject.name == "ViewButton")
but.onClick.AddListener(() => ViewToggle());
}
So I just reused the restartCanvas that I got a reference to.
restartCanvas = (GameObject)Instantiate(prefab);
Hope this helps someone. :)
I answered this on another post, but I'll answer it here for people that still need this info.
The GameObject your instantiated button is a child of must have a CanvasRenderer component on it.
I'm not sure why this works, but it does.
Once the parent of the button GameObject has the CanvasRenderer on it, you can call myButton.onClick.AddListener(() => MyMethod(MyArgs)); as you normally would.
Ok make sure you are not getting any null reference error, and check tht spelling of you buttons , output some debug logs in your second function to see if its even reaching there
I have a screen where we have 4 tabs, each tab should be displayed as per the login priority.
Ex:Department,Role,Employee,Screen are the tabs.
Each tab is having buttons to add,edit,remove the data.
by default when i log with any user its going to the first tab, but not all the users are having the first tab as their requirement.
how can i resolve this to do it dynamically in html client application
As covered towards the end of the following LightSwitch Team blog post, you can programmatically change the tab by using the screen.showTab method:
Creating a wizard-like experience for HTML client (Andy Kung)
However, in order to use this showTab API command when your screen is loading, its use needs to be delayed until the screen has fully displayed. This can be achieved in your screen's created method by using a combination of the jQuery mobile pagechange event (as the LightSwitch HTML Client uses jQuery mobile) and a setTimeout with a zero timeout (to delay the showTab until the loading screen is rendered).
The following shows a brief example of how you can use this approach to dynamically set the initial screen tab:
myapp.BrowseScreen.created = function (screen) {
var initialTabName = localStorage.getItem("Rolename") + "Tab";
$(window).one("pagechange", function (e, data) {
setTimeout(function () {
screen.showTab(initialTabName);
});
});
};
Based on your earlier post it appears that you're using LocalStorage to track your logged in user and their role.
On this basis, the above example assumes that the user's role will be the factor dictating the tab they are shown when the screen loads (the screen is named BrowseScreen in the above example).
It also assumes that your tabs are named after each employee role (suffixed with the text 'Tab') e.g. a user who is assigned the role 'DepartmentManager' would be directed to a tab called 'DepartmentManagerTab'.
Whilst slightly more involved, if you'd prefer to avoid the pagechange and setTimeout it's possible to customise the LightSwitch library to introduce a new navigationComplete screen event. This new event is ideal for executing any operations dependent upon the screen having fully rendered (such as navigating to a different tab using the showTab function).
If you'd like to introduce this additional event, you'll need to reference the un-minified version of the LightSwitch library by making the following change in your HTML client's default.htm file (to remove the .min from the end of the library script reference):
<!--<script type="text/javascript" src="Scripts/msls-?.?.?.min.js"></script>-->
<script type="text/javascript" src="Scripts/msls-?.?.?.js"></script>
The question marks in the line above will relate to the version of LightSwitch you're using.
You'll then need to locate the section of code in your Scripts/msls-?.?.?.js file that declares the completeNavigation function and change it as follows:
function completeNavigation(targetUnit) {
msls_notify(msls_shell_NavigationComplete, { navigationUnit: targetUnit });
var screen = targetUnit.screen;
var intialNavigation = !screen.activeTab;
var selectedTab = targetUnit.__pageName;
if (screen.activeTab !== selectedTab) {
callNavigationUnitScreenFunction(targetUnit, "navigationComplete", [intialNavigation, selectedTab]);
screen.activeTab = selectedTab; // Set at the end of the process to allow the previous selection to be referenced (activeTab)
}
}
function callNavigationUnitScreenFunction(navigationUnit, functionName, additionalParameters) {
var screenObject = navigationUnit.screen;
var constructorName = "constructor";
var _ScreenType = screenObject[constructorName];
if (!!_ScreenType) {
var fn = _ScreenType[functionName];
if (!!fn) {
return fn.apply(null, [screenObject, navigationUnit].concat(additionalParameters));
}
}
}
You can then use this new event in your screens as follows:
myapp.BrowseScreen.navigationComplete = function (screen, navigationUnit, intialNavigation, selectedTab) {
if (intialNavigation) {
var initialTabName = localStorage.getItem("Rolename") + "Tab";
screen.showTab(initialTabName);
}
};
This event fires whenever a navigation event completes (including a change of tab) with the initialNavigation parameter being set to true upon the initial load of the screen and the selectedTab parameter reflecting the selected tab.
Although modification to the LightSwitch library aren't uncommon with some of the more seasoned LightSwitch developers, if you decide to go down this path you'll need to thoroughly test the change for any adverse side effects. Also, if you upgrade your version of LightSwitch, you'll need to repeat the library modification in the new version.
I'm using some external styles on containers in our CMS, one of which is the css background colour, and then we use a CKEditor (4.x) instance to manage the content within the container. One issue is that when you want the container to have a black (#000) background but the editor has a standard white (#FFF) background and you want to use white text, you obviously wouldn't be able to see the text in the editor without MacGyvering some fake backround while you work, or working in a different colour text and then changing to white.... any way you spin it, it's a PITA and certainly not user friendly.
So what we're doing is using the change event from the colour picker in the external form field, to fire a function that changes the editor instance background on the fly. I got the base for this from a previous question (changing the background color for ckEditor):
set_background: function(hex) {
if (typeof CKEDITOR !== "object") { return; }
var editor = CKEDITOR.instances['body'];
if (editor) {
editor.on('instanceReady', function(e) {
// First time
e.editor.document.getBody().setStyle('background-color', hex);
// in case the user switches to source and back
e.editor.on('contentDom', function() {
e.editor.document.getBody().setStyle('background-color', hex);
});
});
}
}
The method is fired once on form load which works great, whatever value is in the colour picker at load is set properly and the editor inherits that background colour. However when I change the colour of the picker it doesn't update the instance. If I remove the instanceReady check however, it'll do the opposite, the load fire won't work but any changes to the picker work perfectly.
I'm guessing the ck instance isn't ready during the first call of my second scenario, meaning I probably must have it there, so my question is, how to I get the follow up calls to function properly like the first call to it does?
Thanks for any insights!
I managed to find a working solution that stores the instance once it's ready and uses that for any future calls...
ck_instance: null,
set_background: function(hex) {
if (this.ck_instance === null) {
if (typeof CKEDITOR !== "object") { return; }
this.ck_instance = CKEDITOR.instances['body'];
if (typeof this.ck_instance !== "object") { return; }
this.ck_instance.on('instanceReady', function(e) {
// First time
e.editor.document.getBody().setStyle('background-color', hex);
// in case the user switches to source and back
e.editor.on('contentDom', function() {
e.editor.document.getBody().setStyle('background-color', hex);
});
});
return;
}
// First time
this.ck_instance.document.getBody().setStyle('background-color', hex);
// in case the user switches to source and back
this.ck_instance.on('contentDom', function() {
this.ck_instance.document.getBody().setStyle('background-color', hex);
});
}
Both required firings are working now, once on form load to set the saved background in the new editor, and again by way of the colour pickers change callback.
I have a Panel that I initially replace with another panel (a spinning circle saying "loading") and after a while in an AJAX event replace back. So what I do is:
#Override
protected void onConfigure() {
if (!content.isLoaded()) {
tmp = new LoadingCircle(getId(), "Loading...");
this.replaceWith(tmp);
}
}
public void onLoaded(AjaxRequestTarget target) {
if (tmp != null) {
tmp.replaceWith(this);
tmp = null;
}
target.add(this);
}
This works, so the panel is shown back in the page. However, this panel has some subpanels with some labels and they are not refreshed. I see the updated labels when I reload the page but not immediately after showing the whole panel with AJAX.
I notice that the onConfigure and onBeforeRender methods are called only once - when the panel is created but not again when it is actually shown for the first time using AJAX. The same for the subpanels, so that would explain why they are not refreshed. But the question is - why is the panel not refreshed (the updated model values are not used) when it is added to the AJAX request target?
EDIT: I think this may be relevant: https://issues.apache.org/jira/browse/WICKET-5107. Still, I wonder what I should change in my code to make it work?
IMO it looks like you should use an AjaxCallDecorator instead to do what you are trying to do with the spinner.