How to make a text field link be opened in a new tab, in Velo? - text

In Wix, I have a text field in a repeater that is used for navigating to other dynamic pages. The link works, but there are two problems with that. First, I have to click two times, not double click, for functioning the link. Second, I want to make the text field act as a button link, I mean be able to right click on that and choose 'open in new tab'. How can I fix these problems in my code?
Here is the code
// Navigating to related dynaic page
import wixLocation from 'wix-location';
export function ndText_click(event) {
$w("#repeater1").onItemReady(($item, itemData, index) => {
$item("#nText").onClick((event) => {
let postTypeValue = itemData.pType
wixData.query("Collection1").eq("_id", itemData._id)
.find()
.then(results => {
let item = results.items[0];
let pIDValue = item.postId;
if (postTypeValue == "R") {
wixLocation.to('/re/' + postIDValue);
} else if (postTypeValue == "L") {
wixLocation.to('/lo/' + postIDValue);
}
})
});
})
}

I suggest trying to use a button instead of the text element. You can usually style the button so it looks the same as the text element you already have. Then instead of setting the onClick, try setting the button's link and target properties.

Related

How to remove view sub-menu in electron app for main window

Hi i want to remove 3 options from electron title menu they are
reload
Force reload
Toggle developer tools
as shown below
Here is what i have tried
background.js
import { app, session, protocol, BrowserWindow , dialog, ipcMain, Menu} from 'electron'
const menu = Menu.getApplicationMenu(); // get default menu
console.log('menu %s',menu.items);
let menuIndex = menu.items.findIndex(o => {
return o.role == 'viewmenu'
})
//splice items based on names , i'm not able to do that because i cannot see the full json object and its structure in console.log
//Menu.setApplicationMenu(menu); //set menu
Further i don't know what to do
Please help me thanks in advance !!
You can create a new menu based on the default using Menu.buildFromTemplate and pass the default's menu items as template.
Then set that as application menu. During the construction you can cut out elements you don't want
const menu = Menu.getApplicationMenu(); // get default menu
// build a new menu based on default one
const newmenu = Menu.buildFromTemplate(
menu.items.map(i => {
// overwrite viewmenu item
if (i.role === 'viewmenu') {
// create new submenu
const newviewsub = Menu.buildFromTemplate(
i.submenu.items.slice(4) // cut first 4 item (4th is separator)
)
// replace this item's submenu with the news
return Object.assign({}, i, { submenu: newviewsub })
}
// otherwise keep
return i
})
)
Menu.setApplicationMenu(newmenu)
You should see that the 'view' menu's first 3 element is gone

React Popper - updates position dynamically when adding content to the Popover

I have a Popover containing a list + "Add item" button, so the user can dynamically add items to the list (after 3 items the list gets overflow). The problem starts if the Popover open in the bottom of the window and contain less than 3 items, then the user clicks the "Add item" button, the Popover gets more height thus part of it is outside of the window.
I want to force the Popover to update and gets the right position (Modifiers, ResizeObserver..) but I can't find the right way to make it work.
Any suggestions?
For example:
const observeReferenceModifier = {
name: 'observeReferenceModifier',
enabled: true,
phase: 'write',
effect: ({ state, instance }) => {
const RO_PROP = '__popperjsRO__';
const { reference } = state.elements;
reference[RO_PROP] = new ResizeObserver(entries => {
console.log('size-updated: ', reference.id);
instance.update();
});
reference[RO_PROP].observe(reference);
return () => {
console.log('unobserve: ', reference);
reference[RO_PROP].disconnect();
delete reference[RO_PROP];
};
},
};

How can I avoid a hover in protractor?

I want to click on an element, but I don't know why, before clicking on that element the hover appears. What I need is that if this hover appears, avoid it, such as pressing the ESC key, or if you know any other way.
Here is my code:
await browser.wait(EC.elementToBeClickable(element.all(by.className('center-align short-label white mf-show-type-episode')).first()), waitLongTime);
var elements_master = await element.all(by.className('center-align short-label white mf-show-type-episode'));
await elements_master[0].click();
var row_selected = browser.element(by.className('ui-grid-row ng-scope ui-grid-row-selected')).element(by.className('field-link ng-binding'));
await browser.sleep(500);
if(await tooltip.isDisplayed() == true) {
await tooltip.sendKeys(protractor.Key.ESCAPE);
await row_selected.click();
} else {
await row_selected.click();
}
It gives me an error that the tooltip is not interactable.
you can use javscript click described here
var loginButton = element(by.css('.login-form .login-button'));
browser.executeScript("arguments[0].click();", loginButton);
you can also call it "forced" click, because what it does is - it clicks on the element regardless its visibility. And even if there is another element on top of it, it will click the element you pass

React Native: Reach-Navigation and Pouch-DB - db.put not done before "refresh" callback is run

Relative newbie; forgive me if my etiquette and form here aren't great. I'm open to feedback.
I have used create-react-native-app to create an application using PouchDB (which I believe ultimately uses AsyncStorage) to store a list of "items" (basically).
Within a TabNavigator (main app) I have a StackNavigator ("List screen") for the relevant portion of the app. It looks to the DB and queries for the items and then I .map() over each returned record to generate custom ListView-like components dynamically. If there are no records, it alternately displays a prompt telling the user so. In either case, there is an "Add Item" TouchableOpacity that takes them to a screen where they an add a new item (for which they are taken to an "Add" screen).
When navigating back from the "Add" screen I'm using a pattern discussed quite a bit here on SO in which I've passed a "refresh" function as a navigation param. Once the user uses a button on the "Add" screen to "save" the changes, it then does a db.post() and adds them item, runs the "refresh" function on the "List screen" and then navigates back like so:
<TouchableOpacity
style={styles.myButton}
onPress={() => {
if (this.state.itemBrand == '') {
Alert.alert(
'Missing Information',
'Please be sure to select a Brand',
[
{text: 'OK', onPress: () =>
console.log('OK pressed on AddItemScreen')},
],
{ cancelable: false }
)
} else {
this.createItem();
this.props.navigation.state.params.onGoBack();
this.props.navigation.navigate('ItemsScreen');
}
}
}
>
And all of this works fine. The "refresh" function (passed as onGoBack param) works fine... for this screen. The database is called with the query, the new entry is found and the components for the item renders up like a charm.
Each of the rendered ListItem-like components on the "List screen" contains a react-native-slideout with an "Edit" option. An onPress for these will send the user to an "Item Details" screen, and the selected item's _id from PouchDB is passed as a prop to the "Item Details" screen where loadItem() runs in componentDidMount and does a db.get(id) in the database module. Additional details are shown from a list of "events" property for that _id (which are objects, in an array) which render out into another bunch of ListItem-like components.
The problem arises when either choose to "Add" an event to the list for the item... or Delete it (using another function via [another] slideout for these items. There is a similar backward navigation, called in the same form as above after either of the two functions is called from the "Add Event" screen, this being the "Add" example:
async createEvent() {
var eventData = {
eventName: this.state.eventName.trim(),
eventSponsor: this.state.eventSponsor.trim(),
eventDate: this.state.eventDate,
eventJudge: this.state.eventJudge.trim(),
eventStandings: this.state.eventStandings.trim(),
eventPointsEarned: parseInt(this.state.eventPointsEarned.trim()),
};
var key = this.key;
var rev = this.rev;
await db.createEvent(key, rev, eventData);
}
which calls my "db_ops" module function:
exports.createEvent = function (id, rev, eventData) {
console.log('You called db.createEvent()');
db.get(id)
.then(function(doc) {
var arrWork = doc.events; //assign array of events to working variable
console.log('arrWork is first assigned: ' + arrWork);
arrWork.push(eventData);
console.log('then, arrWork was pushed and became: ' + arrWork);
var arrEvents = arrWork.sort((a,b)=>{
var dateA = new Date(a.eventDate), dateB = new Date(b.eventDate);
return b.eventDate - a.eventDate;
})
doc.events = arrEvents;
return db.put(doc);
})
.then((response) => {
console.log("db.createEvent() response was:\n" +
JSON.stringify(response));
})
.catch(function(err){
console.log("Error in db.createEvent():\n" + err);
});
}
After which the "Add Event" screen's button fires the above in similar sequence to the first, just before navigating back:
this.createEvent();
this.props.navigation.state.params.onGoBack();
this.props.navigation.navigate('ItemsDetails');
The "refresh" function looks like so (also called in componentDidMount):
loadItem() {
console.log('Someone called loadItem() with this.itemID of ' + this.itemID);
var id = this.itemID;
let totalWon = 0;
db.loadItem(id)
.then((item) => {
console.log('[LOAD ITEM] got back data of:\n' + JSON.stringify(item));
this.setState({objItem: item, events: item.events});
if (this.state.events.length != 0) { this.setState({itemLoaded: true});
this.state.events.map(function(event) {
totalWon += parseInt(event.eventPointsEarned);
console.log('totalWon is ' + totalWon + ' with ' +
event.eventPointsEarned + ' having been added.');
});
};
this.setState({totalWon: totalWon});
})
.catch((err) => {
console.log('db.loadItem() error: ' + err);
this.setState({itemLoaded: false});
});
}
I'm at a loss for why the List Screen refreshes when I add an item... but not when I'm doing other async db operations with PouchDB in what I think is similar fashion to modify the object containing the "event" information and then heading back to the Item Details screen.
Am I screwing up with Promise chain someplace? Neglecting behavior of the StackNavigator when navigating deeper?
The only other difference being that I'm manipulating the array in the db function in the non-working case, whereas the others I'm merely creating/posting or deleting/removing the record, etc. before going back to update state on the prior screen.
Edit to add, as per comments, going back to "List screen" and the opening "Item Details" does pull the database data and correctly shows that the update was made.
Further checking I've done also revealed that the console.log in createEvent() to print the response to the db call isn't logging until after some of the other dynamic rendering methods are getting called on the "Item Details" screen. So it seems as though the prior screen is doing the get() that loadItem() calls before the Promise chain in createEvent() is resolving. Whether the larger issue is due to state management is still unclear -- though it would make sense in some respects -- to me as this could be happening regardless of whether I've called my onGoBack() function.
Edit/bump: I’ve tried to put async/await to use in various places in both the db_ops module on the db.get() and the component-side loadItem() which calls it. There’s something in the timing of these that just doesn’t jive and I am just totally stuck here. Aside from trying out redux (which I think is overkill in this particular case), any ideas?
There is nothing to do with PDB or navigation, it's about how you manage outer changes in your depending (already mounted in Navigator since they are in history - it's important to understand - so componentDidMount isn't enough) components. If you don't use global state redux-alike management (as I do) the only way to let know depending component that it should update is passing corresponding props and checking if they were changed.
Like so:
//root.js
refreshEvents = ()=> { //pass it to DeleteView via screenProps
this.setState({time2refreshEvents: +new Date()}) //pass time2refreshEvents to EventList via screenProps
}
//DeleteView.js
//delete button...
onPress={db.deleteThing(thingID).then(()=> this.props.screenProps.refreshEvents())}
//EventList.js
...
constructor(props) {
super(props);
this.state = {
events: [],
noEvents: false,
ready: false,
time2refreshEvents: this.props.screenProps.time2refreshEvents,
}
}
static getDerivedStateFromProps(nextProps, currentState) {
if (nextProps.screenProps.time2refreshEvents !== currentState.time2refreshEvents ) {
return {time2refreshEvents : nextProps.screenProps.time2refreshEvents }
} else {
return null
}
}
componentDidMount() {
this._getEvents()
}
componentDidUpdate(prevProps, prevState) {
if (this.state.time2refreshEvents !== prevState.time2refreshEvents) {
this._getEvents()
}
}
_getEvents = ()=> {
//do stuff querying db and updating your list with actual data
}

recognize multple lines on info.selectionText from Context Menu

My extension adds a context menu whenever a user selects some text on the page.
Then, using info.selectionText, I use the selected text on a function executed whenever the user selects one of the items from my context menu. (from http://code.google.com/chrome/extensions/contextMenus.html)
So far, all works ok.
Now, I got this cool request from one of the extension users, to execute that same function once per line of the selected text.
A user would select, for example, 3 lines of text, and my function would be called 3 times, once per line, with the corresponding line of text.
I haven't been able to split the info.selectionText so far, in order to recognize each line...
info.selectionText returns a single line of text, and could not find a way to split it.
Anyone knows if there's a way to do so? is there any "hidden" character to use for the split?
Thanks in advance... in case you're interested, here's the link to the extension
https://chrome.google.com/webstore/detail/aagminaekdpcfimcbhknlgjmpnnnmooo
Ok, as OnClickData's selectionText is only ever going to be text you'll never be able to do it using this approach.
What I would do then is inject a content script into each page and use something similar to the below example (as inspired by reading this SO post - get selected text's html in div)
You could still use the context menu OnClickData hook like you do now but when you receive it instead of reading selectionText you use the event notification to then trigger your context script to read the selection using x.Selector.getSelected() instead. That should give you what you want. The text stays selected in your extension after using the context menu so you should have no problem reading the selected text.
if (!window.x) {
x = {};
}
// https://stackoverflow.com/questions/5669448/get-selected-texts-html-in-div
x.Selector = {};
x.Selector.getSelected = function() {
var html = "";
if (typeof window.getSelection != "undefined") {
var sel = window.getSelection();
if (sel.rangeCount) {
var container = document.createElement("div");
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
html = container.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
return html;
}
$(document).ready(function() {
$(document).bind("mouseup", function() {
var mytext = x.Selector.getSelected();
alert(mytext);
console.log(mytext);
});
});​
http://jsfiddle.net/richhollis/vfBGJ/4/
See also: Chrome Extension: how to capture selected text and send to a web service

Resources