I have a website that users with an affiliate URL often visit, for example:
https://demowebsite.com/?ref=550
There is a link that initially has an URL:
https://demowebsite.com/register
Register
How can I make that if there is a part with a ref ID in the address bar like https://demowebsite.com/?ref=550, then the href is transformed into the following by click:
https://subdomain.demowebsite.com/ref/
and add the ref ID at the end as an append:
https://subdomain.demowebsite.com/ref/550
And if there is no affiliate part in the address bar, then the link would remain the same.
Register
I would be grateful for any help.
You can use the location object given in tabs
<script>
var href=location.href
if(href.includes('ref')){
document.getElementById('reg')
.href="https://demowebsite.com/ref/" + href.split('=')[1]
}
</script>
Use the URL api
const affRef = (loc) => {
const url = new URL(loc || location.href); // we can pass a url to test
const ref = url.searchParams.get("ref");
if (ref) {
url.pathname += ref;
url.searchParams.delete("ref")
url.hostname = "subdomain."+url.hostname;
}
return url.href
};
document.getElementById("reg1").href = affRef("https://demowebsite.com/register"); // nothing should happen
document.getElementById("reg2").href = affRef("https://demowebsite.com/?ref=550"); // changed
1. Register<br/>
2. Register
On your site you would not need the LOC or pass the URL
const affRef = () => {
const url = new URL(location.href);
const ref = url.searchParams.get("ref");
if (ref) {
url.pathname += ref;
url.searchParams.delete("ref")
url.hostname = "subdomain."+url.hostname;
}
return url.href
};
document.getElementById("reg1").href = affRef();
1. Register<br/>
2. Register
You can change it from the place where the users are being sent. I'm not very sure, but the code would look something like this:
var searchBar; //Assign the Search bar it's value through ID or however you can
if (searchBar=="www.demowebsite.com/register") {
document.getElementById("a").href = ""; //Your desired link
}
else {
document.getElementById("a").href = ""; //Your desired link
}
Register
Related
I'm a new developer and am currently asked to set up a login / signup page for a Single Page Application in JavaScript. This SPA is in the early stages, since the published version is a multipage application.
Our database already contains the user information. I suppose I would have to work with post and get requests in order to authenticate users?
So far, I have managed to fetch data from the database in json, but I don't know how to handle user input and send it to the database.
A general overview: Our Single Page Application is written in JavaScript. A separate Python file retrieves data from the database, creates specific routes (urls) (which we access in our js files) and stores the data in json.
P.S. the code might be pretty janky, and any suggestions on how to improve or simplify the code are appreciated
rest_server.py:
#app.route(url_prefix + '/json/team/<int:team_id>')
def get_team(team_id):
team = adapter.team_info(team_id)
resp = flask.jsonify(team)
resp.headers['Access-Control-Allow-Origin'] = '*'
return resp
#app.route(url_prefix + '/json/team_ids')
def get_team_ids():
team_ids = adapter.team_ids()
resp = flask.jsonify(team_ids)
resp.headers['Access-Control-Allow-Origin'] = '*'
return resp
main.js (reduced version here, I hope it makes sense):
async function renderPage(path) {
if (!path) {
path = window.location.pathname;
}
console.log(`render page ${path}`);
let renderedPath = await pathHandler.createContent(path);
if (renderedPath && renderedPath != path) {
// if page was rendered under a different name, override history
console.log(`different rendered path ${renderedPath}`);
window.history.replaceState(renderedPath,'', renderedPath);
}
}
/**
* handles back button events on window object
* #param {Event} event event object emitted by window.
*/
function onBackButton(event) {
event.preventDefault();
renderPage();
}
/**
* handles click events on the document interface
* #param {Event} event object on the document interface
*/
function onBodyClick(event) {
var tag = event.target;
// use default behavior if this was not a hyperlink
if (tag.tagName != 'A' || !tag.href || event.button != 0) {
return;
}
// use default behavior if link points to other server
if (tag.origin != window.location.origin) {
return;
}
// use default behavior if path is not supported
if (!pathHandler.isSupported(tag.pathname)) {
return;
}
event.preventDefault();
redirect(tag.pathname);
}
/**
* determines the path prefix, the page is loaded with. at the moment, a path prefix requires an
* indicator string. in future, the path could be transmitted within the HTML page and extracted here
* #returns {String|null} path prefix or null if there is none.
*/
function determinePathPrefix() {
let pathPrefixIndicator = '/sp/';
let path = window.location.pathname;
let index = path.lastIndexOf(pathPrefixIndicator);
if (index >= 0) {
return path.slice(0, index + pathPrefixIndicator.length - 1);
}
return null;
}
function displayTeams() {
contentCreator.createDisplayTeams();
}
const contentElement = document.querySelector('.content');
const headerElement = document.querySelector('.details');
const teamsLi = document.querySelector('#teams');
const baseElements = {
headerElement: headerElement,
contentElement: contentElement
};
const functions = {
displayTeams: displayTeams
}
const pathPrefix = determinePathPrefix();
console.log(`path prefix: ${pathPrefix}`);
const pathHandler = new PathHandler(pathPrefix);
const contentCreator = new ContentCreator(pathHandler, baseElements, functions);
const createDisplayTeams = contentCreator.createDisplayTeams.bind(contentCreator);
const createTeams = contentCreator.createTeams.bind(contentCreator);
pathHandler.addPath('createTeams', '/team_<int:itemId>', createTeams);
pathHandler.addPath('teams', '/teams', createDisplayTeams);
document.body.addEventListener('click', onBodyClick);
teamsLi.addEventListener('click', displayTeams);
window.addEventListener('popstate', onBackButton);
renderPage();
Then there is a PathHandler.js file, which might not be necessary to show here.
Finally, ContentCreator.js, which takes care of the UI (also reduced):
class ContentCreator {
#pathHandler;
#baseElements;
#functions;
/**
* #param {PathHandler} pathHandler path handler to be used for generating links.
* #param {Object} baseElements base HTML elements of which children can be replaced.
* #param {Object} functions functions for reloading or redirecting.
*/
constructor(pathHandler, baseElements, functions) {
this.#pathHandler = pathHandler;
this.#baseElements = baseElements;
this.#functions = functions;
}
// the displayTeams function in main.js calls this function
async createDisplayTeams() {
let paragraphElement = document.createElement('p');
paragraphElement.setAttribute('class', 'teamsList');
const response = await fetch('http://localhost:5000/json/teams');
const teams = await response.json();
for (let i = 0; i < teams.length; i++) {
const id = teams[i].TeamId;
const li = document.createElement('li');
const link = document.createElement('a');
const name = teams[i].Name;
link.innerHTML = name;
li.appendChild(link);
li.setAttribute('class', 'teamLi');
paragraphElement.appendChild(li);
link.setAttribute('href', this.#pathHandler.generatePath('createTeams', {itemId: id}));
}
this.#baseElements.contentElement.replaceChildren(paragraphElement);
}
async createTeams(args) {
const id = args['itemId'];
const infoResponse = await fetch(`http://localhost:5000/json/team/${id}`);
const teamInfo = await infoResponse.json();
const roleInfo = teamInfo['RoleInfoList'];
const members = document.createElement('ul');
const container = document.createElement('div');
container.setAttribute('class', 'teamContainer');
const header = document.createElement('h2');
header.innerHTML = teamInfo['Name'];
container.appendChild(header);
const paragraphElement = document.createElement('p');
if (teamInfo['Email']) {
paragraphElement.innerHTML = teamInfo['Email'];
}
for (let p = 0; p < roleInfo.length; p++) {
const member = document.createElement('li');
member.innerHTML = `${roleInfo[p]['Person Name']}`;
members.appendChild(member);
}
container.appendChild(paragraphElement);
container.appendChild(members);
this.#baseElements.contentElement.replaceChildren(container);
}
}
Now I would like to create a form in ContentCreator.js, which somehow fetches the user input and then makes a database request in order to authenticate the user. The UI code won't be a problem, but how could I fetch and send the data?
Thank you!!
Mina
I have a function to render comments, in which each comment is stored as an object in an array. Comments can have reply comments, in which they have the exact same html and data to render, just their styling is different (via a CSS modifier class).
How can I make this function recursive? The renderReplies(comment.replies) calls a function that is the exact same as renderComments function, just without the mentioned function call renderReplies (as a reply to a reply is the exact same also in styling terms).
const renderComments = (comments) => {
commentsElement.innerHTML = '';
comments.forEach(comment => {
commentsElement.innerHTML += html;
// data-id attribute
const liElements = commentsElement.querySelectorAll('.comment');
const liElement = liElements.item(liElements.length - 1);
liElement.setAttribute('data-id', comment.id);
// author
liElement.querySelector('.comment__author').innerHTML = comment.user.username;
// avatar src & alt attributes
const avatar = liElement.querySelector('.comment__avatar');
avatar.setAttribute('src', comment.user.image.png);
avatar.setAttribute('alt', comment.user.username);
// time since posted
// content
const p = liElement.querySelector('.comment__text');
p.appendChild(document.createTextNode(comment.content));
// score
liElement.querySelector('.comment__score b').innerHTML = comment.score;
// replies
renderReplies(comment.replies);
});
};
Check whether there's a replies property. If it exists, call the function recursively. Since replies won't have replies of their own, you'll stop there.
const renderComments = (comments) => {
commentsElement.innerHTML = '';
comments.forEach(comment => {
commentsElement.innerHTML += html;
// data-id attribute
const liElements = commentsElement.querySelectorAll('.comment');
const liElement = liElements.item(liElements.length - 1);
liElement.setAttribute('data-id', comment.id);
// author
liElement.querySelector('.comment__author').innerHTML = comment.user.username;
// avatar src & alt attributes
const avatar = liElement.querySelector('.comment__avatar');
avatar.setAttribute('src', comment.user.image.png);
avatar.setAttribute('alt', comment.user.username);
// time since posted
// content
const p = liElement.querySelector('.comment__text');
p.appendChild(document.createTextNode(comment.content));
// score
liElement.querySelector('.comment__score b').innerHTML = comment.score;
// replies
if (comment.hasOwnProperty("replies")) {
renderComments(comment.replies);
}
});
};
I have an url like :
?from=353&distance=&page=2
If I clik on a map’s track, I add or reset track to a new value. In the same time I would like to reset the page's value to zéro
function processTrackGeoJSON(feature, layer) {
layer.on("click", () => {
let search = window.location.search;
if(search.includes("track")) {
search = search.replace(/track=\d+/g, 'track=' + feature.properties.id);
}
else {
search += (search.length === 0 ? '?' : '')+'&track='+feature.properties.id;
}
window.location = window.location.pathname + search;
})
}
I'm trying to chaining, but ther don't work :
search.replace(/track=\d+/g, 'track=' + feature.properties.id).replace(/page=\d+/g, 'track=' + 0)
For example, I have an url like :
http://example.com?name=paris&from=353&distance&page=2
After on(click) I get a value like track=37
I would like to add this value and reset the page's value to 0 (or delete it) like
http://example.com?name=paris&from=353&distance=120&trak=37&page=0
or
http://example.com?name=paris&from=353&distance=120&trak=37
I think this will be the better way, check this one. You can use URLSearchParams
const query = '?from=353&distance=&page=2'
const searchParams = new URLSearchParams(query);
const parameterExist = searchParams.get('page');
if(parameterExist){
searchParams.set('page', 1) // with your feature.properties.id
}else{
searchParams.set('page', 0) // default value
}
window.history.replaceState({}, '', `${window.location.pathname}?${searchParams}`);
Update to the question
const url = new URL('http://example.com?name=paris&from=353&distance=120&page=2')
const clickedTrackValue = 37;
const params = new URLSearchParams(url.search);
params.append('track', clickedTrackValue);
params.delete('page') // searchParams.set('page', 0)
console.log(`${url.origin}?${params}`)
// for updating the new url, use the below snippet
//window.history.replaceState({}, '', `${location.pathname}?${params}`);
I have a function prototype that loads data from a path. The trick is that I need to change the path afterward. I tried call, apply, bind and even assign but as I am a novice I did not find the solution.
Here a sample of my code :
Chat.prototype.loadMessages = function() {
this.messagesRef = this.database;
var setMessage = function(data) {
var val = data.val();
this.displayMessage(data.key, val.name, val.text);
}.bind(this);
};
var chat = new Chat
function setPath (newpath) {
chat.loadMessages.messageRef = newpath; // I guess, it is where I'm wrong...
chat.loadMessages(); // It should load messages from the new path in my chat container.
}
As I said I also tried :
chat.loadMessages.call(newpath);
or
var setPath = function(newpath) {
chat.loadMessages(newpath);
}.bind(chat);
setPath();
chat.loadMessages();
But the chat container continues to disclose messages from the old path...
This looks a bit convoluted. Just pass messagesRef as a parameter and make it default to this.database:
Chat.prototype.loadMessages = function(messagesRef = this.database) {
// do whatever is needed with messagesRef
};
chat = new Chat();
chat.loadMessages(); // load from the default location
chat.loadMessages('foobar'); // load from this specific location
It looks like you are creating a function with loadMessages, which is fine but you need to pass in a value to set the new path. Is this more of what you were thinking?
Chat.prototype.loadMessages = function (newPath) {
this.messagesRef = newPath || this.database; // if newPath is empty than default to this.database
var setMessage = function(data) {
var val = data.val();
this.displayMessage(data.key, val.name, val.text);
};
var chat = new Chat
function setPath (newpath) {
chat.loadMessages(newpath);
}
In jQuery how can I check if a user is visiting a particular direct id link url?
For example:
http://mydomain.com/#foo
I this case, I like to check for foo.
Would love something like:
if(jQuery.urlHasHash("foo")) {
//logic here
}
No need for jQuery, your browser gives you all you need with document.location.hash
If you want to check if such an ID exists on your page:
var hash = document.location.hash.replace(/^#/, '');
if (document.location.hash != '' && document.getElementById(hash) {
// or just: $(document.location.hash)
// ...
}
Try this Demo http://jsfiddle.net/7QceB/
This might fit your needs :)
Code
$(function(){
//var href = location.href; // get the url
var href = "http://mydomain.com/#foo"; // example url
var split = href.split("#"); // split the string; usually there'll be only one # in an url so there'll be only two parts after the splitting
var afterSplit = "Error parsing url";
if(split[1] != null){
afterSplit = split[1];
}
// If everything went well shows split[1], if not then de default error message is shown
alert(afterSplit);
});
Try my jsFiddle : jsFiddle here
// it might be from browser & / anywhere else
var url = "http://mydomain.com/#foo";
url = url.split('#').pop().split('?').pop();
var page = url.substring(url.lastIndexOf('/') + 1);
console.log(page); // foo
or just
var url = "http://mydomain.com/#foo";
var page = url.substring(url.lastIndexOf('/') + 1); // #foo
After you can use if statement to know if (page == "foo")