Recently, I use the Html5 framework: "phonejs" to develop a mobile project,
when I want to make a toolbar menusheet in empty views,
It seems menu text will show up twice in this demo:
http://phonejs.devexpress.com/Documentation/ApiReference/Widgets/dxToolbar/Configuration?version=13_2#menuItemRender
I use it like this:
homeToolbarItems = [
{ location: 'menu', text: 'Logout',clickAction:logout },
{ location: 'center', text: 'Subscribe Manage' }
];
and the menu shows 'Logout' twice, what can I do?
It appears that the menuItemRenderer is triggering twice. Once on initial view and once on click. I was able to remedy this buggy behavior by added a Initialize flag to the first view render. Then if the flag was tripped do not render the menu items again on additional request. Example...
var menuInit = false;
var viewModel = {
menuItemRenderer: function(itemData, itemIndex, itemElement){
if(menuInit == false){
itemElement.dxButton({ text: "Execute \"" + itemData.text + "\" action" });
menuInit = true;
}
}}
It seems it's a bug, I just asked the devExpress Phonejs develop team. And it have been solve several days ago.
Here is the question link: http://www.devexpress.com/Support/Center/Question/Details/Q571866
Related
I have tried various snippets of code that I've found online, but I can't get any of them to work with the current version of VideoJS, which is version 7. I'm very new to javascript programming, and the documentation does not give example code on how to implement this. There is a codepen here that can be used to experiment with customizing the player: https://codepen.io/heff/pen/EarCt This is the link to the VideoJS player documentation on adding a button to the player: https://docs.videojs.com/button
I've tried inserting code from various web page and 5-6 different discussions I found on StackExchange, but none of them make a button appear next to the video progress bar.
I'm simply trying to create a button with the text "Exit Course" that will appear to the right of the video progress bar, and that will execute a javascript function when pressed.
Could someone familiar with VideoJS please take a look at the codepen link above to see if they can add such a button to the player? Thank you!
I'm required to add some code to this question, so here is one piece of code that I tried on codepen:
var setup = {
'techOrder' : ['html5', 'flash'],
'controls' : true,
'preload' : 'auto',
'children':{
'controlBar': {
'children': {
'playbackSpeedPopoverMenu': {},
'selectBitrateControlButton': {src:videosrc},
'verticalVolumeMenuButton': {},
'volumeControl': false,
'muteToggle':false,
'liveDisplay':false,
}
}
};
var player = new vjs.Player(vjs.el("id_of_my_video_element_note_that_theres_no_poundsign"),
setup,
function() {
//this is your ready function
}));
I've tested this snippet with video.js 7.4.1 and it works fine. I used video.js's cancel icon instead of text to save space on the control bar. Give it a try:
<script>
var player = videojs('my-player');
var button = videojs.getComponent('Button');
var closeButton = videojs.extend(button, {
constructor: function() {
button.apply(this, arguments);
this.controlText("Exit Course");
this.addClass('vjs-icon-cancel');
},
handleClick: function() {
this.player().dispose();
}
});
videojs.registerComponent('closeButton', closeButton);
player.getChild('controlBar').addChild('closeButton', {});
</script>
var player = videojs('video');
var skipBehindButton = player.controlBar.addChild("button");
var skipBehindButtonDom = skipBehindButton.el();
skipBehindButtonDom.innerHTML = "30<<";
skipBehindButton.addClass("buttonClass");
skipBehindButtonDom.onclick = function(){
skipS3MV(-30);
}
var skipAheadButton = player.controlBar.addChild("button");
var skipAheadButtonDom = skipAheadButton.el();
skipAheadButtonDom.innerHTML = ">>30";
skipAheadButton.addClass("buttonClass");
skipAheadButtonDom.onclick = function(){
skipS3MV(30);
}
function skipS3MV(skipBy) {
player.currentTime(player.currentTime() + skipBy);
}
The reason I've used text ("30<<" and ">>30") is because in my player, the colors are all customizable. So if I used an icon image for skip-back and skip-forward, then I wouldn't be able to change the color of the icon every time someone customizes the player colors (which includes the all the text in the control bar).
I’m pretty new to backbonejs and i’m trying to create a basic application.
The application is something like this:
I have 5 sections: A, B, C, D and E
Each section has 2 radio buttons.
Section A - Radio1, Radio2
Section B - Radio3, Radio4
Section C - Radio5, Radio6
Section D - Radio7, Radio8
Section E - Radio9, Radio10
Depending on what radio button is selected, I need to display a section (previous sections must also display)
I have had a look at maybe using a model to determine which radio was selected and also what section is displayed. Is this the correct approach?
var State = Backbone.Model.extend({
defaults: {
id: null,
name: "",
isOn: false
}
});
var Section = Backbone.View.extend({
model: State,
events: {
'change [type="checkbox"]': function (event) {
var $checkbox = $(event.target);
this.model.set("isOn", $checkbox.is(":checked"));
this.model.get("dispatcher").trigger("toggle", this.model.get("id"));
}
},
initialize: function (options) {
this.listenTo(this.model, "change:isOn", function (model, isOn) {
if ( isOn ) {
this.$el.find(".section").show();
this.$el.find("input").prop("checked", true);
}
else {
this.$el.find(".section").hide();
this.$el.find("input").prop("checked", false);
}
});
this.listenTo(dispatcher, "toggle", function (id) {
if ( this.model.get("id") < id ) {
this.model.set("isOn", true);
}
if ( this.model.get("id") > id ) {
this.model.set("isOn", false);
}
});
},
render: function () {
this.$el.html('<div>' + this.model.get("name") + '</div><input type="checkbox"><div class="section" style="min-height:100px; background-color:grey; display:none;"></div>');
this.$el.appendTo("body");
}
});
var dispatcher = _.extend({}, Backbone.Events);
_.each([
{id: 1, name: "A", isOn: false, dispatcher: dispatcher},
{id: 2, name: "B", isOn: false, dispatcher: dispatcher},
{id: 3, name: "C", isOn: false, dispatcher: dispatcher},
{id: 4, name: "D", isOn: false, dispatcher: dispatcher},
{id: 5, name: "E", isOn: false, dispatcher: dispatcher}
], function (item) {
var view = new Section({model: new State(item)});
view.render();
});
I didn't understand the meaning of two radio.. so I used checkbox per section.. Hope this will uncover some basics of backbone.
Yes this approach will work. I recommend if you need to communicate between views to use models via events - this will generally result in better architecture (your views will be more decoupled).
You can react to the change event in the view (using the events hash) and update an attribute on a model for each group, e.g. this.model.set('termsAccepted', true/false) then as long as the other view(s) have access to this model you can react to the change event of that attribute, e.g. this.listenTo(this.model, 'change:termsAccepted', this.onTermsAcceptedChange).
There may be a very simple solution to your objective. If you monitor the radio-button state via a javascript function, then you can use that function to change a class statement for the parent div. In CSS, you can then define actions to hide or display a div based on it's class. This would only take a few lines of javascript and a few lines of CSS.
For example, this example in codepen shows a way to accomplish the hide/show for a variably sized div. The number of divs in this approach is arbitrary - you can have as many or few as you like, and the only action required of the user is to click on the header to expand or collapse the associated div. In this example, clicking on the header acts as a toggle to expand or collapse the associated div. The example is set up so that only one div is expanded at a time and clicking on a different header automatically collapses any open div so that only one div is open at a time. If you do not want that behavior, just remove the for loop in the accOff() function.
It's kinda like a choose-your-own-adventure, ya sipher_z?
I advise using the Backbone Router with route parameters storing the current state, that is, which section is currently showing.
Each component of the view should be a Backbone.View.extend({...}). Components might be Section and Radio.
On each Radio button, in HTML, put a data-go-to attribute, with a value of the section to go to next. Then, in your RadioView code, put a click event. When clicked, extract this data-go-to, and do something like location.hash = '/section/' + section to trigger your router.
Then, all your router does is hide all the Sections except the selected one whenever triggered. If there's no selection, it just shows the first one!
I'm not 100% sure of this strategy, but this is definitely "the Backbone way". Let me know if I can clear anything up.
I have a TinyMCE 4.x instance where the text should be in read only mode. But I still have some buttons that I want to have enabled. For example, one button could provide a character count for the part of the text I've selected.
But when I turn on read only mode for TinyMCE all buttons are disabled. Can I enable just my buttons while still retaining read only mode?
It's probably too late for you but other people may pass by here.
I came up by writing this function
function enableTinyMceEditorPlugin(editorId, pluginName, commandName) {
var htmlEditorDiv = document.getElementById(editorId).previousSibling;
var editor = tinymce.get(editorId);
var buttonDiv = htmlEditorDiv.querySelectorAll('.mce-i-' + pluginName.toLowerCase())[0].parentElement.parentElement;
buttonDiv.className = buttonDiv.className.replace(' mce-disabled', '');
buttonDiv.removeAttribute('aria-disabled');
buttonDiv.firstChild.onclick = function () {
editor.execCommand(commandName);
};
}
It does the trick in 2 steps:
make the button clickable (remove mce-disabled CSS class and remove the aria-disabled property)
assign the good command to the click event
And in my editor init event I call the function.
editor.on('init', function () {
if (readOnly) {
editor.setMode('readonly');
enableTinyMceEditorPlugin(htmlEditorId, 'preview', 'mcePreview');
enableTinyMceEditorPlugin(htmlEditorId, 'code', 'mceCodeEditor');
}
});
Current version of TinyMCE for which I wrote this code is 4.4.3. It may break in a future version, specifically about the selectors to get and modify the good HTML elements.
Command identifiers can be found at this page otherwise you can also find them under tinymce\plugins\PluginName\plugin(.min).js
Here is a simple way to enable your custom toolbar button and attach a click event handler inside a read only TinyMCE editor using JQUERY:
//Initialize read only Tinymce editor so that Lock button is also disabled
function initReadOnlyTinyMCE() {
tinymce.init({
selector: '#main'
, toolbar: 'myLockButton'
, body_class: 'main-div'
, content_css: 'stylesheets/index.css'
, readonly: true
, setup: function (readOnlyMain) {
readOnlyMain.addButton('myLockButton', { //Lock button is disabled because readonly is set to true
image: 'images/lock.png'
, tooltip: 'Lock Editor'
});
}
});
}
function displayReadOnlyTinyMCEwithLockButtonEnabled() {
var edContent = $('main').html();
$("#main").empty();
initReadOnlyTinyMCE(true);
tinyMCE.activeEditor.setContent(edContent);
//enable the lock button and attach a click event handler
$('[aria-label="Lock Editor"]').removeClass("mce-disabled");
$('[aria-label="Lock Editor"]').removeAttr("aria-disabled");
$('[aria-label="Lock Editor"]').attr("onclick", "LockEditor()");
}
function LockEditor() {
alert("Tiny mce editor is locked by the current user!!");
//Write your logic to lock the editor...
}
I couldn't find an easy way to do this. The simplest way is to remove the contenteditable attribute from the iframe body instead and substitute a read only toolbar set. It also means that people will still be able to copy content from the editor.
$("iframe").contents().find("body").removeAttr("contenteditable");
How about this :
editor.addButton('yourButton', {
title: 'One can Enable/disable TinyMCE',
text: "Disable",
onclick: function (ee) {
editor.setMode('readonly');
if($(ee.target).text() == "Disable"){
var theEle = $(ee.target).toggle();
var edit = editor;
var newBut = "<input type='button' style='opacity:1;color:white; background-color:orange;' value='Enable'/>";
$(newBut).prependTo($(theEle).closest("div")).click(function(e){
edit.setMode('design');
$(e.target).remove();
$(theEle).toggle();
});
}
}
});
You can try to run the code below:
$("#tinymce").contentEditable="false";
if you have more than one editors, you can use their id like below
$("#tinymce[data-id='idOfTheEditor']").contentEditable="false";
I am editing the link plugin to allow staff to select links to internal content.
I have managed to add another tab to the link plugin dialog with a text input with an onKeyup event. The idea is, when they type it will list the results below where they can select the link they want. Once selected I was just going to update the info tab with the url and protocol.
Here is my code sections from the existing link plugin:
....
....
//Should update info tab with value
function AddLink(txtLink)
{
var dialog = this.getDialog();
dialog.setValueOf('info', 'url', txtLink);
dialog.setValueOf('info', 'protocol', '');
}
//called when the user types in the search box. currently just uses text for basic testing
var searchBoxChanged = function ()
{
var dialog = this.getDialog();
var href = $(this).attr('href');
var txt = dialog.getValueOf('article', 'searchWords');
$('#searchResults').html("Test Title");
}
....
....
{
//Adds extra tab to the link plugin for custom link searching
id: 'article',
label: linkLang.article,
title: linkLang.article,
elements:
[
{
type: 'text',
id: 'searchWords',
label: linkLang.articleSearch,
style: 'height:40px',
size: 29,
onKeyUp: searchBoxChanged
},
{
type: 'html',
html: '<div id="searchResults">Please start tying to get results</div>'
}
]
}
....
....
At the moment I am just using some basic static data from the textbox. The link in creating on the page ok, but when it is clicked I get the error:
CRIPT5009: 'AddLink' is undefined
Can anyone shed some light on where I am going wrong?
In my experience, ["x" is undefined] errors quite often mean there's a syntax error or, often, something in the function does not evaluate to what you think it does.
Possibly, this.getDialog() is out of context so it doesn't return anything. Then, dialog.setValueOf() won't work.
I was asked to post this as a question on StackOverflow by http://twitter.com/jonathanjulian which was then retweeted by several other people. I already have an ugly solution, but am posting the original problem as requested.
So here's the back story. We have a massive database application that uses ExtJS exclusively for the client side view. We are using a GridPanel (Ext.grid.GridPanel) for the row view loaded from a remote store.
In each of our interfaces, we also have a FormPanel (Ext.form.FormPanel) displaying a form that allows a user to create or edit records from the GridPanel. The GridPanel columns are bound to the FormPanel form elements so that when a record is selected in the GridPanel, all of the values are populated in the form.
On each form, we have an input field for the table row ID (Primary Key) that is defined as such:
var editFormFields = [
{
fieldLabel: 'ID',
id: 'id_field',
name: 'id',
width: 100,
readOnly: true, // the user cannot change the ID, ever.
monitorValid: true
} /* other fields removed */
];
So, that is all fine and good. This works on all of our applications. When building a new interface, a requirement was made that we needed to use a third-party file storage API that provides an interface in the form of a small webpage that is loaded in an IFrame.
I placed the IFrame code inside of the html parameter of the FormPanel:
var editForm = new Ext.form.FormPanel({
html: '<div style="width:400px;"><iframe id="upload_iframe" src="no_upload.html" width="98%" height="300"></iframe></div>',
/* bunch of other parameters stripped for brevity */
});
So, whenever a user selects a record, I need to change the src attribute of the IFrame to the API URL of the service we are using. Something along the lines of http://uploadsite.com/upload?appname=whatever&id={$id_of_record_selected}
I initially went in to the id field (pasted above) and added a change listener.
var editFormFields = [
{
fieldLabel: 'ID',
id: 'id_field',
name: 'id',
width: 100,
readOnly: true, // the user cannot change the ID, ever.
monitorValid: true,
listeners: {
change: function(f,new_val) {
alert(new_val);
}
}
} /* other fields removed */
];
Nice and simple, except that it only worked when the user was focused on that form element. The rest of the time it failed to fire at all.
Frustrated that I was past a deadline and just needed it to work, I quickly implemented a decaying poller that checks the value. It's a horrible, ugly hack. But it works as expected.
I will paste my ugly dirty hack in an answer to this question.
"The GridPanel columns are bound to
the FormPanel form elements so that
when a record is selected in the
GridPanel, all of the values are
populated in the form."
As I understand it from the quote above, the rowclick event is what actually triggers the change to your form in the first place. To avoid polling, this could be the place to listen, and eventually raise to your custom change event.
Here is the ugly hack that I did to accomplish this problem:
var current_id_value = '';
var check_changes = function(offset) {
offset = offset || 100;
var id_value = document.getElementById('id_field').value || '';
if ( id_value && ( id_value != current_id_value ) ) {
current_id_value = id_value;
change_iframe(id_value);
} else {
offset = offset + 50;
if ( offset > 2500 ) {
offset = 2500;
}
setTimeout(function() { check_changes(offset); }, offset);
}
};
var change_iframe = function(id_value) {
if ( id_value ) {
document.getElementById('upload_iframe').src = 'http://api/upload.php?id=' + id_value;
} else {
document.getElementById('upload_iframe').src = 'no_upload.html';
}
setTimeout(function() { check_changes(100); }, 1500);
};
It's not pretty, but it works. All of the bosses are happy.
If you took a moment to read the source, you would see that the Ext.form.Field class only fires that change event in the onBlur function