Polymer: Step through array on button click - arrays

I am trying to update the URL bar on a button press, and cycle through JSON objects that are declared in the tag array.
The iterator works fine when the window.location.href = "http://localhost:777/tag/" + this.tag[this.counter]; line is commented out, but gets stuck on the first array item when this line is active.
I think counter gets reset when the page is refreshed. Is there a good way to save the state of the counter so I can cycle through the array as the URL changes?
<template>
<paper-button class="menu-button" on-tap="leftArrowButton">Button Text</paper-button>
</template>
<script>
Polymer({
is: 'sub-menu',
properties: {
tag: {
type: Array,
value: function () {
return ['one', 'two', 'three', 'four'];
}
},
counter: {
type: Number,
value: 0
}
},
leftArrowButton: function (e) {
this.counter = (this.counter + 1) % this.tag.length;
console.log(this.counter);
console.log(this.tag.length);
console.log(this.tag[this.counter]);
console.log("http://localhost:777/tag/" + this.tag[this.counter])
window.location.href = "http://localhost:777/tag/" + this.tag[this.counter];
}
});
</script>

You need a router to manage your app's state between pages. Check out app-route. It was built by the Polymer team as a "web components" approach to routing.

Using your links will reload the page and reset the counter. You might either want to use hashbang in your URLs like http://localhost:777/tag#one or query params like http://localhost:777/tag?choice=one. Prior will prevent a page load, latter won't but lets you parse the link (see below).
If altering the link structure is no option you could read the currently selected option from location.pathname in leftArrowButton, calculate the index of the corresponding tag entry, choose the next and build your link with that:
leftArrowButton: function (e) {
var current = location.href.substr(location.href.lastIndexOf('/') + 1);
var index = this.tag.indexOf(current);
var counter = (index + 1) % tags.length;
...

Related

React - useState appending to the array changes previously appended objects

Hi all,
I have a small react app that is creating (mapping from an array) new tabs (and panels) when there is a new message over the websocket.
There is an initial setup, that is hardcoded for the test purposes which sets up 2 tabs on load, any new ones should be appended to these two.
const INITIAL_ARRAY= [
{
id: 1,
child_component_config: {...}
},
{
id: 2,
child_component_config: {...}
}
];
const template = {
child_component_config: {...}
}
The code, simplifed:
const [current_array, setNewArray] = useState( INITIAL_ARRAY);
export default function ParentComponent() {
useEffect(() => {
const client = new ws...
client.onConnect = function (frame) {
var message = clientDesk.subscribe( '/topic/desks/4', function (message) {
// on message
var new_tab = TEMPLATE;
new_tab.id = Math.max( ...current_array.map( elem => elem.id ) ) + 1;
setActiveTab(new_tab.id);
setNewArray([...current_array, new_tab]);
}
}
}, [ current_array ]);
const tabs = map tabs
cosnt panels = map panels
return(
{tabs}
{panels}
)
The problem:
On first message from the WS the third element is added to the array properly (example-1)
, fourth one is added properly but it also overwrites the third element (example-2)
making them exactly the same. After fourth it gets strange, where some are overwritten and some are not.
I've tried:
Moving the state updating out of useEffect or removing useEffect completly
Storing current_array in a temp var before any logic
Adding a counter to track which tab's id is the latest -> tracking state of just one number works
const [tab_count, setTabCount] = useState( INITIAL_ARRAY.lenght );
Using counter to try to force rendering
Setting up a fixed number of objects in the initial array and just update which ever is needed (with and without counter)
Updating based on the previous value
setNewArray( prevArray => {
logic
return [...prevArray, new_tab];
}
After the first WS message, if the code is changed/saved and webpack compiled, the next message will add a new element to the array properly.
EDIT - Solved:
Managed to solve this by building a new object (instead of using the template) before adding it to the array.

Can I remove parameter from URL generated by video playlist in Elementor

Elementor Pro has a new widget, video playlist. It appends a parameter to the URL, like so: http://aaronpenton.net/ampcreative/vip/about-vip/?playlist=f68425e&video=b8a9967
This is obviously terrible for SEO and UX. Is there a way to remove the ?playlist=f68425e&video=b8a9967 ?
My brother help me with the next script.
Put a "HTML Elementor Widget" with the following:
<script>
function getURLParameter(name) {
return decodeURI((RegExp(name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1]);
}
function hideURLParams() {
//Parameters to hide (ie ?playlist=value, ?video=value, etc)
var hide = ['playlist','video'];
for(var h in hide) {
if(getURLParameter(h)) {
history.replaceState(null, document.getElementsByTagName("title")[0].innerHTML, window.location.pathname);
}
}
}
window.onload = hideURLParams;
</script>
This should do the trick.
const url = 'http://aaronpenton.net/ampcreative/vip/about-vip/?playlist=f68425e&video=b8a9967'
url.replace(url.split('/')[6], '')
split, well.. splits the string into an array by the /
character.
At index 6 the array contains the ?playlist=f68425e&video=b8a9967 substring which can than be removed (i.e. replaced by the empty string) using replace.
A more general approach to removing the last part of the url might
be to use the array length instead of specifying the index:
const url = 'http://aaronpenton.net/ampcreative/vip/about-vip/?playlist=f68425e&video=b8a9967'
const urlArr = url.split('/')
url.replace(urlArr[urlArr.length - 1], '')
Update:
Another way to do this is using the URL API
const url = new URL('http://aaronpenton.net/ampcreative/vip/about-vip/?playlist=f68425e&video=b8a9967');
const result = url.origin + url.pathname
or in a function:
const removeParameter = u => {
const url = new URL(u);
return url.origin + url.pathname
}
You might have to check the specification for further details (browser support etc)

external redirection in AngularJS erasing navigation stack

We have set up different applications something like micro frontends running in different versions of Angular, one of them which is in AngularJS is required to redirect to a url which is in another project. Everything works until you try to go back using the browsers back button, and it takes you to the previous domain the user has navigated to. It can't go back to the immediately previous URL. It seems the navigation has been replaced but I can't see anything on the project that uses location.replace.
for example:
I am navigating
www.anyurl.com
then i go to my projects dns like
myproject.com/employer/dashboard
after I can click on to desired button which will take me to
myproject.com/employer/job-flow#location
Up to there everything is fine, but If I click on the browsers back button instead of taking me to:
myproject.com/employer/dashboard
It will go to the previous domain:
www.anyurl.com
I hope this is a clear explanation
from here: /employer/search to /employer/job-flow#location
The Process:
Declare a new item in the menu:
..., {
title: 'Post a job',
mainPath: 'job-flow',
fallbackUrl: 'employer/job-flow',
image: '/assets/images/new-job.svg',
notification: false,
subitems: [],
enabled: true
}
In the HTML there is a:
ng-href="{{ item.fallbackUrl }}"
Then there is an angular module which stores an array with all the routes:
var employerWebRoutes = [
...
'employer/job-flow'
];
Afterwards the array is iterated (I think it works like an interceptor for the given routes):
employerWebRoutes.forEach( function ( route ) {
$stateRegistryProvider.register( {
url: '/' + route + '{path:.*}',
name: route + 'ExternalState',
component: 'merlExternalRoutesComponent',
resolve: {
reloadFromServer: reloadFromServerResolver
},
data: {
authAccess: 'private',
isExternalRoute: true
}
} );
} );
And lastly the reloadFromServerResolver method
var reloadFromServerResolver = [
'$transition$',
'$q',
function (
$transition$,
/** angular.IQService */ $q
) {
var /** #type module:angular.ui.IStateService */ stateService = $transition$.router.stateService;
var /** #type string */ toUrl = stateService.href( $transition$.to().name, $transition$.params() );
setTimeout( function () {
window.location.assign( toUrl );
}, 10 );
return $q.reject();
}
];
I am guessing this is how is done, I am new to this project and can't figure very well how to describe this problem, if anyone can point in the right direction I would be highly grateful. Thanks

Migrating jQuery selector to angularjs for third party vendor client help functionality

I'm trying to migrate old jQuery code to angularjs.
The issue that I'm having is that I'm not sure on the best approach.
Bascially, depending on the selector a different type of 'event' needs to be pushed into a array called gt.
The purpose of the jQuery code is to provide detailed info of clients having issues while filling in a form. the gt array is picked up by third party software that helps the clients by asking if they want to chat.
Example of how the array is populated:
$('a').live('click', { element: this }, function (element) {
_clickedElement = this;
var linkUrl = element.currentTarget.hostname + element.currentTarget.pathname;
var querystring = window.location.search
var shortLocationUrl = window.location.href.replace(querystring, "").replace("http://", "").replace("https://", "");
if (element.currentTarget.hostname.length > 0 && element.currentTarget.target != "_blank" && linkUrl != shortLocationUrl) { //click on a link that opens in the current window and points to a page external to this part
_gt.push(['event', { eventName: 'Leave_Page_' + chat.name, name: chat.name, pageName: chat.pageName, locale: _locale, isClient: chat.isClient }]);
_pushLeavePageEvent = false;
}
else if (this.id == backButtonId) { //click "previous"
_gt.push(['event', { eventName: 'Go_Back_' + chat.name, name: chat.name, pageName: chat.pageName, locale: _locale, isClient: chat.isClient }]);
_pushLeavePageEvent = false;
}
return true;
});
So for all the a tags inside my page (or form) the above code needs to be executed.
What would be a good approach to have similar behaviour in Angularjs?
I was thinking of a directive but I'm not sure whether to make this a directive at the level of my form or make a directive that I then use throughout my page?
P.S.: similar behaviour is needed (pushing an event into the gt array) for all the input, textarea and select fields on the page as well as the errors on the page caused by the clients and when a client hovers over a tooltip.

Reverse a route in Backbone js

Similar to Django's {{ url }}, is there a method or way to reverse a particular route by passing it a name and variables.
// example Router
var router = Backbone.Router.extend({
routes: {
'!/user/:user_id': 'editUserAction',
'!/': 'homeAction'
},
editUserAction(user_id) {
// edit user view
},
homeAction() {
// home view
}
});
Some method like
router.reverse('editUserAction', '5');
Would return the hash: !/user/5
router.reverse('homeAction');
Would return the hash: !/
A discussion about reverse routing. https://github.com/documentcloud/backbone/issues/951
a simple hack
var personRoutes = {
list: "/persons",
show: "/persons/:id",
edit: "/persons/:id/edit"
}
var getRoute = function(obj, route, routeDefinitions){
return routeDefinitions[route].replace(":id", obj.id);
}
var person = new Model({id: 1});
var route = getRoute(person, "edit", personRoutes); // => "/persons/1/edit"
Unfortunately no, there isn't anything like this built in to backbone. I've wanted something similar and there has been discussion of this on the list once or twice - maybe even a pull request (don't remember for sure at the moment). But it has not yet been done.
The best that I've come up with is to write my own methods that produce the correct route string:
function userEditPath(userId){
return "/user/" + userId + "/edit";
}

Resources