Can anyone tell me what is wrong with this code?
When user selects a word and does a right-click he can choose 'Open Wiki-Link' -
that's working fine. But for some reason nothing happens on a click,
the code in onMessage is not been executed. Why?
exports.main = function() {
var tabs = require('tabs');
//var sel = require('selection');
var cm = require('context-menu');
var menuItem = cm.Item({
label: 'Open Wiki-Link',
context: cm.SelectionContext(),
contextScript: 'self.on("click", function() {' +
'var text = window.getSelection().toString();' +
'self.postMessage(text);' +
'});',
onMessage: function(text) {
if (text.length === 0) {
throw ('No text selected');
}
tabs.open('http://de.wikipedia.org/wiki/' + text);
}
});
};
Your code seems correct and matches the examples from the documentation pretty closely. I think that the only issue is a typo: it should be contentScript, not contextScript.
Related
Disclaimer: I know my code is pretty bad. I'm not very experienced with JavaScript yet.
So I built a gallery with filtering using JavaScript and the WP Rest API. I finally have it working, but after a few clicks between the gallery sub-categories, the page starts slowing down and eventually crashes. I imagine I'm doing something really inefficient that is killing the page, but I'm not sure what the main culprit is.
Besides the other obvious issues with how I've written the code, what might be causing it and is there a good way to test performance issues like this?
(Here's a link to a working version of this: http://victorysurfaces.x10host.com/gallery/)
Edit: Updated code with fix for extra HTML DOM nodes being added by lightbox code. Didn't fix page crashing issue, unfortunately.
Update: I've noticed that sometimes when I click on a sub-category, it makes more network requests, but sometimes it doesn't. I feel like this might be important.
Update 2: I think it might have something to do with the event listeners I'm adding. Since I'm adding the sub-categories dynamically, I have to add the event listeners after they have been loaded, but the event listeners from the previous run seem to remain, so the number of event listeners just grows and grows. I don't know what to do about that.
<div class="gallery">
<div class="medium-wrapper">
<div class="gallery__filters text-center">
<div class="gallery__main-filters">
<button class="category-filter main-category active" data-category="residential">Residential</button>
<span>|</span>
<button class="category-filter main-category" data-category="commercial">Commercial</button>
</div>
<div class="gallery__category-filters"></div>
</div>
<div class="gallery__images"></div>
</div>
</div>
<script>
/* I'm so sorry for this monstrosity. This was way more complicated than I thought and in the end I just wanted it to work */
jQuery(document).ready(function($) {
$('.main-category').on('click', function() {
$('.main-category').removeClass('active');
$(this).addClass('active');
});
initLightbox();
});
jQuery( function( $ ) {
$.getJSON("/wp-json/wp/v2/gallery-categories", function( data ) {
var currentMainCategory = $('.main-category.active').data('category');
getSubCategories();
var currentSubCategory = '';
document.querySelectorAll('.main-category').forEach( function(trigger) {
trigger.addEventListener('click', function() {
resetCategories($(this).data('category')); }, false);
});
function getSubCategories() {
var categoriesArray = [];
var subCategories = data.map(function(category) {
if( category.acf.gallery_section.trim().toLowerCase() === currentMainCategory) {
var setCategory = "<button class='category-filter sub-category' data-category='" + category.acf.category_title + "'>" + category.acf.category_title + "</button>";
categoriesArray.push(setCategory);
}
});
$('.gallery__category-filters').html(categoriesArray);
getPhotos();
}
function resetCategories(mainCategoryTitle) {
currentMainCategory = '';
currentSubCategory = '';
$('.sub-category').removeClass('active');
$('.gallery__category-filters').empty();
currentMainCategory = mainCategoryTitle;
getSubCategories();
}
function setSubCategory() {
currentSubCategory = document.querySelector('.sub-category.active').dataset.category;
getPhotos();
}
var galleryPhotos;
function getPhotos(photos) {
$('.gallery__images').empty();
var mainCategory = currentMainCategory.trim().toLowerCase();
if( (currentSubCategory !== undefined) && (currentSubCategory !== '' ) ) {
var subCategory = currentSubCategory.trim().toLowerCase();
}
galleryPhotos = data.map(function(category) {
if( category.acf.gallery_section.toLowerCase() === mainCategory ) {
if( subCategory !== '' && subCategory !== undefined) {
var categoryTitle = category.acf.category_title.toLowerCase().trim();
if( categoryTitle === subCategory ) {
var galleryCategory = category.acf.gallery_items;
var categoryPhotos = galleryCategory.map(function(photo) {
var galleryPhoto = "<div class='gallery__item'><a class='lightbox-link' href=''><img class='full-width lightbox-target' src='" + photo.gallery_item_image.sizes.flexible + "' alt='" + photo.gallery_item_image.alt + "'></a></div>";
return galleryPhoto;
});
$('.gallery__images').append(categoryPhotos);
}
} else {
var galleryCategory = category.acf.gallery_items;
var categoryPhotos = galleryCategory.map(function(photo) {
var galleryPhoto = "<div class='gallery__item'><a class='lightbox-link' href=''><img class='full-width lightbox-target' src='" + photo.gallery_item_image.sizes.flexible + "' alt='" + photo.gallery_item_image.alt + "'></a></div>";
return galleryPhoto;
});
$('.gallery__images').append(categoryPhotos);
}
}
});
$('.sub-category').on('click', function() {
$('.sub-category').removeClass('active');
$(this).addClass('active');
setSubCategory();
});
checkOrientation();
handleLightboxUpdate();
}
});
});
function checkOrientation() {
document.querySelectorAll('.lightbox-target').forEach(function(item) {
var image = new Image();
image.src = item.src;
image.onload = function() {
if(image.naturalHeight >= image.naturalWidth) {
item.classList.add('portrait');
}
}
});
}
function initLightbox() {
var $overlay = jQuery('<div id="overlay"></div>');
var $container = jQuery('<div class="lightbox">×</div>');
var $image;
var $imageClone;
jQuery('body').append($overlay);
$overlay.click(function(){
$overlay.hide();
});
$overlay.append($container);
}
function handleLightboxUpdate() {
document.querySelectorAll('.lightbox-link').forEach( function(trigger) {
trigger.addEventListener('click', function() {
event.preventDefault();
jQuery('.lightbox-image').remove();
$image = jQuery(this).find('.lightbox-target');
$imageClone = $image.clone();
if($imageClone.hasClass('portrait')) {
$imageClone.addClass('resize-lightbox');
}
jQuery('#overlay').show();
//add image to overlay
$imageClone.addClass('lightbox-image').appendTo('#overlay .lightbox');
});
});
}
</script>
I'm not looking much into code, but I can tell you what's going on here. Page slows down with each 'subcategory' click, because you add more and more HTML nodes into the page until it's just too much. To be specific you add <div id="overlay">...</div> exponentially with every click.
is there a good way to test performance issues like this?
I suggest opening dev tools and see what's happening there. If adding more html wasn't the case, I'd look into potential problems with recursion or creating too many objects.
I figured it out! My setSubCategory() function was calling getPhotos() which was calling setSubCategory(), and so on and so forth.
Turns out it was a simple never-ending loop. Face-palm.
I'm working on a twitter clone in JS + jQuery for a pre-course to a development program, so if this is an obvious fix - let me know!
I have a problem I'm unable to solve: "click on username, page returns with that user's last tweets".
The only thing I could come up with is, an event handler on the <a> tag filter the page. However I'm vastly inexperienced and unclear in how to proceed.
Any ideas?
note- I removed some code for brevity.
$(document).ready(function() {
var $body = $('body');
$body.html();
var stream = function() {
var index = streams.home.length - 1;
while (index >= 0) {
var tweet = streams.home[index];
var $tweet = $('<div class="tweetbody"></div>');
$tweet.text(': ' + tweet.message);
$tweet.appendTo($body);
index -= 1;
var link = $('<a>', {
text: tweet.user,
href: '#',
}).prop('outerHTML');
$tweet.html('#' + link + ': ' + tweet.message);
}
};
Here's the <a> tag event:
//click on a username to see that user's timeline.
$('a').on('click', function() {
console.log("a tag is clicked ");
console.log(this);
});
}();
}); //end document ready body
In the on click function you could perhaps do either of the two things, so go to another page, like redirecting to a new page
//click on a username to see that user's timeline.
$('a').on('click', function() {
//console.log("a tag is clicked ");
//console.log(this);
window.location = '/some_file.php?get_tweets='+tweet.user;
});
or, use an ajax call to do the same:
//click on a username to see that user's timeline.
$('a').on('click', function() {
//console.log("a tag is clicked ");
//console.log(this);
$.ajax({
type: "GET",
url: "/some_file.php",
data: {
'user' : tweet.user
},
success: function(msg) {
$body.html(msg);
});
});
In both cases some_file.php should format the content.
Hi guys this might be a really stupid error but im using jquery to add a formset to a page it also does other things such as updating the number of forms but that does not seem to be a issue.
http://jsfiddle.net/b5Y8f/
$(document).ready(function () {
function updateElementIndex(el, prefix, ndx) {
var id_regex = new RegExp('(' + prefix + '_set-\\d+-)');
var replacement = prefix + '_set-' + ndx + '-';
if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
if (el.id) el.id = el.id.replace(id_regex, replacement);
if (el.name) el.name = el.name.replace(id_regex, replacement);
}
function changeDeleteForms(el, prefix, formid) {
var idstring = 'id_' + prefix + '_set-' + formid + '-DELETE';
//$('<input>').attr({type: 'hidden', id: 'id_' + idstring, name: idstring}).appendTo('.command-delete');
$('#' + idstring).prop('checked', true);
}
function deleteForm(btn, prefix) {
var formCount = parseInt($('#id_' + prefix + '_set-TOTAL_FORMS').val());
if (formCount > 1) {
// Delete the item/form
$(btn).parents('.command').hide();
$(btn).parents('.command').attr('class', 'command-delete');
var dc = $(".command-delete");
$(dc).children().children().children().each(function () {
var formid = this.id.match(/\d+/g);
changeDeleteForms(this, prefix, formid);
//$(this).val("");
});
var forms = $('.command'); // Get all the forms
var formsdelete = $('.command-delete'); // Get all the forms
var fl = parseInt(forms.length);
var fdl = parseInt(formsdelete.length);
var finalcount = fl + fdl
// Update the total number of forms (1 less than before)
//$('#id_' + prefix + '_set-TOTAL_FORMS').val(forms.length);
var i = 0;
} // End if
else {
alert("Please enter atleast 1 command for this item.");
}
return false;
}
function addForm(btn, prefix) {
var formCount = parseInt($('#id_' + prefix + '_set-TOTAL_FORMS').val());
var maxCount = parseInt($('#id_' + prefix + '_set-MAX_NUM_FORMS').val());
var forms = parseInt($('.command-delete').length); // Get all the forms
var newcount = formCount + forms;
// You can only submit a maximum of 10 todo items
if (newcount < maxCount) {
// Clone a form (without event handlers) from the first form
var row = $(".command:first").clone(false).get(0);
// Insert it after the last form
$(row).removeAttr('id').hide().insertAfter(".command:last").slideDown(300);
// Remove the bits we don't want in the new row/form
// e.g. error messages
$(".errorlist", row).remove();
$(row).children().removeClass("error");
// Relabel or rename all the relevant bits
$(row).children().children().children().children().each(function () {
updateElementIndex(this, prefix, newcount);
$(this).val("");
});
// Add an event handler for the delete item/form link
$(row).find(".delete").click(function () {
return deleteForm(this, prefix);
});
// Update the total form count
$("#id_" + prefix + "_set-TOTAL_FORMS").val(newcount + 1);
} // End if
else {
alert("Sorry, you can only enter a maximum of 1000 items.");
}
return false;
}
// Register the click event handlers
$("#add").click(function () {
return addForm(this, "itemcommands");
});
$(".delete").click(function () {
return deleteForm(this, "itemcommands");
});
$('.command input:checkbox').hide();
});
If you go to the link above you can see the code works perfectly fine it update the form count and add the new form with the new number in the id and everything however in production when you click the add command button for the first 3 times it does not show however the code has been enter into the page and the form is technically there but not shown.
on the fourth time you press the button it works and the row has been added after the last ('.command') in the element.
What could be causing it to work on JSFiddle but not on production?
-------------------UPDATE--------------------------
It seems if i remove the overflow hidden from the 3 that dont show when you press the button the first 3 times it will show them in the correct place.
Why would overflow no be removed from the first 3 form rows but the rest after fine?
----------------------UPDATE--------------------------
Think i have found the issue and its nothing to do with the JQUERY at all it seems to be bootstraps responsive layout hiding the forms i think if i add them specifically to their own rows i can fix this.
Thanks for the help though guys.
I don't see a src="*jQuery source*" in your file. Since JSFiddle already adds the source to the file, you may have forgotten to put it in.
Is there a way to add the select-result on the url when the pop up window appears? The select-result gives the value of the boxes selected and i want to pass the values selected gto a form but i am not ussing a form. can i pass the values ussing the url?
i want to add the selected values like form.php?id=2882,222,22412,23
$(function() {
$(".selectable").selectable({
filter: "td.cs",
stop: function() {
var result = $("#select-result").empty();
var result2 = $("#result2");
$('.ui-selecting:gt(31)').removeClass("ui-selecting");
confirmation($(".ui-selected").length + " box selected. " + ($(".ui-selected").length));
function confirmation() {
var answer = confirm($(".ui-selected").length + " box selected. " + ($(".ui-selected").length));
if (answer) {
window.open("form.php", "mywindow", "menubar=no,resizable=no,width=650,height=700");
}
else {}
}
$('#divmsg').html($(".ui-selected").length + " box selected")
$('#divmsg2').html($(".ui-selected").length)
if ($(".ui-selected").length > 90) {
alert("Selection of only 90 boxes allowed");
$('#divmsg').html($('#divmsg').html() + ",<br><b>Message: Selection of only 90 pixels allowed!!</b>");
$(".ui-selected").each(function(i, e) {
if (i > 3) {
$(this).removeClass("ui-selected");
}
});
return;
}
$(".ui-selected", this).each(function() {
var cabbage = this.id + ', ';
result.append(cabbage);
});
var newInputResult = $('#select-result').text();
newInputResult = newInputResult.substring(0, newInputResult.length - 1);
result2.val(newInputResult);
}
});
});
this is the fiddle http://jsfiddle.net/dw6Hf/57/
i have tried
window.open ("form.php?id="+ select-result, "mywindow",....
but it won't work!! any idea???
Thanks in advance
If you're asking what I think you're asking, and selectable does what I think it does, then try this:
window.open("form.php?id=" + $('#select-result').text(), "mywindow", "menubar=no,resizable=no,width=650,height=700");
If that doesn't work, then I've obviously misunderstood your answer. I'd suggest clearing it up, and maybe getting a working example up and running for us to see.
Firstly the fiddle you have posted is broken. But no worries i have fixed it along with the solution at http://jsfiddle.net/paragnair/dw6Hf/61/
I have added the following line:
var selectedIds = $.map($('.ui-selected'),function(a){ return $(a).attr('id');}).join(',');
The above line gets the list of ids for all the elements which have the class ui-selected. Then you can append the variable selectedIds to window.open like so:
window.open("form.php?id=" + selectedIds, "mywindow", "menubar=no,resizable=no,width=650,height=700");
I added a custom 'quote' button.
ed.addButton('blockquote', {
title : 'blockquote',
cmd : 'mceblockquote',
image : url + '/img/blockquote.gif',
onclick : function() {
var blockquoteActive = tinyMCE.activeEditor.controlManager.get('blockquote').isActive();
if (blockquoteActive) {
//replace <blockquote> tags ?!
//set Button inactive
}
else {
ed.selection.setContent('<blockquote>' + ed.selection.getContent() + '</blockquote><br />');
}
}
});
ed.onNodeChange.add(function(ed, cm, n) {
cm.setActive('blockquote', n.nodeName == 'IMG');
})
When I click the button, everything works fine. The selection is quoted.
How do I replace the blockquote-tags when klicking the button again?
How do I set the button inactive?
Regards,
saromba
it worked thanks...
I've made some changes (maybe / probably improvements).
When nothing is selected, do nothing
When text is already quoted
When user marked the text with a double-click, the blockquote element will now be removed
onclick : function() {
var blockquoteActive = tinyMCE.activeEditor.controlManager.get('blockquote').isActive();
var selection = ed.selection.getContent();
if (blockquoteActive) {
if (selection) {
var parElem = ed.dom.getParent(ed.selection.getNode(), 'blockquote');
var inner = parElem.innerHTML;
ed.dom.remove(parElem);
ed.selection.setContent(inner);
}
else return
}
else {
if (selection) {
ed.selection.setContent('<blockquote>' + ed.selection.getContent() + '</blockquote><br />');
}
}
}
Try this. You may modify it a bit.
ed.addButton('blockquote', {
title : 'blockquote',
cmd : 'mceblockquote',
image : url + '/img/blockquote.gif',
onclick : function() {
var blockquoteActive = tinyMCE.activeEditor.controlManager.get('blockquote').isActive();
if (blockquoteActive) {
//replace <blockquote> tags ?!
content = ed.selection.getContent();
content.replace(/<\/?blockquote>/ig,'');
ed.selection.setContent(content);
//set Button inactive
// works only if blockquote is registered at the controlManager
ed.controlManager.setActive('blockquote', false);
}
else {
ed.selection.setContent('<blockquote>' + ed.selection.getContent() + '</blockquote><br />');
}
}
});