For the first time in my live i make a Tampermonkey script.
I want add multiple url's to a page: https://voertuig.net/zoek/merk/volkswagen/datum-tenaamstelling/30-05-2018?pagina=3
But i don't know how to get all different licenseplates for the custom urls. He now take the first licenseplate div.
url must be: https://finnik.nl/kenteken/XX-XX-XX/gratis
As you can see, all urls have the same licenseplate
// ==UserScript==
// #name New Userscript
// #namespace http://tampermonkey.net/
// #version 0.1
// #description try to take over the world!
// #author You
// #match https://voertuig.net/zoek/merk/volkswagen/datum-tenaamstelling/30-05-2018?pagina=3
// #icon https://www.google.com/s2/favicons?sz=64&domain=voertuig.net
// #grant none
// ==/UserScript==
(function() {
"use strict"
// Your code here...
var adduserinfo = $("div.voertuig > a");
var Username = $("div.kenteken");
var words = Username.html().split(' ');
adduserinfo.each (function () {
var jThis = $(this);
jThis.parent ().append ('Finnik ' + words + ' ');
} );
})()
Something like this should do it.
Note that you need to modify the //#match line or it will only work for the given page (i.e. page 3 -- just end the line with a * at the point where the match can be wild-carded.
// ==UserScript==
// #name voertuig.net SO EXAMPLE
// #namespace http://tampermonkey.net/
// #match https://voertuig.net/zoek/merk/volkswagen/datum-tenaamstelling/30-05-2018?pagina=3
// #grant none
// ==/UserScript==
(function() {
'use strict';
//Look closely - this is not jQuery
const $ = document.querySelector.bind(document);
const $$ = document.querySelectorAll.bind(document);
$('body').insertAdjacentHTML('beforeend', init_css() );
$$('.voertuig').forEach((div) => {
const lp = div.getAttribute('data-kentekenplaat');
div.insertAdjacentHTML('beforeend', `<a target='_blank' class='finTagA' href='https://finnik.nl/kenteken/${lp}/gratis#historie'>Finnik ${lp}</a>`);
});
})();
function init_css(){
return `
<style id="jdInitCss">
.finTagA{width:100%;padding:5px;display:flex;justify-content:center;background:white;border-top:1px solid #ccccccCC;}
.finTagA:hover{color:blue;}
</style>
`;
}
Related
So I'm going to publish my Tampermonkey userscript (It's a button to get you to a random link in the list) to the Chrome Web Store, I have been testing it today and I got an error:
Uncaught TypeError: $ is not a function
at Chain Finder.user.js:258
at Chain Finder.user.js:261
If you want to take a look at my script:
(function() {
const $ = window.$;
var randomLink = function () {
// Beggining of target list
var links = [
"torn.com/profiles.php?XID=2410074",
"torn.com/profiles.php?XID=2393322",
"torn.com/profiles.php?XID=2049797",
"torn.com/profiles.php?XID=2268673",
"torn.com/profiles.php?XID=2059647"
// More links.... but I cut them so it's easier to understand.
];
// End of target list
// by counting the number of links in the array
var max = (links.length)
// now generate a random number
var randomNumber = Math.floor(Math.random()*max);
// use that random number to retrieve a link from the array
var link = links[randomNumber];
// change the location of the window object
return "https://" + link;
}
// Opens a new tab.
function openInNewTab(url) {
var win = window.open(url, '_blank');
win.focus();
}
function main() {
$('.buttons-list').append(`<a id="mc-btn" href="#" class="profile-button" style="width:99px;text-align:center">
<img src='https://i.imgur.com/TQdk3Pp.png'>
</a>`);
$('#mc-btn').on('click', () => openInNewTab(randomLink()));
}
//Here's the error:
$(document).ready(() => {
main();
});
})();
If you could tell me what's wrong in there, I will be very grateful.
Make sure that somewhere in your script that you include these two lines of code, put var $ = window.jQuery; above where you code starts, and put // #require http://code.jquery.com/jquery-3.4.1.min.js somewhere up top with the rest of the // lines.
Example:
// ==UserScript==
// #name Example
// #namespace http://tampermonkey.net/
// #version 0.1
// #description
// #author Username
// #require http://code.jquery.com/jquery-3.4.1.min.js
// #grant GM_addStyle
// #grant GM.listValues
// #grant GM_setValue
// #grant GM_getValue
// #match *
// #match https://*/*
// #match http://*/*
// #match *://*/*
// ==/UserScript==
(function() {
'use strict';
// Your code here...
})();
var $ = window.jQuery;
That error is usually displayed if Jquery is not included in the script.
I can't describe controllers methods. How i can do this?
/**
* #ngdoc controller
* #name works.controller:worksCtrl
* #requires $http
* #requires $element
* #function
*
* #description
* Description for works controller. All methods will be writen later
*/
var worksCtrl = function ($http, $element) {
var ctrl = this;
//how it do there? this not work
/**
* #name initializeGrid
* #function
* #description
* Description for initializeGrid
*/
ctrl.initializeGrid = function (a) {
//...
}
ctrl.getTemplate = function (workIndex) {
//...
}
//...
};
I am using ngdoc for auto generate documentation. But i can't understand what i do wrong.
I have never used ngdoc but looking to angular code itself, it looks that you need to add a #ngdoc method tag to the documentation for internal functions. For example, inside $locationProvider:
/**
* #ngdoc method
* #name $locationProvider#hashPrefix
* #description
* #param {string=} prefix Prefix for hash part (containing path and search)
* #returns {*} current value if used as getter or itself (chaining) if used as setter
*/
this.hashPrefix = function(prefix) {
if (isDefined(prefix)) {
hashPrefix = prefix;
return this;
} else {
return hashPrefix;
}
};
I hope it helps.
/**
* #ngdoc function
* #name initializeGrid
* #methodOf works.controller:worksCtrl
* #description This method initialize auto grid system for works
* #private
*/
ctrl.initializeGrid = function () {
...
}
That is what i need.)
I'm using DaftMonk's generator-angular-fullstack for a project with everything set as default,
I find myself needing socket authentication with it so I have enabled "socketio-jwt" on the socketio.js
and on the Angular service.
This is how my Angular service looks like:
/* global io */
'use strict';
angular.module('myApp')
.factory('socket', function(socketFactory, Auth) {
// socket.io now auto-configures its connection when we ommit a connection url
var ioSocket = io('', {
// Send auth token on connection, you will need to DI the Auth service above
query: 'token=' + Auth.getToken(),
path: '/socket.io-client'
});
var socket = socketFactory({
ioSocket: ioSocket
});
return {
socket: socket,
/**
* Register listeners to sync an array with updates on a model
*
* Takes the array we want to sync, the model name that socket updates are sent from,
* and an optional callback function after new items are updated.
*
* #param {String} modelName
* #param {Array} array
* #param {Function} cb
*/
syncUpdates: function (modelName, array, cb) {
cb = cb || angular.noop;
/**
* Syncs item creation/updates on 'model:save'
*/
socket.on(modelName + ':save', function (item) {
var oldItem = _.find(array, {_id: item._id});
var index = array.indexOf(oldItem);
var event = 'created';
// replace oldItem if it exists
// otherwise just add item to the collection
if (oldItem) {
array.splice(index, 1, item);
event = 'updated';
} else {
array.push(item);
}
cb(event, item, array);
});
/**
* Syncs removed items on 'model:remove'
*/
socket.on(modelName + ':remove', function (item) {
var event = 'deleted';
_.remove(array, {_id: item._id});
cb(event, item, array);
});
},
/**
* Removes listeners for a models updates on the socket
*
* #param modelName
*/
unsyncUpdates: function (modelName) {
socket.removeAllListeners(modelName + ':save');
socket.removeAllListeners(modelName + ':remove');
}
};
});
This is how my socketio file on the server looks like:
/**
* Socket.io configuration
*/
'use strict';
var config = require('./environment');
// When the user disconnects.. perform this
function onDisconnect(socket) {
}
// When the user connects.. perform this
function onConnect(socket) {
//I dont have any decoded_token here
console.log(socket.handshake.decoded_token._id, 'connected');
// When the client emits 'info', this listens and executes
socket.on('info', function (data) {
console.info('[%s] %s', socket.address, JSON.stringify(data, null, 2));
});
// Insert sockets below
require('../api/conversation/conversation.socket').register(socket);
}
module.exports = function (socketio) {
// socket.io (v1.x.x) is powered by debug.
// In order to see all the debug output, set DEBUG (in server/config/local.env.js) to including the desired scope.
//
// ex: DEBUG: "http*,socket.io:socket"
// We can authenticate socket.io users and access their token through socket.handshake.decoded_token
//
// 1. You will need to send the token in `client/components/socket/socket.service.js`
//
// 2. Require authentication here:
// socketio.use(require('socketio-jwt').authorize({
// secret: config.secrets.session,
// handshake: true
// }));
socketio.use(require('socketio-jwt').authorize({
secret: config.secrets.session,
handshake: true
}));
socketio.on('connection', function (socket) {
socket.address = socket.handshake.address !== null ?
socket.handshake.address.address + ':' + socket.handshake.address.port :
process.env.DOMAIN;
socket.connectedAt = new Date();
// Call onDisconnect.
socket.on('disconnect', function () {
onDisconnect(socket);
console.info('[%s] DISCONNECTED', socket.address);
});
// Call onConnect.
onConnect(socket);
console.info('[%s] CONNECTED', socket.address);
});
};
I have read this blog post about socket authentication, and expected my socket to have a decoded_token value but it does not, I verified that the jwt sign attaches the userId to the token
but I still don't see it...
This is my jwt sign:
/**
* Returns a jwt token signed by the app secret
*/
function signToken(id) {
return jwt.sign({ _id: id }, config.secrets.session, { expiresInMinutes: 60*5 });
}
/**
* Set token cookie directly for oAuth strategies
*/
function setTokenCookie(req, res) {
if (!req.user) return res.json(404, { message: 'Something went wrong, please try again.'});
var token = signToken(req.user._id, req.user.role);
res.cookie('token', JSON.stringify(token));
}
My question is this, how do I get the current user info attached to the socket? (just the id is fine).
Silly me, it seems like I was looking for the decoded token in the wrong place, it was here:
socket.decoded_token._id
Angular adds 'ng-dirty' class to input field when the input field is modified irrespective of whether newValue==oldValue or not.
i.e. if the input value is 'manohar', and i delete 'r' and add it back. Even though the value is 'manohar'( original value), the 'ng-dirty' class still exists.
Is there a way to check whether the input value is modified or not(newValue != oldValue)?
Thanks in advance.
If you want to handle behavior depending on the actual state of data in a form (edit vs original) you need to keep track of that yourself. Like Cétia sais, dirty/prestine is just to keep track of interaction and validation, not state.
It might be overkill but I usually do something like this:
.controller('MyController', function ($scope, Restangular) {
/**
* #ngdoc property
* #name _dataWatcher
* #private
* #propertyOf MyController
*
* #description
* Holds the watch stop-method, if the "data-has-changed" watcher is active.
*/
var _dataWatcher;
/**
* #ngdoc property
* #name data
* #propertyOf MyController
*
* #description Stores "original" and "edit" copy of the data beeing handled by the form.
*/
$scope.data = {};
/**
* #ngdoc property
* #name data
* #propertyOf MyController
*
* #description Stores state for the view.
*/
$scope.state = {
loading: true,
saving: false,
hasChanged: false,
hasBeenSaved: false
};
/**
* #ngdoc method
* #name _setup
* #private
* #methodOf MyController
*
* #description Run on controller init.
*/
function _setup() {
$scope.reset();
$scope.state.loading = false;
};
/**
* #ngdoc method
* #name _startWatcher
* #private
* #methodOf MyController
*
* #description
* Setup watcher for changes in data.test. Stop method will be saved to
* private property _dataWatcher.
*/
function _startWatcher() {
_dataWatcher = $scope.$watch('data.edit', function (newValue, oldValue) {
if (newValue !== oldValue) {
if (JSON.stringify(newValue) === JSON.stringify($scope.data.original)) {
$scope.state.hasChanged = false;
// If you want the form to act like its untouched if no changes are found:
$scope.nameOfYourForm.$setPristine();
} else {
$scope.state.hasChanged = true;
}
}
}, true);
}
/**
* #ngdoc method
* #name _stopWatcher
* #private
* #methodOf MyController
*
* #description
* Stop watching data.test for changes. This is needed for "reset" and
* syncing data without triggering data-has-changed loop.
*/
function _stopWatcher() {
if (!_dataWatcher) {
return;
}
_dataWatcher();
}
/**
* #ngdoc method
* #name save
* #methodOf MyController
*
* #description
* Save data.edit changes to database, Restangular is used in example but you get the idea.
*/
$scope.save = function () {
var newData;
// Set states
$scope.state.error = false;
$scope.state.saving = true;
// Update with new data
// $scope.entity is a restangularized object from some server
newData = Restangular.copy($scope.entity);
newData.name = $scope.data.edit.name;
newData.status = $scope.data.edit.status;
// Save to db
newData.put().then(function (entity) {
_stopWatcher();
// Db returns saved data, update restangular object, to update
// data in view.
$scope.entity.name = entity.name;
$scope.entity.status = entity.status;
$scope.reset();
$scope.state.hasBeenSaved = true;
}, function (error) {
$scope.state.hasChanged = true;
$scope.state.error = error.data;
}).finally(function () {
$scope.state.saving = false;
});
};
/**
* #ngdoc method
* #name reset
* #methodOf MyController
*
* #description
* Resets the data object to current state of the original source
* object. Any unsaved changes in data.edit will be overwritten.
*/
$scope.reset = function () {
// Stop watcher, if initialized
_stopWatcher();
// Save original data (for comparison)
$scope.data.original = {
status: $scope.feed.status,
name: $scope.feed.name
};
// Create new copy of editable data
$scope.data.edit = angular.copy($scope.data.original);
// Make sure state signals "not changed"
$scope.state.hasChanged = false;
// Force form to be prestine
$scope.nameOfYourForm.$setPristine();
// Start watching changes
_startWatcher();
};
_setup();
});
ngDirty/ngPristine goal is to tell you if the user has modified the form regardless of the values. So in your case the behavior is totally normal.
If you want to modify this behavior, you can use the model.$setPristine() function. More details here : https://code.angularjs.org/1.2.26/docs/api/ng/type/ngModel.NgModelController
You might be interested in this project, called:
angular-forms-enhanced
It modifies $prisitine to be able to do these actions:
Save the original values.
Revert to the original values, and change back to pristine state.
Inform parent forms when child control get back to pristine state
Even though I have my userscript restricted to one domain, any site I visit that uses Jquery experiences all kinds of nasty issues when my script is active. Checking the error console in chrome reveals an identical error on all sites:
"Uncaught TypeError: Property '$' of object [object Window]"
What's causing this? My objective is to get my userscript running in noconflict mode on a site that uses both jquery and prototype. I didn't make the code above var = myFunction, so I don't know what about it is causing the problem I'm running into. Any suggestions?
// ==UserScript==
// #name Restore Dashboard Tags
// #namespace http://userstyles.org
// #description This script restores a user's tracked tag list to the sidebar on tumblr
// #author
// #homepage
// #history 1.0 first version
// #include http://www.tumblr.com/*
// #match http://www.tumblr.com/*
// ==/UserScript==
var jQuery, $ = null;
function addJQuery(callback) {
var p = null;
if(window.opera || window.navigator.vendor.match(/Google/)) {
var div = document.createElement("div");
div.setAttribute("onclick", "return window;");
p = div.onclick();
}
else {
p = Window;
}
jQuery = $ = p.jQuery.noConflict();
callback();
}
var myFunction = function() {
jQuery('div#right_column ul:first-child').after('<ul class="controls_section" id="tracked_tags"></ul>');
jQuery('div.tracked_tags a').each(function (i) {
var tagID = jQuery(this).attr("id");
var tagIDNumber = tagID.replace('tag_','');
var tagName = jQuery(this).attr("href");
var tagNameClean = tagName.replace('/tagged/','');
var tagContent ='';
tagContent += '<li><a href="'+tagName+'" id="'+tagID+'" class="tag">';
tagContent += '<div class="hide_overflow">'+tagNameClean+'</div>';
tagContent += '<span id="tag_unread_'+tagIDNumber+'" class="count" style=""></span></a></li>';
jQuery(tagContent).appendTo('div#right_column ul#tracked_tags');
});
};
var NewPosts = function(){
jQuery('div.tracked_tags > div').each(function (i) {
var thisIndex = jQuery(this).index();
if (jQuery(this).find('small').length){
var postCount = jQuery(this).find('small').text();
jQuery('div#right_column ul#tracked_tags li:eq('+thisIndex+')').find('.count').html(postCount.replace("new posts", "") );
}
});
setTimeout(NewPosts,30000);
}
addJQuery(myFunction);
addJQuery(NewPosts);
The problem has been solved! Someone on another site IDed the culprit as jQuery = $ = p.jQuery.noConflict();; since I wasn't loading my own copy of Jquery I didn't need noConflict, and its usage was hiding Jquery from the rest of the page.