I am using bootstrap-popover to show a message beside an element.
If I want to show different text in the popover after the first time, the text does not change. Re instantiating the popover with new text does not overwrite.
See this js fiddle for a live example:
http://jsfiddle.net/RFzvp/1/
(The message in the alert and the message in the dom is inconsistent after the first click)
The documentation is a bit light on how to unbind: http://twitter.github.com/bootstrap/javascript.html#popovers
Am I using this wrong? The Any suggestions on how to work around?
Thanks
You can access the options directly using the jquery data closure dictionary like this:
$('a#test').data('bs.popover').options.content = 'new content';
This code should work fine even after first initializing the popover.
Hiya please see working demo here: http://jsfiddle.net/4g3Py/1/
I have made the changes to get your desired outcome. :)
I reckon you already know what you are doing but some example recommendations from my end as follows for sample: http://dl.dropbox.com/u/74874/test_scripts/popover/index.html# - sharing this link to give you idea for different link with different pop-over if you will see the source notice attribute data-content but what you wanted is working by the following changes.
Have a nice one and hope this helps. D'uh don't forget to up vote and accept the answer :)
Jquery Code
var i = 0;
$('a#test').click(function() {
i += 1;
$('a#test').popover({
trigger: 'manual',
placement: 'right',
content: function() {
var message = "Count is" + i;
return message;
}
});
$('a#test').popover("show");
});
HTML
<a id="test">Click me</a>
just in-case anyone's looking for a solution that doesn't involve re-instantiating the popover and just want to change the content html, have a look at this:
$('a#test').data('popover').$tip.find(".popover-content").html("<div>some new content yo</div>")
Update: At some point between this answer being written and Bootstrap 3.2.0 (I suspect at 3.0?) this changed a little, to:
$('a#test').data('bs.popover').tip().find ............
Old question, but since I notice that the no answer provides the correct way and this is a common question, I'd like to update it.
Use the $("a#test").popover("destroy");-method. Fiddle here.
This will destroy the old popover and enable you to connect a new one again the regular way.
Here's an example where you can click a button to set a new popover on an object that already has a popover attached. See fiddle for more detail.
$("button.setNewPopoverContent").on("click", function(e) {
e.preventDefault();
$(".popoverObject").popover("destroy").popover({
title: "New title"
content: "New content"
);
});
The question is more than one year old, but maybe this would be usefull for others.
If the content is only changed while the popover is hidden, the easiest way I've found is using a function and a bit of JS code.
Specifically, my HTML looks like:
<input id="test" data-toggle="popover"
data-placement="bottom" data-trigger="focus" />
<div id="popover-content" style="display: none">
<!-- Hidden div with the popover content -->
<p>This is the popover content</p>
</div>
Please note no data-content is specified. In JS, when the popover is created, a function is used for the content:
$('test').popover({
html: true,
content: function() { return $('#popover-content').html(); }
});
And now you can change anywhere the popover-content div and the popover will be updated the next time is shown:
$('#popover-content').html("<p>New content</p>");
I guess this idea will also work using plain text instead of HTML.
On Boostrap 4 it is just one line:
$("#your-element").attr("data-content", "your new popover content")
You can always directly modify the DOM:
$('a#test').next(".popover").find(".popover-content").html("Content");
For example, if you want a popover that will load some data from an API and display that in the popover's content on hover:
$("#myPopover").popover({
trigger: 'hover'
}).on('shown.bs.popover', function () {
var popover = $(this);
var contentEl = popover.next(".popover").find(".popover-content");
// Show spinner while waiting for data to be fetched
contentEl.html("<i class='fa fa-spinner fa-pulse fa-2x fa-fw'></i>");
var myParameter = popover.data('api-parameter');
$.getJSON("http://ipinfo.io/" + myParameter)
.done(function (data) {
var result = '';
if (data.org) {
result += data.org + '<br>';
}
if (data.city) {
result += data.city + ', ';
}
if (data.region) {
result += data.region + ' ';
}
if (data.country) {
result += data.country;
}
if (result == '') {
result = "No info found.";
}
contentEl.html(result);
}).fail(function (data) {
result = "No info found.";
contentEl.html(result);
});
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
Hover here for details on IP 151.101.1.69
This assumes that you trust the data supplied by the API. If not, you will need to escape the data returned to mitigate XSS attacks.
Learn't from previous answers
let popOverOptions = {
trigger: 'click',
...
};
// save popOver instance
let popOver = $(`#popover-unique-id`).popover(popOverOptions);
// get its data
let popOverData = popOver.data('bs.popover');
// load data dynamically (may be with AJAX call)
$(`#popover-unique-id`).on('shown.bs.popover', () => {
setTimeout(() => {
// set content, title etc...
popOverData.config.content = 'content/////////';
// updata the popup in realtime or else this will be shown next time opens
popOverData.setContent();
// Can add this if necessary for position correction:
popOver._popper.update();
}, 2000);
});
This way we can update popover content easily.
There's another way using destroy method.
http://jsfiddle.net/bj5ryvop/5/
Bootstrap 5.0 update
let popoverInstance = new bootstrap.Popover($('#element'));
And then:
popoverInstance._config.content = "Hello world";
popoverInstance.setContent();
(Caution: it will update popover content globally, so if you have multiple open popovers then they all will be updated with "Hello world")
I found Bootstrap popover content cannot changed dynamically which introduces the setContent function. My code (hopefully helpful to someone) is therefore:
(Noting that jquery data() isn't so good at setting as it is getting)
// Update basket
current = $('#basketPopover').data('content');
newbasket = current.replace(/\d+/i,parseInt(data));
$('#basketPopover').attr('data-content',newbasket);
$('#basketPopover').setContent();
$('#basketPopover').$tip.addClass(popover.options.placement);
if jQuery > 4.1 use
$("#popoverId").popover("dispose").popover({
title: "Your new title"
content: "Your new content"
);
Bootstrap 5.1
I tried about 8 different ways to change the content for my Bootstrap 5.1 project, but none worked. I could see the values in the underlying popover object and could change them, but they didn't show on the page.
I got it going by first using the Bootstrap Popover's selector option, which the docs don't explain that well, but basically amounts to putting a watch on the page, so if new popover elements are added to the page (with the selector) they will become popovers automatically.
$(function() {
// set up all popovers
new bootstrap.Popover(document.body, {selector: 'has-popover');
})
then in my ajax call where some different content has been fetched, I remove the existing popover div, change the attribute with the text, and add it again:
var $pop = $('#pop_id1234')
var html = $pop[0].outerHTML // save the HTML
$pop.remove()
var $new = $(html).attr('data-bs-content',popoverText) // data('bs-content') becomes bsContent which won't work
$('#pop-container').append($new)
Related
I'm currently using the following JS to open an accordion when an <a> tag is clicked. It uses the data-trigger value to determine what <a> to use.
<script type="text/javascript">
$('[data-trigger="accordion"]').on('click', function(e) {
var obj = $(this),
accordionButtons = $('[href*="#"]', '[data-accordion] .accordion-navigation'),
accordionPanels = $('.content.1', '[data-accordion]');
if (obj.hasClass('toggle-open')) {
accordionButtons.removeClass('active');
accordionPanels.removeClass('active');
obj.removeClass('toggle-open');
} else {
accordionButtons.addClass('active');
accordionPanels.addClass('active');
obj.addClass('toggle-open');
}
$('[href*="#"]', '[data-accordion] .accordion-navigation').trigger('click.fndtn.accordion');
window.location.href = "#" + anchor;
e.preventDefault();
});
</script>
This above JS will open an accordion based on it's class. Below is an example of the link that is used to open the Accordion:
<a href="#protect-the-nhs" data-trigger="accordion">
An example of the code that it is referencing to open the accordion:
<div id="protect-the-nhs" class="content 1">
I was wondering if anyone can help me change this code so that I can reuse it for each Accordion on the page. Let me explain. The page has 5 different accordions, above I have used generic naming for the data-trigger and the accordion class "content 1".
I'd like to know if it is possible to somehow make it so I can use this code for each different accordion (So for example accordion 1 would have a class of "content 1", accordion 2 would have a class of "content 2" etc. However, for each accordion, there would also be a different link you have to click to open the accordion.
For example: Accordion one would rely on an <a> tag with data-trigger="accordion1" and it would open the accordion with class="content 1".
I hope someone understands my ask and might be able to help! I've tried looking for something for this but haven't found anything. I'm still learning JS so TIA.
Thanks.
My basic idea is to listen to the entire document, determine where got clicked and activate the correct accordion
PLEASE NOTE: I'm assuming that every accordion has a number right after it that corresponds to the content classes like accordion1 content 1
document.onclick=function(e) {
if(!e.path[0].dataset.trigger){return;} //i forgot that not every element has a data-trigger
if(!e.path[0].dataset.trigger.startsWith('accordion')){return;} //listening to the whole document needs you have to ensure you aren't activating when you don't need to
var n=e.path[0]["data-trigger"].split('accordion')[1]
alert(n)
var obj = e.path[0],
accordionButtons = $('[href*="#"]', '[data-accordion] .accordion-navigation'),
accordionPanels = $(`.content.${n}`, '[data-accordion]');
if (obj.hasClass('toggle-open')) {
accordionButtons.removeClass('active');
accordionPanels.removeClass('active');
obj.removeClass('toggle-open');
} else {
accordionButtons.addClass('active');
accordionPanels.addClass('active');
obj.addClass('toggle-open');
}
$('[href*="#"]', '[data-accordion] .accordion-navigation').trigger('click.fndtn.accordion');
window.location.href = "#" + anchor;
e.preventDefault();
}
I'm trying to create a $ionicPopup where one of the buttons is disabled under certain conditions (being the return value of a function, let's call it MyFunction()). I want to use ng-disabled for this purpose.
The problem is, I don't know how to programmatically add the attribute "ng-disabled".
What I tried so far:
Adding the attribute when creating the popup, like attr:"ng-disabled='myFunction()'"
Adding the attribute after the popup was created, using JavaScript => The problem is that the setAttribute() method is executed before the popup is actually shown, so I would need a way to detect when the popup is open, and execute the method only then.
Creating the button as html elements inside the popup template, and not setting any button with the $ionicPopup.show() method. This works, but I'm not satisfied with it because I don't want to "reinvent the wheel" and redefine CSS styles for buttons that are already covered by Ionic framework.
My JS function:
$scope.displayPopUp=function(){
var alertPopup = $ionicPopup.show({
templateUrl: 'sharePopUp.html',
title: 'Invite a friend',
cssClass: 'popupShare',
buttons:[
{
text:'Close',
type: 'button-round button-no',
onTap: function(){
/* Some instructions here */
}
},
{ /* v THIS IS THE BUTTON I WANT TO DISABLE UNDER CERTAIN CONDITIONS v */
text:'Share',
type: 'button-round button-yes',
onTap: function(){
/* Some instructions here */
}
}
]
});
$(".button-yes")[0].setAttribute("ng-disabled", "MyFunction()"); /* NOT WORKING BECAUSE button-yes IS NOT EXISTING YET */
}
TL;DR
$timeout(function () { // wait 'till the button exists
const elem = $('.button-yes')[0];
elem.setAttribute('ng-disabled', 'MyFunction()'); // set the attribute
$compile(elem)(angular.element(elem).scope()); // Angular-ify the new attribute
});
Live demo: working plunk
Introduction
That problem you're encountering, it's a real one, and it has apparently been for years.
Here's the latest version of the code used by $ionicPopup (last updated in December 2015)
This template is the one used by your Ionic-1 popups (from the first lines of the code linked above):
var POPUP_TPL =
'<div class="popup-container" ng-class="cssClass">' +
'<div class="popup">' +
'<div class="popup-head">' +
'<h3 class="popup-title" ng-bind-html="title"></h3>' +
'<h5 class="popup-sub-title" ng-bind-html="subTitle" ng-if="subTitle"></h5>' +
'</div>' +
'<div class="popup-body">' +
'</div>' +
'<div class="popup-buttons" ng-show="buttons.length">' +
'<button ng-repeat="button in buttons" ng-click="$buttonTapped(button, $event)" class="button" ng-class="button.type || \'button-default\'" ng-bind-html="button.text"></button>' +
'</div>' +
'</div>' +
'</div>';
There's one line in particular that's interesting to us: the button template:
<button ng-repeat="button in buttons" ng-click="$buttonTapped(button, $event)" class="button" ng-class="button.type || \'button-default\'" ng-bind-html="button.text"></button>
As you can see, there's just no built-in way to alter its button's attributes.
Two approaches
From here, you've got two fixes:
We can contribute to their project on GitHub, implement the missing functionality, write the tests for it, document it, submit an issue, a Pull Request, ask for a newer version to be released and use the newer version.
This is the ideal solution, 'cause it fixes everyone's problems forever. Although, it does take some time. Maybe I'll do it. Feel free to do it yourself though, and tag me, I'll +1 your PR 👍
Write a dirty piece of code that monkey-patches your specific problem in your specific case
This isn't ideal, but it can be working right now.
I will explore and expand on the (quick 'n dirty) option #2 below.
The fix
Of the 3 things you've tried so far:
the first one is simply not a thing (although it could be if we implement it, test it, document it and release it)
the third one is rather unmaintainable (as you know)
That leaves us with the second thing you mentioned:
Adding the attribute after the popup was created, using JavaScript
The problem is that the setAttribute() method is executed before the popup is actually shown, so I would need a way to detect when the popup is open, and execute the method only then.
You're right, but that's only part one of a two-fold problem.
Part 1: The button isn't created yet
Actually, you can delay that call to setAttribute to later, when the popup is shown. You wouldn't wanna delay it by any longer than would be noticeable by a human, so you can't reasonably go for anything longer than 20ms.
Would there be some callback when the popup is ready, we could use that, but there isn't.
Anyways, I'm just teasing you: JavaScript's "multi-tasking" comes into play here and you can delay it by 0 millisecond! 😎
In essence, it has to do with the way JS queues what it has to do. Delaying the execution of a piece of code by 0ms puts it at the end of the queue of things to be done "right away".
Just use:
setTimeout(function () {
$(".button-yes")[0].setAttribute("ng-disabled", "MyFunction()");
}, 0); // <-- 0, that's right
And you're all set!
Well, you do have a button whose ng-disabled attribute indeed is "MyFunction()". But it's not doing anything...
So far, you simply have an HTML element with an attribute that doesn't do anything for a simple HTML button: Angular hasn't sunk its teeth into your new DOM and hooked itself in there.
Part 2: Angular isn't aware of the new attribute
There's a lot to read here about this, but it boils down to the following: Angular needs to compile your DOM elements so that it sets things in motion according to your Angular-specific attributes.
Angular simply hasn't been made aware that there's a new attribute to your button, or that it should even concern itself with it.
To tell Angular to re-compile your component, you use the (conveniently named) $compile service.
It will need the element to compile, as well as an Angular $scope to compile it against (for instance, MyFunction probably doesn't exist in your $rootScope).
Use it once, like so:
$compile(/* the button */ elem)(/* the scope */ scope);
Assuming the following element is your button:
const elem = $(".button-yes")[0];
... you get its actual scope through its corresponding Angular-decorated element thingy:
const scope = angular.element(elem).scope();
So, basically:
const elem = $('.button-yes')[0];
elem.setAttribute('ng-disabled', 'MyFunction()');
$compile(elem)(angular.element(elem).scope());
Tadaaa! That's it! 🎉
... sort of. Until there's some user interaction that would alter the corresponding $scope, the button is actually not even displayed.
Bonus Part: Avoid $scope.$apply() or $scope.$digest()
Angular isn't actually magically picking up things changing and bubbling it all to the right places. Sometimes, it needs to explicitly be told to have a look around and see if the elements are in sync with their $scope.
Well, more specifically, any change that happens asynchronously won't be picked up by itself: typically, I'm talking about AJAX calls and setTimeout-delayed functions. The methods that are used to tell Angular to synchronise scopes and elements are $scope.$apply and $scope.$digest... and we should thrive on avoiding them :)
Again, there's lots of reading out there about that. In the meantime, there's an Angular service (again), that can (conceptually, it's not the literal implementation) wrap all your asynchronous code into a $scope.$apply() -- I'm talking about $timeout.
Use $timeout instead of setTimeout when you will change things that should alter your DOM!
Summing it all up:
$timeout(function () { // wait 'till the button exists
const elem = $('.button-yes')[0];
elem.setAttribute('ng-disabled', 'MyFunction()'); // set the attribute
$compile(elem)(angular.element(elem).scope()); // Angular-ify the new attribute
});
Live demo: working plunk
I think in ionic v1 Ionic Framework team have not implemented this yet as per (Oct 6, '14 10:49 PM). I think still situation is same. But there is a work around for that.
Option 1:
What I understand from your question, your main purpose is to prevent user to click on buttonDelete ionicPopup buttons and perform some instructions until MyFunction() returns truecreate your own template with buttons which you can fully control them. Below is code:
You can achieve this inside onTap :. Here you can add condition of your MyFunction() like below:
JavaScript:
// Triggered on a button click, or some other target
$scope.showPopup = function() {
// Enable/disable text"Share" button based on the condition
$scope.MyFunction = function() {
return true;
};
//custom popup
var myPopup = $ionicPopup.show({
templateUrl: 'Share'"popup-template.html",
typetitle: 'button-round"Invite button-yes'a friend",
onTapscope: function(e)$scope
{ });
// close popup on Cancel ifbutton (MyFunctionclick
$scope.closePopup = function()) {
myPopup.close();
};
};
HTML:
/*<button Someclass="button instructionsbutton-dark" hereng-click="showPopup()">
*/ show
</button>
}<script elseid="popup-template.html" {type="text/ng-template">
<p>Share button is disabled if condition not /satisfied</don'tp>
allow the user to<button performclass="button unlessbutton-dark" MyFunctionng-click="closePopup()"> returns
true Cancel
</button>
e.preventDefault<button class="button button-dark" ng-disabled="MyFunction(); == true">
}Share
}</button>
}</script>
Working example here Here is working codepen snippet:
https://codepen.io/anon/pen/bvXXKG?editors=1011
Option 2:
Delete ionicPopup buttons and create your own template with buttons which you can fully control them. Below is code:
JavaScript:
// Triggered on a button click, or some other target
$scope.showPopup = function() {
// Enable/disable "Share" button based on the condition
$scope.MyFunction = function() {
return true;
};
//custom popup
var myPopup = $ionicPopup.show({
templateUrl: "popup-template.html",
title: "Invite a friend",
scope: $scope
});
// close popup on Cancel button click
$scope.closePopup = function() {
myPopup.close();
};
};
HTML:
<button class="button button-dark" ng-click="showPopup()">
show
</button>
<script id="popup-template.html" type="text/ng-template">
<p>Share button is disabled if condition not satisfied</p>
<button class="button button-dark" ng-click="closePopup()">
Close
</button>
<button class="button button-dark" ng-disabled="MyFunction() == true">
Share
</button>
</script>
Here is working codepen snippet:
https://codepen.io/anon/pen/qYEWmY?editors=1010
Note: Apply your own styles/button's alignment etc
I hope it will help you.
Most of our customers complain about formatting carried across from Word to our redactor.js rich text editor fields. We upgraded to use the pastePlainText setting, which seems to work well.
However SOME customers still need to paste html into the rich text boxes. We've added a "paste as html" button to the toolbar using a plugin but we can't work out what code to add to the plugin to paste the clipboard content as-is into the editor. Help!
We'd be almost as happy to remove the pastePlainText option and have a "paste as plain text" button on the toolbar instead, but we also can't work out how to do that.
RedactorPlugins.pasteAsHtml = {
init: function () {
this.buttonAdd('pasteAsHtml', 'Paste as HTML', this.testButton);
},
testButton: function (buttonName, buttonDOM, buttonObj, e) {
// What do we do here?
};
$(".richText").redactor({
plugins: ['pasteAsHtml'],
pastePlainText: true
});
We now have a solution to this.
We were barking up the wrong tree here: for security reasons it's difficult to read from the clipboard. We had assumed that redactor.js has the ability to do this, but in fact it appears to read from the rich text editor only after the user has initiated the paste themselves via Ctrl+v or the context menu. That means clicking a button to trigger a "paste" isn't easy. I believe there's at least one jquery plugin that attempts to solve that problem, and a bunch of solutions involving Flash, but we're after a more lightweight fix.
Instead, we did the following.
Set redactor to accept html (ie we didn't set the pastePlainText option).
Caused our button to show a modal dialog containing a textarea, into which the user pastes their html content. Once the content is pasted we process it to strip out html and retain line breaks.
So users wanting to retain formatting just paste into the RTE, and users who want to paste as plain text click the new button. Here's the code for the plugin.
if (!RedactorPlugins) var RedactorPlugins = {};
RedactorPlugins.pasteAsPlainText = {
init: function () {
// add a button to the toolbar that calls the showMyModal method when clicked
this.buttonAdd('pasteAsPlainText', 'Paste as plain text', this.showMyModal);
},
// pasteAsPlainText button handler
showMyModal: function () {
// add a modal to the DOM
var $modalHtml = $('<div id="mymodal" style="display:none;"><section><label>Paste content here to remove formatting</label><textarea id="mymodal-textarea" style="width: 100%; height: 150px;"></textarea></section><footer><button class="btn btn-primary" id="mymodal-insert" style="color:#fff;">Insert</button></footer></div>');
$("body").append($modalHtml);
// callback executed when modal is shown
var callback = $.proxy(function () {
this.selectionSave();
$('#mymodal-insert')
.css("width", "100px")
.click($.proxy(this.insertFromMyModal, this));
$("#mymodal-textarea").focus();
}, this);
// initialize modal with callback
this.modalInit('Paste as plain text', '#mymodal', 500, callback);
},
insertFromMyModal: function (html) {
this.selectionRestore();
// remove formatting from the text pasted into the textarea
html = $('#mymodal-textarea').val();
var tmp = this.document.createElement('div');
html = html.replace(/<br>|<\/H[1-6]>|<\/p>|<\/div>/gi, '\n');
tmp.innerHTML = html;
html = tmp.textContent || tmp.innerText;
html = $.trim(html);
html = html.replace('\n', '<br>');
html = this.cleanParagraphy(html);
// insert the text we pulled out of the textarea into the rich text editor
this.insertHtml(html);
// close the modal and remove from the DOM
this.modalClose();
$("#mymodal").remove();
}
};
$(".richText").redactor({
plugins: ['pasteAsPlainText']
});
By the way, if Internet Explorer had a "paste as plain text" option available via Ctrl+shift+v or on the context menu like Firefox and Chrome we would just have told customers to do that!
If you've just recently upgraded from Redactor v9 to v10, you will find that the above code does not work since Redactor has now updated most of its existing APIs and added new modules. For example, .modalInit(), .selectionRestore(), .selectionSave(), .insertHtml() from v9 is now .modal.load(), selection.restore(), .selection.save(), etc in v10.
I've modified the above code slightly and am adding it here if anybody's interested. Feel free to edit/ optimize it if needed.
Reference - http://imperavi.com/redactor/docs/how-to-create-modal/
if (!RedactorPlugins) var RedactorPlugins = {};
RedactorPlugins.pasteasplaintext = function()
{
return {
init: function()
{
// add a button to the toolbar that calls the showMyModal method when clicked
var button = this.button.add('pasteasplaintext', 'Paste As Plain Text');
this.button.setAwesome('pasteasplaintext', 'fa-paste');
this.button.addCallback(button, this.pasteasplaintext.showMyModal);
},
getTemplate: function()
{
// this function creates template for modal that is to be added
return String()
+ '<div id="mymodal">'
+ ' <section>'
+ ' <label>Paste content here to remove formatting</label>'
+ ' <textarea id="mymodal-textarea" style="width: 100%; height: 150px;"></textarea>'
+ ' </section>'
+ '</div>';
},
showMyModal: function () {
// fetch and load template
this.modal.addTemplate('pasteasplaintext', this.pasteasplaintext.getTemplate());
this.modal.load('pasteasplaintext', 'Paste As Plain Text', 500);
// create cancel and insert buttons
this.modal.createCancelButton();
var buttonPaste = this.modal.createActionButton('Paste');
buttonPaste.on('click',this.pasteasplaintext.insertFromMyModal);
// save current content, show modal and add focus to textarea
this.selection.save();
this.modal.show();
$("#mymodal-textarea").focus();
},
insertFromMyModal: function (html) {
// remove formatting from the text pasted into the textarea
html = $('#mymodal-textarea').val();
var tmp = document.createElement('div');
html = html.replace(/<br>|<\/H[1-6]>|<\/p>|<\/div>/gi, '\n');
tmp.innerHTML = html;
html = tmp.textContent || tmp.innerText;
html = $.trim(html);
html = html.replace('\n', '<br>');
// close modal, restore content and insert 'plain' text
this.modal.close();
this.selection.restore();
this.insert.html(html);
$("#mymodal").remove();
}
};
};
If you, like me, were looking for a plugin to paste simple text into Redactor and found this question only to learn that the answers are very old, you'd be happy to find out that the answer is actually in the Redactor docs.
It turns out that their example plugin with modal window is exactly that, a "paste clean text" plugin.
You can find it here:
https://imperavi.com/redactor/examples/creating-plugins/sample-plugin-with-modal-window/
I'm trying to make a button that will hide a specific -- and then replace it with another hidden . However, when I test the code, everything fires correctly except for the .removeClass which contains the "display: none."
Here is the code:
<script type="text/javascript">
$(document).ready(function(){
var webform = document.getElementById('block-webform-client-block-18');
var unmarriedbutton = document.getElementById('unmarried');
var buyingblock = document.getElementById('block-block-10');
$(unmarriedbutton).click(function () {
$(buyingblock).fadeOut('slow', function() {
$(this).replaceWith(function () {
$(webform).removeClass('hiddenbox')
});
});
});
});
</script>
The CSS on 'hiddenbox' is nothing more than "display: none.'
There is a with the id of unmarried, which when clicked fades out a div and replaces it with a hidden div that removes the class to reveal it. However, the last part doesn't fire -- everything else does and functions properly. When I look at in the console too, it shows no errors.
Can someone please tell me where the error is? Thanks!
Edit: I may be using the wrong function to replace the div with, so here's the site: http://drjohncurtis.com/happily-un-married. If you click the "download the book" button, the the div disappears and is replaced correctly with the div#block-webform-client-block-18. However, it remains hidden.
The function you pass to replaceWith has to return the content you want to replace it with. You have to actually return the content.
I don't know exactly what you're trying to accomplish, but you could use this if the goal is to replace it with the webform object:
$(this).replaceWith(function () {
return($(webform).removeClass('hiddenbox'));
});
NB, use jquery !
var webform = $('#block-webform-client-block-18');
var unmarriedbutton = $('#unmarried');
var buyingblock =$('#block-block-10');
unmarriedbutton.click(function () {
buyingblock.fadeOut('slow', function() {
$(this).replaceWith( webform.removeClass('hiddenbox'));
});
});
Was too fast, i believe it's the way you select your object (getelementbyid) then you create a jquery object from it... -> use jquery API
I'm trying to do something that seems (to me, at least) to be a fairly easy, common thing to do.
Here's the HTML for what I've got on a web page:
<div class="allergiesDiv">
<div>
<span class="editButton">Allergies</span><br />
</div>
<span>Allergies</span>
</div>
</div>
I turn the first <span> into a jQuery button with $('.editButton').button().
(I have many of these pairs on the page.)
What I am trying to do is the following:
When the button is clicked, it loads a jQuery Dialog with the value of the span that follows it loaded into a <textarea>. (BONUS: When the dialog is loaded, I'd like the <textarea> to be focused and all text inside highlighted.)
The user is able to edit the value and then click 'OK'.
When the user clicks 'OK', the Dialog is dismissed and the new value that was entered is used to replace the old value for the span.
Here's the code I'm trying to use (this works OK in IE, but breaks in Mobile Safari and Chrome for PC):
NOTE: I've been chopping the code up some to try to get each problem isolated. I have had this working, at least in IE.
// How I get the button and bind to the click event
$('.editButton')
.button({icons: {primary:'ui-icon-pencil'} })
.click(EditClicked);
// 'Edit' button click handler
function EditClicked() {
var span = $(this).parent().next().children().first();
var text = span[0].innerText;
var dialog = $('<div>').prop('title', 'Edit: ' + $(this).text());
var textArea = $('<textarea>').css('width', '98%').prop('rows', '4').html(text);
textArea.appendTo(dialog);
var windowWidth = $(window).width();
var buttonTop = $(this).button().offset().top;
$(dialog).dialog({
modal: true,
minWidth: windowWidth / 2,
position: ['center',buttonTop],
buttons: {
'Ok' : function () {
OKClicked(span);
},
'Cancel' : function () {
$(this).dialog('close').remove();
}
}
});
textArea.focus().select();
}
// Dialog 'OK' button click handler
function OKClicked(span) {
var text = $(this).find('textarea')[0].innerText;
span.html(text);
$(this).dialog('close').remove();
}
This is currently broken when it gets to var buttonTop..., with the error message of "button is undefined". I haven't yet figured out why that is (I used to have a variable in that method named 'button', but it's gone now. Not sure if that's a caching issue.)
Other than that, can anyone see what's wrong with my process? It seems like I've got some kind of misunderstanding with closure, but I'm not yet good enough with JavaScript to understand how to get the kink out of this code.
what about
var buttonTop = $(this).offset().top;
I am not sure, that $('<div>') is properly syntax for jQuery. Try to use $('div') instead.
When you use $(this).button() - you try to call button method of $(this) object. Seems like a bug.