What is the best way to shorten this code? - javascript

Using the DRY methodology, I was wondering what could be the best way this code could be shorten. It seems to me there is too much repetition in there.
function back(){
$('.back').click(function(){
if($(this).hasClass('back_3')){
$('.screen3').addClass('hidden');
$('.screen1').removeClass('hidden');
}else if ($(this).hasClass('back_2')){
$('.screen2').addClass('hidden');
$('.screen1').removeClass('hidden');
}else if($(this).hasClass('back_4')){
$('.screen4').addClass('hidden');
$('.screen3').removeClass('hidden');
}else if($(this).hasClass('back_5')){
$('.screen5').addClass('hidden');
$('.screen3').removeClass('hidden');
}else if($(this).hasClass('back_6')){
$('.screen6').addClass('hidden');
$('.screen3').removeClass('hidden');
}
});
}

Best way to DRYify this code is to use data-* attributes to link the button to what to hide/show
eg (for first if branch)
<button class="back" data-hide=".screen3" data-show=".screen1">Back_3</button>
and then this
$('.back').click(function(){
var $this = $(this);
$($this.data("hide")).addClass("hidden");
$($this.data("show")).removeClass("hidden");
});
Same handler works for any .back button with data-hide and data-show attributes.

Simpy extract the id of the class, then hide/show the respective classes:
$('.back').click(function(){
var id = this.className.split(" ").find(clss => clss.includes("back_")).split("_")[1];
$(".screen"+id).addClass("hidden");
$(".screen"+id>3?3:1).removeClass("hidden");
});

I would do something like this (not tested):
var arrScreens=[
{hC:"back_3",screenShow:".screen3",screenHide:".screen1"]},
{hC:"back_2",screenShow:".screen2",screenHide:".screen1"]},
]
function back(){
$('.back').click(function(){
var $this=$(this);
$(arrScreens).each(function(i,obj) {
if($this.hasClass(obj.hC)) {
$(obj.screenShow).addClass('hidden');
$(obj.screenHide).removeClass('hidden');
return false;
}
});
});
}

This is what I would have done in your case.
const routes = [
{id: 'back_3', hide: '.screen3', show: '.screen1' },
{id: 'back_2', hide: '.screen2', show: '.screen1' },
{id: 'back_4', hide: '.screen4', show: '.screen3' },
{id: 'back_5', hide: '.screen5', show: '.screen3' },
{id: 'back_6', hide: '.screen6', show: '.screen3' },
];
function back() {
const hiddenCls = 'hidden';
const $back = $('.back');
return $back.click(event => {
event.preventDefault();
for(const route of routes) {
const {id, hide, show} = route;
if($(event.currentTarget).hasClass(id)) {
$(hide).addClass(hiddenCls);
$(show).removeClass(hiddenCls);
break;
}
}
});
}

Related

EXT JS: How to hide the fourth tab of the item based on some if condition?

I am new to ext js and I am trying to hide the fourth tab on my screen based on certain entity condition. As, I have coded I am able to disable
(blur) the 4th Setting tab, but the hidden or hide() function is failing.
Basically, I want to hide the fourth tab in items Payment.PaymentSettingsCfg on certain condition.
Any help would really appreciate, thanks in advance.
var bsdataloded = false;
Payment.PaymentSettingsCfg = {
id: 'PaymentSettingsPanel',
title: getMsg('PaymentAdmin', 'PaymentSettingsHeader'),
xtype: 'PaymentSettingsPanels',
listeners: {
activate: function() {
if (!bsdataloded) {
this.loadSettings();
bsdataloded = true;
}
}
}
}
var hidePaymentSettingcfg = false;
debugger;
if (Payment.EntitySettings &&
Payment.EntSettings["EntSITE|Payment_SWitch"] === "Y") {
Payment.PaymentSettingsCfg.disabled = true; //working
// Payment.PaymentSettingsCfg.hidden = true;// not working, even hide() not working
hidePaymentSettingcfg = true;
}
init: function() {
Ext.QuickTips.init();
Ext.state.Manager.setProvider(new Ext.state.CookieProvider({
expires: null
}));
app = new Payment.admin.AppContainer({
id: 'main-panel',
title: Payment.getMsg('PaymentAdmin', 'PaymentConfHeader'),
el: 'bodydiv',
border: true,
layout: 'fit',
defaults: {
border: false
},
items: [{
xtype: 'tabpanel',
activeTab: 0,
width: 500,
deferredRender: false,
hidden: false,
defaults: {
border: false
},
items: [
Payment.PaymentItemCfg,
Payment.PaymentPeriodCfg,
Payment.PaymentTypeCfg,
Payment.PaymentSettingsCfg
]
}]
});
app.render();
}
};
}();
Here is the example to hide and show the tab based on if condition
i am hiding and showing the tab on checkbox checking but you can get your idea
i hope it will help you
here is the Fiddle...
Added the logic to the listeners and it worked.
listeners : {
afterrender : function(){
var testTab = this.getTabEl(3);
if (Payment.EntSettings["EntSITE|Payment_SWitch"] === "Y") {
testTab.hide();
}
}
}

Javascript functions in custom namespaces

It is possible to declare 2 more functions in main function like this ?
var jquery4u = {
init: function() {
jquery4u.countdown.show();
},
countdown: function() {
show: function() {
console.log('show');
},
hide: function() {
console.log('hide');
}
}
}
jquery4u.init();
and i receive the following error: Uncaught SyntaxError: Unexpected token ( on this line "show: function() {"
Remove the function from the right of the countdown (demo)
var jquery4u = {
init: function() {
jquery4u.countdown.show();
},
countdown: {
show: function() {
console.log('show');
},
hide: function() {
console.log('hide');
}
}
}
jquery4u.init();
Next time, use jsFiddle to make a demo and click the "JSHint" button.
Actually, none of this will work. Unless you make countdown an object or you treat its sub-functions as proper functions.
Why: Under countdown, you created an instance of object not a function.
var jquery4u = {
countdown: function() {
show = function() {
console.log('show');
}
hide = function() {
console.log('hide');
}
jquery4u.countdown.show();
}
}
The above code is a valid code so it is possible. Unfortunately it will not return anything.
The proper way to do this is in this format:
var jquery4u = {
countdown: {
show: function() {
console.log('show');
},
hide: function() {
console.log('hide');
}
}
}
This will work. You can try it out by calling:
jquery4u.countdown.show();

ng-hide & ng-show in AngularJS

Using AngularJS I want to show and hide the data related with particular id in the toggle way.
My JSON Data format is like:
$scope.things = [{
id: 1,
data: 'One',
shown: true
}, {
id: 2,
data: 'Two',
shown: false
}, {
id: 3,
data: 'Three',
shown: true
}, ];
What I want is when click on id-1 It will show text One and Hide the others, when click on id-2 will show text Two and hide others and so on.
Here is the fiddle what I tried : jsfiddle : Demo Link
i updated your code
$scope.flipMode = function (id) {
$scope.things.forEach(function (thing) {
if(id == thing.id){
thing.shown = true;
}
else{
thing.shown = false;
}
})
};
{{thing.id}}
here is the working fiddle
It should work
$scope.flipMode = function (id) {
$scope.things.forEach(function (thing) {
if(thing.id === id) {
thing.shown = true;
return;
}
thing.shown = false;
})
};
<div ng-repeat="thing in things">
{{thing.id}}
</div>
Forked working solution: http://jsfiddle.net/nypmmkrh/
Change your scope function:
$scope.flipMode = function (id) {
$scope.things.forEach(function(thing) {
if(thing.id == id) {
thing.shown = true;
} else {
thing.shown = false;
}
});
};
And pass the id in the view:
{{thing.id}}

How to turn music on and off with one button?

For my website I use the ION.sound plugin and i would like to pause a fragment and play it again with the same button. Unfortunately, Jquery's .toggle has been removed in version 1.9 and can not be used anymore. How could I turn this audiofragment on and off with the same button? This is what i have so far:
$.ionSound({
sounds: [
"track_radio"
],
path: "sounds/",
multiPlay: true,
volume: "0.8"
});
playRadio = function() {
$.ionSound.play("track_radio");
}
stopRadio = function() {
$.ionSound.stop("track_radio");
}
$("#speakers").click(function(event){
playRadio();
});
You need something to track the playing status and check it when clicked.
$.ionSound({
sounds: [
"track_radio"
],
path: "sounds/",
multiPlay: true,
volume: "0.8",
playing: false;
});
onOffRadio = function() {
$.ionSound.play("track_radio");
$.ionSound.playing = true;
}
stopRadio = function() {
$.ionSound.stop("track_radio");
$.ionSound.playing = false;
}
$("#speakers").click(function(event){
if ($.ionSound.playing) {
stopRadio();
}
else {
playRadio();
}
});
You can simply make use of the 'text' attribute of the button element.
<button id="play-pause">Play</button>
$("#play-pause").click(function() {
if($(this).text() == 'Play') {
playRadio();
$(this).text('Pause');
}
else {
pauseRadio();
$(this).text('Play');
}
});
Here's the fiddle

How to get Ext JS component from DOM element

Trying to create an inline edit form.
I have a form that looks like this:
var editPic = "<img src='https://s3.amazonaws.com/bzimages/pencil.png' alt='edit' height='24' width='24' style='margin-left: 10px;'/>";
var submitPic = "<img id='submitPic' src='https://s3.amazonaws.com/bzimages/submitPic.png' alt='edit' height='24' width='24'/>";
Ext.define('BM.view.test.Edit', {
extend: 'Ext.form.Panel',
alias: 'widget.test-edit',
layout: 'anchor',
title: 'Edit Test',
defaultType: 'displayfield',
items: [
{name: 'id', hidden: true},
{
name: 'name',
fieldLabel: 'Name',
afterSubTpl: editPic,
cls: 'editable'
},
{
name: 'nameEdit',
fieldLabel: 'Name',
xtype: 'textfield',
hidden: true,
cls: 'editMode',
allowBlank: false,
afterSubTpl: submitPic
}
]
});
The controller looks like this (a lot of events):
init: function() {
this.control({
'test-edit > displayfield': {
afterrender: this.showEditable
},
'test-edit': {
afterrender: this.formRendered
},
'test-edit > field[cls=editMode]': {
specialkey: this.editField,
blur: this.outOfFocus
}
});
},
outOfFocus: function(field, event) {
console.log('Lost focus');
this.revertToDisplayField(field);
},
revertToDisplayField: function(field) {
field.previousNode().show();
field.hide();
},
formRendered: function(form) {
Ext.get('submitPic').on('click', function (event, object) {
var field = Ext.get(object).parent().parent().parent().parent();
var cmp = Ext.ComponentQuery.query('test-edit > field[cls=editMode]');
});
},
editField: function(field, e) {
var value = field.value;
if (e.getKey() === e.ENTER) {
if (!field.allowBlank && Ext.isEmpty(value)){
console.log('Not permitted!');
} else {
var record = Ext.ComponentQuery.query('test-edit')[0].getForm().getRecord();
Ext.Ajax.request({
url: '../webapp/tests/update',
method:'Post',
params: {
id: record.getId(),
fieldName: field.name,
fieldValue: field.value
},
store: record.store,
success: function(response, t){
field.previousNode().setValue(value);
t.store.reload();
var text = response.responseText;
// process server response here
console.log('Update successful!');
}
});
}
this.revertToDisplayField(field);
} else if (e.getKey() === e.ESC) {
console.log('gave up');
this.revertToDisplayField(field);
}
},
showEditable: function(df) {
df.getEl().on("click", handleClick, this, df);
function handleClick(e, t, df){
e.preventDefault();
var editable = df.nextNode();
editable.setValue(df.getValue());
editable.show();
editable.focus();
df.hide();
}
},
I'm using the 'afterSubTpl' config to add the edit icon, and the accept icon.
I have listeners set up to listen on click events concerning them, but after they are clicked, I only have the element created by Ext.get('submitPic'). Now I want to have access to the the Ext field and form that surround it. The parent method only brings back other DOM elements. How do I connect between them? You can see what I tried in formRendered.
I hope someone can clarify this little bit for me.
Walk up the DOM tree until you find a component for the element's id:
getCmpFromEl = function(el) {
var body = Ext.getBody();
var cmp;
do {
cmp = Ext.getCmp(el.id);
el = el.parentNode;
} while (!cmp && el !== body);
return cmp;
}
Ext.Component.from(el) does exactly this since ExtJS 6.5.0, as I just learnt. Doc
Source
You can get the component by id, but only if your component and its dom element have the same id (they usually do):
Ext.getCmp(yourelement.id)
But this is not exactly good practice -- it would be better to set up your listeners so that the handler methods already have a reference to the component. For example, in your 'submitPic' component, you could define the click listener like this:
var me = this;
me.on({
click: function(arguments){
var cmp = me;
...
});

Categories

Resources